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

227 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-28 13:37 +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 sys import version_info # needed for versions before Python 3.11 

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

41 

42try: 

43 from pyTooling.Decorators import export, readonly 

44 from pyTooling.Common import getFullyQualifiedName 

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

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

47 

48 try: 

49 from Decorators import export, readonly 

50 from Common import getFullyQualifiedName 

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

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

53 raise ex 

54 

55 

56__all__ = ["ValueT"] 

57 

58 

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

60 

61 

62@export 

63class CommandLineArgument: 

64 """ 

65 Base-class for all *Argument* classes. 

66 

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

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

69 to specify how argument are formatted. 

70 

71 There are multiple derived formats supporting: 

72 

73 * commands |br| 

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

75 * simple names (flags) |br| 

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

77 * simple values (vlaued flags) |br| 

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

79 * names and values |br| 

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

81 * key-value pairs |br| 

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

83 """ 

84 

85 _pattern: ClassVar[str] 

86 

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

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

89 

90 :param args: Any positional arguments. 

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

92 :param kwargs: Any keyword argument. 

93 """ 

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

95 cls._pattern = pattern 

96 

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

98 if cls is CommandLineArgument: 

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

100 

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

102 return super().__new__(cls) 

103 

104 # TODO: Add property to read pattern 

105 

106 @abstractmethod 

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

108 """ 

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

110 the internal name and value. 

111 

112 :return: Formatted argument. 

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

114 """ 

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

116 

117 @abstractmethod 

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

119 """ 

120 Return a string representation of this argument instance. 

121 

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

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

124 """ 

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

126 

127 @abstractmethod 

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

129 """ 

130 Return a string representation of this argument instance. 

131 

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

133 

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

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

136 """ 

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

138 

139 

140@export 

141class ExecutableArgument(CommandLineArgument): 

142 """ 

143 Represents the executable. 

144 """ 

145 

146 _executable: Path 

147 

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

149 """ 

150 Initializes a ExecutableArgument instance. 

151 

152 :param executable: Path to the executable. 

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

154 """ 

155 if not isinstance(executable, Path): 

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

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

158 raise ex 

159 

160 self._executable = executable 

161 

162 @property 

163 def Executable(self) -> Path: 

164 """ 

165 Get the internal path to the wrapped executable. 

166 

167 :return: Internal path to the executable. 

168 """ 

169 return self._executable 

170 

171 @Executable.setter 

172 def Executable(self, value): 

173 """ 

174 Set the internal path to the wrapped executable. 

175 

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

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

178 """ 

179 if not isinstance(value, Path): 

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

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

182 raise ex 

183 

184 self._executable = value 

185 

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

187 """ 

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

189 the internal path to the wrapped executable. 

190 

191 :return: Formatted argument. 

192 """ 

193 return f"{self._executable}" 

194 

195 def __str__(self) -> str: 

196 """ 

197 Return a string representation of this argument instance. 

198 

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

200 """ 

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

202 

203 __repr__ = __str__ 

204 

205 

206@export 

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

208 """ 

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

210 """ 

211 

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

213 """ 

214 This method is called when a class is derived. 

215 

216 :param args: Any positional arguments. 

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

218 :param kwargs: Any keyword argument. 

219 """ 

220 kwargs["pattern"] = pattern 

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

222 

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

224 """ 

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

226 

227 :return: Formatted argument. 

228 """ 

229 return self._pattern 

230 

231 def __str__(self) -> str: 

232 """ 

233 Return a string representation of this argument instance. 

234 

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

236 """ 

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

238 

239 __repr__ = __str__ 

240 

241 

242@export 

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

244 """ 

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

246 """ 

247 

248 _name: ClassVar[str] 

249 

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

251 """ 

252 This method is called when a class is derived. 

253 

254 :param args: Any positional arguments. 

255 :param name: Name of the argument. 

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

257 :param kwargs: Any keyword argument. 

258 """ 

259 kwargs["pattern"] = pattern 

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

261 cls._name = name 

262 

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

264 if cls is NamedArgument: 

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

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

267 

268 @readonly 

269 def Name(self) -> str: 

270 """ 

271 Get the internal name. 

272 

273 :return: Internal name. 

274 """ 

275 return self._name 

276 

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

278 """ 

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

280 the internal name. 

281 

282 :return: Formatted argument. 

283 :raises ValueError: If internal name is None. 

284 """ 

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

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

287 

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

289 

290 def __str__(self) -> str: 

291 """ 

292 Return a string representation of this argument instance. 

293 

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

295 """ 

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

297 

298 __repr__ = __str__ 

299 

300 

301@export 

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

303 """ 

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

305 """ 

306 

307 _value: ValueT 

308 

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

310 """ 

311 This method is called when a class is derived. 

312 

313 :param args: Any positional arguments. 

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

315 :param kwargs: Any keyword argument. 

316 """ 

317 kwargs["pattern"] = pattern 

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

319 

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

321 """ 

322 Initializes a ValuedArgument instance. 

323 

324 :param value: Value to be stored internally. 

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

326 """ 

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

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

329 

330 self._value = value 

331 

332 @property 

333 def Value(self) -> ValueT: 

334 """ 

335 Get the internal value. 

336 

337 :return: Internal value. 

338 """ 

339 return self._value 

340 

341 @Value.setter 

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

343 """ 

344 Set the internal value. 

345 

346 :param value: Value to set. 

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

348 """ 

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

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

351 

352 self._value = value 

353 

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

355 """ 

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

357 the internal value. 

358 

359 :return: Formatted argument. 

360 """ 

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

362 

363 def __str__(self) -> str: 

364 """ 

365 Return a string representation of this argument instance. 

366 

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

368 """ 

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

370 

371 __repr__ = __str__ 

372 

373 

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

375 """ 

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

377 """ 

378 

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

380 """ 

381 This method is called when a class is derived. 

382 

383 :param args: Any positional arguments. 

384 :param name: Name of the argument. 

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

386 :param kwargs: Any keyword argument. 

387 """ 

388 kwargs["name"] = name 

389 kwargs["pattern"] = pattern 

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

391 del kwargs["name"] 

392 del kwargs["pattern"] 

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

394 

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

396 ValuedArgument.__init__(self, value) 

397 

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

399 """ 

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

401 the internal name and value. 

402 

403 :return: Formatted argument. 

404 :raises ValueError: If internal name is None. 

405 """ 

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

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

408 

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

410 

411 def __str__(self) -> str: 

412 """ 

413 Return a string representation of this argument instance. 

414 

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

416 """ 

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

418 

419 __repr__ = __str__ 

420 

421 

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

423 """ 

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

425 

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

427 to the executable. 

428 

429 **Example: ** 

430 

431 * `width 100`` 

432 """ 

433 

434 _valuePattern: ClassVar[str] 

435 

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

437 kwargs["name"] = name 

438 kwargs["pattern"] = pattern 

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

440 cls._valuePattern = valuePattern 

441 

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

443 if cls is NamedTupledArgument: 

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

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

446 

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

448 ValuedArgument.__init__(self, value) 

449 

450 # TODO: Add property to read value pattern 

451 

452 # @property 

453 # def ValuePattern(self) -> str: 

454 # if self._valuePattern is None: 

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

456 # 

457 # return self._valuePattern 

458 

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

460 """ 

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

462 pattern based on the internal name and value. 

463 

464 :return: Formatted argument as tuple of strings. 

465 :raises ValueError: If internal name is None. 

466 """ 

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

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

469 

470 return ( 

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

472 self._valuePattern.format(self._value) 

473 ) 

474 

475 def __str__(self) -> str: 

476 """ 

477 Return a string representation of this argument instance. 

478 

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

480 """ 

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

482 

483 def __repr__(self) -> str: 

484 """ 

485 Return a string representation of this argument instance. 

486 

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

488 """ 

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

490 

491 

492@export 

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

494 """ 

495 Represents a simple string argument. 

496 

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

498 """ 

499 

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

501 """ 

502 This method is called when a class is derived. 

503 

504 :param args: Any positional arguments. 

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

506 :param kwargs: Any keyword argument. 

507 """ 

508 kwargs["pattern"] = pattern 

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

510 

511 

512@export 

513class StringListArgument(ValuedArgument): 

514 """ 

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

516 

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

518 """ 

519 Initializes a StringListArgument instance. 

520 

521 :param values: An iterable of str instances. 

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

523 """ 

524 self._values = [] 

525 for value in values: 

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

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

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

529 raise ex 

530 

531 self._values.append(value) 

532 

533 @property 

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

535 """ 

536 Get the internal list of str objects. 

537 

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

539 """ 

540 return self._values 

541 

542 @Value.setter 

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

544 """ 

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

546 

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

548 

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

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

551 """ 

552 self._values.clear() 

553 for value in value: 

554 if not isinstance(value, str): 

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

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

557 raise ex 

558 self._values.append(value) 

559 

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

561 """ 

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

563 the internal value. 

564 

565 :return: Sequence of formatted arguments. 

566 """ 

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

568 

569 def __str__(self) -> str: 

570 """ 

571 Return a string representation of this argument instance. 

572 

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

574 """ 

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

576 

577 def __repr__(self) -> str: 

578 """ 

579 Return a string representation of this argument instance. 

580 

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

582 """ 

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

584 

585 

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

587@export 

588class PathArgument(CommandLineArgument): 

589 """ 

590 Represents a single path argument. 

591 

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

593 """ 

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

595 _path: Path 

596 

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

598 """ 

599 Initializes a PathArgument instance. 

600 

601 :param path: Path to a filesystem object. 

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

603 """ 

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

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

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

607 raise ex 

608 self._path = path 

609 

610 @property 

611 def Value(self) -> Path: 

612 """ 

613 Get the internal path object. 

614 

615 :return: Internal path object. 

616 """ 

617 return self._path 

618 

619 @Value.setter 

620 def Value(self, value: Path): 

621 """ 

622 Set the internal path object. 

623 

624 :param value: Value to set. 

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

626 """ 

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

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

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

630 raise ex 

631 

632 self._path = value 

633 

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

635 """ 

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

637 the internal value. 

638 

639 :return: Formatted argument. 

640 """ 

641 return f"{self._path}" 

642 

643 def __str__(self) -> str: 

644 """ 

645 Return a string representation of this argument instance. 

646 

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

648 """ 

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

650 

651 __repr__ = __str__ 

652 

653 

654@export 

655class PathListArgument(CommandLineArgument): 

656 """ 

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

658 """ 

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

660 _paths: List[Path] 

661 

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

663 """ 

664 Initializes a PathListArgument instance. 

665 

666 :param paths: An iterable os Path instances. 

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

668 """ 

669 self._paths = [] 

670 for path in paths: 

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

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

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

674 raise ex 

675 

676 self._paths.append(path) 

677 

678 @property 

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

680 """ 

681 Get the internal list of path objects. 

682 

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

684 """ 

685 return self._paths 

686 

687 @Value.setter 

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

689 """ 

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

691 

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

693 

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

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

696 """ 

697 self._paths.clear() 

698 for path in value: 

699 if not isinstance(path, Path): 

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

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

702 raise ex 

703 self._paths.append(path) 

704 

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

706 """ 

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

708 the internal value. 

709 

710 :return: Sequence of formatted arguments. 

711 """ 

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

713 

714 def __str__(self) -> str: 

715 """ 

716 Return a string representation of this argument instance. 

717 

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

719 """ 

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

721 

722 def __repr__(self) -> str: 

723 """ 

724 Return a string representation of this argument instance. 

725 

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

727 """ 

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