Coverage for pyTooling / CLIAbstraction / Argument.py: 89%

226 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-21 22:22 +0000

1# ==================================================================================================================== # 

2# _____ _ _ ____ _ ___ _ _ _ _ _ # 

3# _ __ _ |_ _|__ ___ | (_)_ __ __ _ / ___| | |_ _| / \ | |__ ___| |_ _ __ __ _ ___| |_(_) ___ _ __ # 

4# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` || | | | | | / _ \ | '_ \/ __| __| '__/ _` |/ __| __| |/ _ \| '_ \ # 

5# | |_) | |_| || | (_) | (_) | | | | | | (_| || |___| |___ | | / ___ \| |_) \__ \ |_| | | (_| | (__| |_| | (_) | | | | # 

6# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)____|_____|___/_/ \_\_.__/|___/\__|_| \__,_|\___|\__|_|\___/|_| |_| # 

7# |_| |___/ |___/ # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany # 

15# Copyright 2014-2016 Technische Universität Dresden - Germany, Chair of VLSI-Design, Diagnostics and Architecture # 

16# # 

17# Licensed under the Apache License, Version 2.0 (the "License"); # 

18# you may not use this file except in compliance with the License. # 

19# You may obtain a copy of the License at # 

20# # 

21# http://www.apache.org/licenses/LICENSE-2.0 # 

22# # 

23# Unless required by applicable law or agreed to in writing, software # 

24# distributed under the License is distributed on an "AS IS" BASIS, # 

25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

26# See the License for the specific language governing permissions and # 

27# limitations under the License. # 

28# # 

29# SPDX-License-Identifier: Apache-2.0 # 

30# ==================================================================================================================== # 

31# 

32""" 

33This module implements command line arguments without prefix character(s). 

34 

35 

36""" 

37from abc import abstractmethod 

38from pathlib import Path 

39from typing import ClassVar, List, Union, Iterable, TypeVar, Generic, Any, Optional as Nullable 

40 

41try: 

42 from pyTooling.Decorators import export, readonly 

43 from pyTooling.Common import getFullyQualifiedName 

44except (ImportError, ModuleNotFoundError): # pragma: no cover 

45 print("[pyTooling.Versioning] Could not import from 'pyTooling.*'!") 

46 

47 try: 

48 from Decorators import export, readonly 

49 from Common import getFullyQualifiedName 

50 except (ImportError, ModuleNotFoundError) as ex: # pragma: no cover 

51 print("[pyTooling.Versioning] Could not import directly!") 

52 raise ex 

53 

54 

55__all__ = ["ValueT"] 

56 

57 

58ValueT = TypeVar("ValueT") #: The type of value in a valued argument. 

59 

60 

61@export 

62class CommandLineArgument: 

63 """ 

64 Base-class for all *Argument* classes. 

65 

66 An argument instance can be converted via ``AsArgument`` to a single string value or a sequence of string values 

67 (tuple) usable e.g. with :class:`subprocess.Popen`. Each argument class implements at least one ``pattern`` parameter 

68 to specify how argument are formatted. 

69 

70 There are multiple derived formats supporting: 

71 

72 * commands |br| 

73 |rarr| :mod:`~pyTooling.CLIAbstraction.Command` 

74 * simple names (flags) |br| 

75 |rarr| :mod:`~pyTooling.CLIAbstraction.Flag`, :mod:`~pyTooling.CLIAbstraction.BooleanFlag` 

76 * simple values (vlaued flags) |br| 

77 |rarr| :class:`~pyTooling.CLIAbstraction.Argument.StringArgument`, :class:`~pyTooling.CLIAbstraction.Argument.PathArgument` 

78 * names and values |br| 

79 |rarr| :mod:`~pyTooling.CLIAbstraction.ValuedFlag`, :mod:`~pyTooling.CLIAbstraction.OptionalValuedFlag` 

80 * key-value pairs |br| 

81 |rarr| :mod:`~pyTooling.CLIAbstraction.NamedKeyValuePair` 

82 """ 

83 

84 _pattern: ClassVar[str] 

85 

86 def __init_subclass__(cls, *args: Any, pattern: Nullable[str] = None, **kwargs: Any): 

87 """This method is called when a class is derived. 

88 

89 :param args: Any positional arguments. 

90 :param pattern: This pattern is used to format an argument. 

91 :param kwargs: Any keyword argument. 

92 """ 

93 super().__init_subclass__(*args, **kwargs) 

94 cls._pattern = pattern 

95 

96 def __new__(cls, *args: Any, **kwargs: Any): 

97 if cls is CommandLineArgument: 

98 raise TypeError(f"Class '{cls.__name__}' is abstract.") 

99 

100 # TODO: not sure why parameters meant for __init__ do reach this level and distract __new__ from it's work 

101 return super().__new__(cls) 

102 

103 # TODO: Add property to read pattern 

104 

105 @abstractmethod 

106 def AsArgument(self) -> Union[str, Iterable[str]]: # type: ignore[empty-body] 

107 """ 

108 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

109 the internal name and value. 

110 

111 :return: Formatted argument. 

112 :raises NotImplementedError: This is an abstract method and must be overwritten by a subclass. 

113 """ 

114 raise NotImplementedError(f"Method 'AsArgument' is an abstract method and must be implemented by a subclass.") 

115 

116 @abstractmethod 

117 def __str__(self) -> str: # type: ignore[empty-body] 

118 """ 

119 Return a string representation of this argument instance. 

120 

121 :return: Argument formatted and enclosed in double quotes. 

122 :raises NotImplementedError: This is an abstract method and must be overwritten by a subclass. 

123 """ 

124 raise NotImplementedError(f"Method '__str__' is an abstract method and must be implemented by a subclass.") 

125 

126 @abstractmethod 

127 def __repr__(self) -> str: # type: ignore[empty-body] 

128 """ 

129 Return a string representation of this argument instance. 

130 

131 .. note:: By default, this method is identical to :meth:`__str__`. 

132 

133 :return: Argument formatted and enclosed in double quotes. 

134 :raises NotImplementedError: This is an abstract method and must be overwritten by a subclass. 

135 """ 

136 raise NotImplementedError(f"Method '__repr__' is an abstract method and must be implemented by a subclass.") 

137 

138 

139@export 

140class ExecutableArgument(CommandLineArgument): 

141 """ 

142 Represents the executable. 

143 """ 

144 

145 _executable: Path 

146 

147 def __init__(self, executable: Path) -> None: 

148 """ 

149 Initializes a ExecutableArgument instance. 

150 

151 :param executable: Path to the executable. 

152 :raises TypeError: If parameter 'executable' is not of type :class:`~pathlib.Path`. 

153 """ 

154 if not isinstance(executable, Path): 

155 ex = TypeError("Parameter 'executable' is not of type 'Path'.") 

156 ex.add_note(f"Got type '{getFullyQualifiedName(executable)}'.") 

157 raise ex 

158 

159 self._executable = executable 

160 

161 @property 

162 def Executable(self) -> Path: 

163 """ 

164 Get the internal path to the wrapped executable. 

165 

166 :return: Internal path to the executable. 

167 """ 

168 return self._executable 

169 

170 @Executable.setter 

171 def Executable(self, value): 

172 """ 

173 Set the internal path to the wrapped executable. 

174 

175 :param value: Value to path to the executable. 

176 :raises TypeError: If value is not of type :class:`~pathlib.Path`. 

177 """ 

178 if not isinstance(value, Path): 

179 ex = TypeError("Parameter 'value' is not of type 'Path'.") 

180 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.") 

181 raise ex 

182 

183 self._executable = value 

184 

185 def AsArgument(self) -> Union[str, Iterable[str]]: 

186 """ 

187 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

188 the internal path to the wrapped executable. 

189 

190 :return: Formatted argument. 

191 """ 

192 return f"{self._executable}" 

193 

194 def __str__(self) -> str: 

195 """ 

196 Return a string representation of this argument instance. 

197 

198 :return: Argument formatted and enclosed in double quotes. 

199 """ 

200 return f"\"{self._executable}\"" 

201 

202 __repr__ = __str__ 

203 

204 

205@export 

206class DelimiterArgument(CommandLineArgument, pattern="--"): 

207 """ 

208 Represents a delimiter symbol like ``--``. 

209 """ 

210 

211 def __init_subclass__(cls, *args: Any, pattern: str = "--", **kwargs: Any): 

212 """ 

213 This method is called when a class is derived. 

214 

215 :param args: Any positional arguments. 

216 :param pattern: This pattern is used to format an argument. Default: ``"--"``. 

217 :param kwargs: Any keyword argument. 

218 """ 

219 kwargs["pattern"] = pattern 

220 super().__init_subclass__(*args, **kwargs) 

221 

222 def AsArgument(self) -> Union[str, Iterable[str]]: 

223 """ 

224 Convert this argument instance to a string representation with proper escaping using the matching pattern. 

225 

226 :return: Formatted argument. 

227 """ 

228 return self._pattern 

229 

230 def __str__(self) -> str: 

231 """ 

232 Return a string representation of this argument instance. 

233 

234 :return: Argument formatted and enclosed in double quotes. 

235 """ 

236 return f"\"{self._pattern}\"" 

237 

238 __repr__ = __str__ 

239 

240 

241@export 

242class NamedArgument(CommandLineArgument, pattern="{0}"): 

243 """ 

244 Base-class for all command line arguments with a name. 

245 """ 

246 

247 _name: ClassVar[str] 

248 

249 def __init_subclass__(cls, *args: Any, name: Nullable[str] = None, pattern: str = "{0}", **kwargs: Any): 

250 """ 

251 This method is called when a class is derived. 

252 

253 :param args: Any positional arguments. 

254 :param name: Name of the argument. 

255 :param pattern: This pattern is used to format an argument. 

256 :param kwargs: Any keyword argument. 

257 """ 

258 kwargs["pattern"] = pattern 

259 super().__init_subclass__(*args, **kwargs) 

260 cls._name = name 

261 

262 def __new__(cls, *args: Any, **kwargs: Any): 

263 if cls is NamedArgument: 

264 raise TypeError(f"Class '{cls.__name__}' is abstract.") 

265 return super().__new__(cls, *args, **kwargs) 

266 

267 @readonly 

268 def Name(self) -> str: 

269 """ 

270 Get the internal name. 

271 

272 :return: Internal name. 

273 """ 

274 return self._name 

275 

276 def AsArgument(self) -> Union[str, Iterable[str]]: 

277 """ 

278 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

279 the internal name. 

280 

281 :return: Formatted argument. 

282 :raises ValueError: If internal name is None. 

283 """ 

284 if self._name is None: 284 ↛ 285line 284 didn't jump to line 285 because the condition on line 284 was never true

285 raise ValueError(f"Internal value '_name' is None.") 

286 

287 return self._pattern.format(self._name) 

288 

289 def __str__(self) -> str: 

290 """ 

291 Return a string representation of this argument instance. 

292 

293 :return: Argument formatted and enclosed in double quotes. 

294 """ 

295 return f"\"{self.AsArgument()}\"" 

296 

297 __repr__ = __str__ 

298 

299 

300@export 

301class ValuedArgument(CommandLineArgument, Generic[ValueT], pattern="{0}"): 

302 """ 

303 Base-class for all command line arguments with a value. 

304 """ 

305 

306 _value: ValueT 

307 

308 def __init_subclass__(cls, *args: Any, pattern: str = "{0}", **kwargs: Any): 

309 """ 

310 This method is called when a class is derived. 

311 

312 :param args: Any positional arguments. 

313 :param pattern: This pattern is used to format an argument. 

314 :param kwargs: Any keyword argument. 

315 """ 

316 kwargs["pattern"] = pattern 

317 super().__init_subclass__(*args, **kwargs) 

318 

319 def __init__(self, value: ValueT) -> None: 

320 """ 

321 Initializes a ValuedArgument instance. 

322 

323 :param value: Value to be stored internally. 

324 :raises TypeError: If parameter 'value' is None. 

325 """ 

326 if value is None: 326 ↛ 327line 326 didn't jump to line 327 because the condition on line 326 was never true

327 raise ValueError("Parameter 'value' is None.") 

328 

329 self._value = value 

330 

331 @property 

332 def Value(self) -> ValueT: 

333 """ 

334 Get the internal value. 

335 

336 :return: Internal value. 

337 """ 

338 return self._value 

339 

340 @Value.setter 

341 def Value(self, value: ValueT) -> None: 

342 """ 

343 Set the internal value. 

344 

345 :param value: Value to set. 

346 :raises ValueError: If value to set is None. 

347 """ 

348 if value is None: 348 ↛ 349line 348 didn't jump to line 349 because the condition on line 348 was never true

349 raise ValueError(f"Value to set is None.") 

350 

351 self._value = value 

352 

353 def AsArgument(self) -> Union[str, Iterable[str]]: 

354 """ 

355 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

356 the internal value. 

357 

358 :return: Formatted argument. 

359 """ 

360 return self._pattern.format(self._value) 

361 

362 def __str__(self) -> str: 

363 """ 

364 Return a string representation of this argument instance. 

365 

366 :return: Argument formatted and enclosed in double quotes. 

367 """ 

368 return f"\"{self.AsArgument()}\"" 

369 

370 __repr__ = __str__ 

371 

372 

373class NamedAndValuedArgument(NamedArgument, ValuedArgument, Generic[ValueT], pattern="{0}={1}"): 

374 """ 

375 Base-class for all command line arguments with a name and a value. 

376 """ 

377 

378 def __init_subclass__(cls, *args: Any, name: Nullable[str] = None, pattern: str = "{0}={1}", **kwargs: Any): 

379 """ 

380 This method is called when a class is derived. 

381 

382 :param args: Any positional arguments. 

383 :param name: Name of the argument. 

384 :param pattern: This pattern is used to format an argument. 

385 :param kwargs: Any keyword argument. 

386 """ 

387 kwargs["name"] = name 

388 kwargs["pattern"] = pattern 

389 super().__init_subclass__(*args, **kwargs) 

390 del kwargs["name"] 

391 del kwargs["pattern"] 

392 ValuedArgument.__init_subclass__(*args, **kwargs) 

393 

394 def __init__(self, value: ValueT) -> None: 

395 ValuedArgument.__init__(self, value) 

396 

397 def AsArgument(self) -> Union[str, Iterable[str]]: 

398 """ 

399 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

400 the internal name and value. 

401 

402 :return: Formatted argument. 

403 :raises ValueError: If internal name is None. 

404 """ 

405 if self._name is None: 405 ↛ 406line 405 didn't jump to line 406 because the condition on line 405 was never true

406 raise ValueError(f"Internal value '_name' is None.") 

407 

408 return self._pattern.format(self._name, self._value) 

409 

410 def __str__(self) -> str: 

411 """ 

412 Return a string representation of this argument instance. 

413 

414 :return: Argument formatted and enclosed in double quotes. 

415 """ 

416 return f"\"{self.AsArgument()}\"" 

417 

418 __repr__ = __str__ 

419 

420 

421class NamedTupledArgument(NamedArgument, ValuedArgument, Generic[ValueT], pattern="{0}"): 

422 """ 

423 Class and base-class for all TupleFlag classes, which represents an argument with separate value. 

424 

425 A tuple argument is a command line argument followed by a separate value. Name and value are passed as two arguments 

426 to the executable. 

427 

428 **Example: ** 

429 

430 * `width 100`` 

431 """ 

432 

433 _valuePattern: ClassVar[str] 

434 

435 def __init_subclass__(cls, *args: Any, name: Nullable[str] = None, pattern: str = "{0}", valuePattern: str = "{0}", **kwargs: Any): 

436 kwargs["name"] = name 

437 kwargs["pattern"] = pattern 

438 super().__init_subclass__(*args, **kwargs) 

439 cls._valuePattern = valuePattern 

440 

441 def __new__(cls, *args: Any, **kwargs: Any): 

442 if cls is NamedTupledArgument: 

443 raise TypeError(f"Class '{cls.__name__}' is abstract.") 

444 return super().__new__(cls, *args, **kwargs) 

445 

446 def __init__(self, value: ValueT) -> None: 

447 ValuedArgument.__init__(self, value) 

448 

449 # TODO: Add property to read value pattern 

450 

451 # @property 

452 # def ValuePattern(self) -> str: 

453 # if self._valuePattern is None: 

454 # raise ValueError(f"") # XXX: add message 

455 # 

456 # return self._valuePattern 

457 

458 def AsArgument(self) -> Union[str, Iterable[str]]: 

459 """ 

460 Convert this argument instance to a sequence of string representations with proper escaping using the matching 

461 pattern based on the internal name and value. 

462 

463 :return: Formatted argument as tuple of strings. 

464 :raises ValueError: If internal name is None. 

465 """ 

466 if self._name is None: 466 ↛ 467line 466 didn't jump to line 467 because the condition on line 466 was never true

467 raise ValueError(f"Internal value '_name' is None.") 

468 

469 return ( 

470 self._pattern.format(self._name), 

471 self._valuePattern.format(self._value) 

472 ) 

473 

474 def __str__(self) -> str: 

475 """ 

476 Return a string representation of this argument instance. 

477 

478 :return: Space separated sequence of arguments formatted and each enclosed in double quotes. 

479 """ 

480 return " ".join([f"\"{item}\"" for item in self.AsArgument()]) 

481 

482 def __repr__(self) -> str: 

483 """ 

484 Return a string representation of this argument instance. 

485 

486 :return: Comma separated sequence of arguments formatted and each enclosed in double quotes. 

487 """ 

488 return ", ".join([f"\"{item}\"" for item in self.AsArgument()]) 

489 

490 

491@export 

492class StringArgument(ValuedArgument, pattern="{0}"): 

493 """ 

494 Represents a simple string argument. 

495 

496 A list of strings is available as :class:`~pyTooling.CLIAbstraction.Argument.StringListArgument`. 

497 """ 

498 

499 def __init_subclass__(cls, *args: Any, pattern: str = "{0}", **kwargs: Any): 

500 """ 

501 This method is called when a class is derived. 

502 

503 :param args: Any positional arguments. 

504 :param pattern: This pattern is used to format an argument. 

505 :param kwargs: Any keyword argument. 

506 """ 

507 kwargs["pattern"] = pattern 

508 super().__init_subclass__(*args, **kwargs) 

509 

510 

511@export 

512class StringListArgument(ValuedArgument): 

513 """ 

514 Represents a list of string argument (:class:`~pyTooling.CLIAbstraction.Argument.StringArgument`).""" 

515 

516 def __init__(self, values: Iterable[str]) -> None: 

517 """ 

518 Initializes a StringListArgument instance. 

519 

520 :param values: An iterable of str instances. 

521 :raises TypeError: If iterable parameter 'values' contains elements not of type :class:`str`. 

522 """ 

523 self._values = [] 

524 for value in values: 

525 if not isinstance(value, str): 525 ↛ 526line 525 didn't jump to line 526 because the condition on line 525 was never true

526 ex = TypeError(f"Parameter 'values' contains elements which are not of type 'str'.") 

527 ex.add_note(f"Got type '{getFullyQualifiedName(values)}'.") 

528 raise ex 

529 

530 self._values.append(value) 

531 

532 @property 

533 def Value(self) -> List[str]: 

534 """ 

535 Get the internal list of str objects. 

536 

537 :return: Reference to the internal list of str objects. 

538 """ 

539 return self._values 

540 

541 @Value.setter 

542 def Value(self, value: Iterable[str]): 

543 """ 

544 Overwrite all elements in the internal list of str objects. 

545 

546 .. note:: The list object is not replaced, but cleared and then reused by adding the given elements in the iterable. 

547 

548 :param value: List of str objects to set. 

549 :raises TypeError: If value contains elements, which are not of type :class:`str`. 

550 """ 

551 self._values.clear() 

552 for value in value: 

553 if not isinstance(value, str): 

554 ex = TypeError(f"Value contains elements which are not of type 'str'.") 

555 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.") 

556 raise ex 

557 self._values.append(value) 

558 

559 def AsArgument(self) -> Union[str, Iterable[str]]: 

560 """ 

561 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

562 the internal value. 

563 

564 :return: Sequence of formatted arguments. 

565 """ 

566 return [f"{value}" for value in self._values] 

567 

568 def __str__(self) -> str: 

569 """ 

570 Return a string representation of this argument instance. 

571 

572 :return: Space separated sequence of arguments formatted and each enclosed in double quotes. 

573 """ 

574 return " ".join([f"\"{value}\"" for value in self.AsArgument()]) 

575 

576 def __repr__(self) -> str: 

577 """ 

578 Return a string representation of this argument instance. 

579 

580 :return: Comma separated sequence of arguments formatted and each enclosed in double quotes. 

581 """ 

582 return ", ".join([f"\"{value}\"" for value in self.AsArgument()]) 

583 

584 

585# TODO: Add option to class if path should be checked for existence 

586@export 

587class PathArgument(CommandLineArgument): 

588 """ 

589 Represents a single path argument. 

590 

591 A list of paths is available as :class:`~pyTooling.CLIAbstraction.Argument.PathListArgument`. 

592 """ 

593 # The output format can be forced to the POSIX format with :py:data:`_PosixFormat`. 

594 _path: Path 

595 

596 def __init__(self, path: Path) -> None: 

597 """ 

598 Initializes a PathArgument instance. 

599 

600 :param path: Path to a filesystem object. 

601 :raises TypeError: If parameter 'path' is not of type :class:`~pathlib.Path`. 

602 """ 

603 if not isinstance(path, Path): 603 ↛ 604line 603 didn't jump to line 604 because the condition on line 603 was never true

604 ex = TypeError("Parameter 'path' is not of type 'Path'.") 

605 ex.add_note(f"Got type '{getFullyQualifiedName(path)}'.") 

606 raise ex 

607 self._path = path 

608 

609 @property 

610 def Value(self) -> Path: 

611 """ 

612 Get the internal path object. 

613 

614 :return: Internal path object. 

615 """ 

616 return self._path 

617 

618 @Value.setter 

619 def Value(self, value: Path): 

620 """ 

621 Set the internal path object. 

622 

623 :param value: Value to set. 

624 :raises TypeError: If value is not of type :class:`~pathlib.Path`. 

625 """ 

626 if not isinstance(value, Path): 626 ↛ 627line 626 didn't jump to line 627 because the condition on line 626 was never true

627 ex = TypeError("Value is not of type 'Path'.") 

628 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.") 

629 raise ex 

630 

631 self._path = value 

632 

633 def AsArgument(self) -> Union[str, Iterable[str]]: 

634 """ 

635 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

636 the internal value. 

637 

638 :return: Formatted argument. 

639 """ 

640 return f"{self._path}" 

641 

642 def __str__(self) -> str: 

643 """ 

644 Return a string representation of this argument instance. 

645 

646 :return: Argument formatted and enclosed in double quotes. 

647 """ 

648 return f"\"{self._path}\"" 

649 

650 __repr__ = __str__ 

651 

652 

653@export 

654class PathListArgument(CommandLineArgument): 

655 """ 

656 Represents a list of path arguments (:class:`~pyTooling.CLIAbstraction.Argument.PathArgument`). 

657 """ 

658 # The output format can be forced to the POSIX format with :py:data:`_PosixFormat`. 

659 _paths: List[Path] 

660 

661 def __init__(self, paths: Iterable[Path]) -> None: 

662 """ 

663 Initializes a PathListArgument instance. 

664 

665 :param paths: An iterable os Path instances. 

666 :raises TypeError: If iterable parameter 'paths' contains elements not of type :class:`~pathlib.Path`. 

667 """ 

668 self._paths = [] 

669 for path in paths: 

670 if not isinstance(path, Path): 670 ↛ 671line 670 didn't jump to line 671 because the condition on line 670 was never true

671 ex = TypeError(f"Parameter 'paths' contains elements which are not of type 'Path'.") 

672 ex.add_note(f"Got type '{getFullyQualifiedName(path)}'.") 

673 raise ex 

674 

675 self._paths.append(path) 

676 

677 @property 

678 def Value(self) -> List[Path]: 

679 """ 

680 Get the internal list of path objects. 

681 

682 :return: Reference to the internal list of path objects. 

683 """ 

684 return self._paths 

685 

686 @Value.setter 

687 def Value(self, value: Iterable[Path]): 

688 """ 

689 Overwrite all elements in the internal list of path objects. 

690 

691 .. note:: The list object is not replaced, but cleared and then reused by adding the given elements in the iterable. 

692 

693 :param value: List of path objects to set. 

694 :raises TypeError: If value contains elements, which are not of type :class:`~pathlib.Path`. 

695 """ 

696 self._paths.clear() 

697 for path in value: 

698 if not isinstance(path, Path): 

699 ex = TypeError(f"Value contains elements which are not of type 'Path'.") 

700 ex.add_note(f"Got type '{getFullyQualifiedName(path)}'.") 

701 raise ex 

702 self._paths.append(path) 

703 

704 def AsArgument(self) -> Union[str, Iterable[str]]: 

705 """ 

706 Convert this argument instance to a string representation with proper escaping using the matching pattern based on 

707 the internal value. 

708 

709 :return: Sequence of formatted arguments. 

710 """ 

711 return [f"{path}" for path in self._paths] 

712 

713 def __str__(self) -> str: 

714 """ 

715 Return a string representation of this argument instance. 

716 

717 :return: Space separated sequence of arguments formatted and each enclosed in double quotes. 

718 """ 

719 return " ".join([f"\"{value}\"" for value in self.AsArgument()]) 

720 

721 def __repr__(self) -> str: 

722 """ 

723 Return a string representation of this argument instance. 

724 

725 :return: Comma separated sequence of arguments formatted and each enclosed in double quotes. 

726 """ 

727 return ", ".join([f"\"{value}\"" for value in self.AsArgument()])