Coverage for pyTooling / CLIAbstraction / ValuedFlagList.py: 97%
63 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-07 17:18 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-07 17:18 +0000
1# ==================================================================================================================== #
2# _____ _ _ ____ _ ___ _ _ _ _ _ #
3# _ __ _ |_ _|__ ___ | (_)_ __ __ _ / ___| | |_ _| / \ | |__ ___| |_ _ __ __ _ ___| |_(_) ___ _ __ #
4# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` || | | | | | / _ \ | '_ \/ __| __| '__/ _` |/ __| __| |/ _ \| '_ \ #
5# | |_) | |_| || | (_) | (_) | | | | | | (_| || |___| |___ | | / ___ \| |_) \__ \ |_| | | (_| | (__| |_| | (_) | | | | #
6# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)____|_____|___/_/ \_\_.__/|___/\__|_| \__,_|\___|\__|_|\___/|_| |_| #
7# |_| |___/ |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2026 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"""
33List of valued flags are argument lists where each item is a valued flag (See
34:mod:`~pyTooling.CLIAbstraction.ValuedFlag.ValuedFlag`).
36Each list item gets translated into a ``***ValuedFlag``, with the same flag name, but differing values.
38.. seealso::
40 * For single valued flags. |br|
41 |rarr| :mod:`~pyTooling.CLIAbstraction.ValuedFlag`
42 * For list of strings. |br|
43 |rarr| :mod:`~pyTooling.CLIAbstraction.Argument.StringListArgument`
44 * For list of paths. |br|
45 |rarr| :mod:`~pyTooling.CLIAbstraction.Argument.PathListArgument`
46"""
47from typing import List, Union, Iterable, cast, Any, Self
49from pyTooling.Decorators import export
50from pyTooling.Common import getFullyQualifiedName
51from pyTooling.CLIAbstraction.Argument import ValueT, NamedAndValuedArgument
54@export
55class ValuedFlagList(NamedAndValuedArgument, pattern="{0}={1}"):
56 """
57 Class and base-class for all ValuedFlagList classes, which represents a list of valued flags.
59 Each list element gets translated to a valued flag using the pattern for formatting.
60 See :mod:`~pyTooling.CLIAbstraction.ValuedFlag` for more details on valued flags.
62 **Example:**
64 * ``file=file1.log file=file2.log``
65 """
67 def __init_subclass__(cls, *args: Any, pattern: str = "{0}={1}", **kwargs: Any) -> None:
68 """
69 This method is called when a class is derived.
71 :param args: Any positional arguments.
72 :param pattern: This pattern is used to format an argument. |br|
73 Default: ``"{0}={1}"``.
74 :param kwargs: Any keyword argument.
75 """
76 kwargs["pattern"] = pattern
77 super().__init_subclass__(*args, **kwargs)
79 # TODO: the whole class should be marked as abstract
80 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
81 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
82 """
83 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
85 :param args: Any positional arguments.
86 :param kwargs: Any keyword arguments.
87 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
88 """
89 if cls is ValuedFlagList:
90 raise TypeError(f"Class '{cls.__name__}' is abstract.")
91 return super().__new__(cls, *args, **kwargs)
93 def __init__(self, value: List[ValueT]) -> None:
94 super().__init__(list(value))
96 @property
97 def Value(self) -> List[str]:
98 """
99 Get the internal value.
101 :return: Internal value.
102 """
103 return self._value
105 @Value.setter
106 def Value(self, values: Iterable[str]) -> None:
107 """
108 Set the internal value.
110 :param values: List of values to set.
111 :raises ValueError: If a list element is not o type :class:`str`.
112 """
113 innerList = cast(list, self._value)
114 innerList.clear()
115 for value in values:
116 if not isinstance(value, str):
117 ex = TypeError(f"Value contains elements which are not of type 'str'.")
118 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
119 raise ex
120 innerList.append(value)
122 def AsArgument(self) -> Union[str, Iterable[str]]:
123 if self._name is None: 123 ↛ 124line 123 didn't jump to line 124 because the condition on line 123 was never true
124 raise ValueError(f"") # XXX: add message
126 return [self._pattern.format(self._name, value) for value in self._value]
128 def __str__(self) -> str:
129 """
130 Return a string representation of this argument instance.
132 :return: Space separated sequence of arguments formatted and each enclosed in double quotes.
133 """
134 return " ".join([f"\"{value}\"" for value in self.AsArgument()])
136 def __repr__(self) -> str:
137 """
138 Return a string representation of this argument instance.
140 :return: Comma separated sequence of arguments formatted and each enclosed in double quotes.
141 """
142 return ", ".join([f"\"{value}\"" for value in self.AsArgument()])
145@export
146class ShortValuedFlagList(ValuedFlagList, pattern="-{0}={1}"):
147 """
148 Represents a :py:class:`ValuedFlagArgument` with a single dash.
150 **Example:**
152 * ``-file=file1.log -file=file2.log``
153 """
155 def __init_subclass__(cls, *args: Any, pattern: str = "-{0}={1}", **kwargs: Any) -> None:
156 """
157 This method is called when a class is derived.
159 :param args: Any positional arguments.
160 :param pattern: This pattern is used to format an argument. |br|
161 Default: ``"-{0}={1}"``.
162 :param kwargs: Any keyword argument.
163 """
164 kwargs["pattern"] = pattern
165 super().__init_subclass__(*args, **kwargs)
167 # TODO: the whole class should be marked as abstract
168 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
169 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
170 """
171 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
173 :param args: Any positional arguments.
174 :param kwargs: Any keyword arguments.
175 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
176 """
177 if cls is ShortValuedFlagList:
178 raise TypeError(f"Class '{cls.__name__}' is abstract.")
179 return super().__new__(cls, *args, **kwargs)
182@export
183class LongValuedFlagList(ValuedFlagList, pattern="--{0}={1}"):
184 """
185 Represents a :py:class:`ValuedFlagArgument` with a double dash.
187 **Example:**
189 * ``--file=file1.log --file=file2.log``
190 """
192 def __init_subclass__(cls, *args: Any, pattern: str = "--{0}={1}", **kwargs: Any) -> None:
193 """
194 This method is called when a class is derived.
196 :param args: Any positional arguments.
197 :param pattern: This pattern is used to format an argument. |br|
198 Default: ``"--{0}={1}"``.
199 :param kwargs: Any keyword argument.
200 """
201 kwargs["pattern"] = pattern
202 super().__init_subclass__(*args, **kwargs)
204 # TODO: the whole class should be marked as abstract
205 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
206 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
207 """
208 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
210 :param args: Any positional arguments.
211 :param kwargs: Any keyword arguments.
212 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
213 """
214 if cls is LongValuedFlagList:
215 raise TypeError(f"Class '{cls.__name__}' is abstract.")
216 return super().__new__(cls, *args, **kwargs)
219@export
220class WindowsValuedFlagList(ValuedFlagList, pattern="/{0}:{1}"):
221 """
222 Represents a :py:class:`ValuedFlagArgument` with a single slash.
224 **Example:**
226 * ``/file:file1.log /file:file2.log``
227 """
229 # TODO: Is it possible to copy the doc-string from super?
230 def __init_subclass__(cls, *args: Any, pattern: str = "/{0}:{1}", **kwargs: Any) -> None:
231 """
232 This method is called when a class is derived.
234 :param args: Any positional arguments.
235 :param pattern: This pattern is used to format an argument. |br|
236 Default: ``"/{0}:{1}"``.
237 :param kwargs: Any keyword argument.
238 """
239 kwargs["pattern"] = pattern
240 super().__init_subclass__(*args, **kwargs)
242 # TODO: the whole class should be marked as abstract
243 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
244 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
245 """
246 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
248 :param args: Any positional arguments.
249 :param kwargs: Any keyword arguments.
250 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
251 """
252 if cls is WindowsValuedFlagList:
253 raise TypeError(f"Class '{cls.__name__}' is abstract.")
254 return super().__new__(cls, *args, **kwargs)