Coverage for pyTooling / CLIAbstraction / BooleanFlag.py: 97%
58 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-06 22:35 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-06 22:35 +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"""
33Boolean flags are arguments with a name and different pattern for a positive (``True``) and negative (``False``) value.
35.. seealso::
37 * For simple flags. |br|
38 |rarr| :mod:`~pyTooling.CLIAbstraction.Flag`
39 * For flags with a value. |br|
40 |rarr| :mod:`~pyTooling.CLIAbstraction.ValuedFlag`
41 * For flags that have an optional value. |br|
42 |rarr| :mod:`~pyTooling.CLIAbstraction.NamedOptionalValuedFlag`
43"""
44from typing import ClassVar, Union, Iterable, Any, Optional as Nullable, Self
46from pyTooling.Decorators import export
47from pyTooling.CLIAbstraction.Argument import NamedArgument, ValuedArgument
50@export
51class BooleanFlag(NamedArgument, ValuedArgument):
52 """
53 Class and base-class for all BooleanFlag classes, which represents a flag argument with different pattern for an
54 enabled/positive (``True``) or disabled/negative (``False``) state.
56 When deriving a subclass from an abstract BooleanFlag class, the parameters ``pattern`` and ``falsePattern`` are
57 expected.
59 **Example:**
61 * True: ``with-checks``
62 * False: ``without-checks``
63 """
65 _falsePattern: ClassVar[str]
67 def __init_subclass__(cls, *args: Any, name: Nullable[str] = None, pattern: str = "with-{0}", falsePattern: str = "without-{0}", **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 when the value is ``True``. |br|
73 Default: ``"with-{0}"``.
74 :param falsePattern: This pattern is used to format an argument when the value is ``False``. |br|
75 Default: ``"without-{0}"``.
76 :param kwargs: Any keyword argument.
77 """
78 kwargs["name"] = name
79 kwargs["pattern"] = pattern
80 super().__init_subclass__(*args, **kwargs)
81 del kwargs["name"]
82 del kwargs["pattern"]
83 ValuedArgument.__init_subclass__(*args, **kwargs)
85 cls._falsePattern = falsePattern
87 # TODO: the whole class should be marked as abstract
88 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
89 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
90 """
91 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
93 :param args: Any positional arguments.
94 :param kwargs: Any keyword arguments.
95 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
96 """
97 if cls is BooleanFlag:
98 raise TypeError(f"Class '{cls.__name__}' is abstract.")
99 return super().__new__(cls, *args, **kwargs)
101 def __init__(self, value: bool) -> None:
102 """Initializes a BooleanFlag instance.
104 :param value: Initial value set for this argument instance.
105 """
106 ValuedArgument.__init__(self, value)
108 def AsArgument(self) -> Union[str, Iterable[str]]:
109 """Convert this argument instance to a string representation with proper escaping using the matching pattern based
110 on the internal name and value.
112 :return: Formatted argument.
113 :raises ValueError: If internal name is None.
114 """
115 if self._name is None: 115 ↛ 116line 115 didn't jump to line 116 because the condition on line 115 was never true
116 raise ValueError(f"Internal value '_name' is None.")
118 pattern = self._pattern if self._value is True else self._falsePattern
119 return pattern.format(self._name)
122@export
123class ShortBooleanFlag(BooleanFlag, pattern="-with-{0}", falsePattern="-without-{0}"):
124 """Represents a :py:class:`BooleanFlag` with a single dash.
126 **Example:**
128 * True: ``-with-checks``
129 * False: ``-without-checks``
130 """
132 def __init_subclass__(cls, *args: Any, name: Nullable[str] = None, pattern: str = "-with-{0}", falsePattern: str = "-without-{0}", **kwargs: Any) -> None:
133 """
134 This method is called when a class is derived.
136 :param args: Any positional arguments.
137 :param pattern: This pattern is used to format an argument when the value is ``True``. |br|
138 Default: ``"-with-{0}"``.
139 :param falsePattern: This pattern is used to format an argument when the value is ``False``. |br|
140 Default: ``"-without-{0}"``.
141 :param kwargs: Any keyword argument.
142 """
143 kwargs["name"] = name
144 kwargs["pattern"] = pattern
145 kwargs["falsePattern"] = falsePattern
146 super().__init_subclass__(*args, **kwargs)
148 # TODO: the whole class should be marked as abstract
149 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
150 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
151 """
152 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
154 :param args: Any positional arguments.
155 :param kwargs: Any keyword arguments.
156 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
157 """
158 if cls is ShortBooleanFlag:
159 raise TypeError(f"Class '{cls.__name__}' is abstract.")
160 return super().__new__(cls, *args, **kwargs)
163@export
164class LongBooleanFlag(BooleanFlag, pattern="--with-{0}", falsePattern="--without-{0}"):
165 """Represents a :py:class:`BooleanFlag` with a double dash.
167 **Example:**
169 * True: ``--with-checks``
170 * False: ``--without-checks``
171 """
173 def __init_subclass__(cls, *args: Any, name: Nullable[str] = None, pattern: str = "--with-{0}", falsePattern: str = "--without-{0}", **kwargs: Any) -> None:
174 """
175 This method is called when a class is derived.
177 :param args: Any positional arguments.
178 :param pattern: This pattern is used to format an argument when the value is ``True``. |br|
179 Default: ``"--with-{0}"``.
180 :param falsePattern: This pattern is used to format an argument when the value is ``False``. |br|
181 Default: ``"--without-{0}"``.
182 :param kwargs: Any keyword argument.
183 """
184 kwargs["name"] = name
185 kwargs["pattern"] = pattern
186 kwargs["falsePattern"] = falsePattern
187 super().__init_subclass__(*args, **kwargs)
189 # TODO: the whole class should be marked as abstract
190 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
191 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
192 """
193 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
195 :param args: Any positional arguments.
196 :param kwargs: Any keyword arguments.
197 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
198 """
199 if cls is LongBooleanFlag:
200 raise TypeError(f"Class '{cls.__name__}' is abstract.")
201 return super().__new__(cls, *args, **kwargs)
204@export
205class WindowsBooleanFlag(BooleanFlag, pattern="/with-{0}", falsePattern="/without-{0}"):
206 """Represents a :py:class:`BooleanFlag` with a slash.
208 **Example:**
210 * True: ``/with-checks``
211 * False: ``/without-checks``
212 """
214 def __init_subclass__(cls, *args: Any, name: Nullable[str] = None, pattern: str = "/with-{0}", falsePattern: str = "/without-{0}", **kwargs: Any) -> None:
215 """
216 This method is called when a class is derived.
218 :param args: Any positional arguments.
219 :param pattern: This pattern is used to format an argument when the value is ``True``. |br|
220 Default: ``"/with-{0}"``.
221 :param falsePattern: This pattern is used to format an argument when the value is ``False``. |br|
222 Default: ``"/without-{0}"``.
223 :param kwargs: Any keyword argument.
224 """
225 kwargs["name"] = name
226 kwargs["pattern"] = pattern
227 kwargs["falsePattern"] = falsePattern
228 super().__init_subclass__(*args, **kwargs)
230 # TODO: the whole class should be marked as abstract
231 # TODO: a decorator should solve the issue and overwrite the __new__ method with that code
232 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
233 """
234 Check if this class was directly instantiated without being derived to a subclass. If so, raise an error.
236 :param args: Any positional arguments.
237 :param kwargs: Any keyword arguments.
238 :raises TypeError: When this class gets directly instantiated without being derived to a subclass.
239 """
240 if cls is WindowsBooleanFlag:
241 raise TypeError(f"Class '{cls.__name__}' is abstract.")
242 return super().__new__(cls, *args, **kwargs)