lockss-pybasic 0.2.0.dev2__py3-none-any.whl → 0.2.0.dev3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,4 +36,4 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
36
  POSSIBILITY OF SUCH DAMAGE.
37
37
  '''.strip()
38
38
 
39
- __version__ = '0.2.0-dev2'
39
+ __version__ = '0.2.0-dev3'
lockss/pybasic/cliutil.py CHANGED
@@ -34,47 +34,50 @@ Command line utilities.
34
34
 
35
35
  from collections.abc import Callable
36
36
  import sys
37
- from typing import Any, Dict, Generic, Optional, TypeVar
37
+ from typing import Any, ClassVar, Dict, Generic, Optional, TypeVar, TYPE_CHECKING
38
38
 
39
- from pydantic.v1 import BaseModel
39
+ if TYPE_CHECKING:
40
+ from _typeshed import SupportsWrite
41
+
42
+ from pydantic.v1 import BaseModel, PrivateAttr, create_model
43
+ from pydantic.v1.fields import FieldInfo
40
44
  from pydantic_argparse import ArgumentParser
41
45
  from pydantic_argparse.argparse.actions import SubParsersAction
42
46
  from rich_argparse import RichHelpFormatter
43
47
 
44
48
 
45
- class ActionCommand(Callable, BaseModel):
46
- """
47
- Base class for a pydantic-argparse style command.
48
- """
49
- pass
49
+ class StringCommand(BaseModel):
50
50
 
51
+ def display(self, file: SupportsWrite[str]=sys.stdout) -> None:
52
+ print(getattr(self, 'display_string'), file=file)
51
53
 
52
- class StringCommand(ActionCommand):
53
- """
54
- A pydantic-argparse style command that prints a string.
54
+ @staticmethod
55
+ def make(model_name: str, option_name: str, description: str, display_string: str):
56
+ return create_model(model_name,
57
+ __base__=StringCommand,
58
+ **{option_name: (Optional[bool], FieldInfo(False, description=description)),
59
+ display_string: PrivateAttr(display_string)})
55
60
 
56
- Example of use:
57
61
 
58
- .. code-block:: python
62
+ class CopyrightCommand(StringCommand):
59
63
 
60
- class MyCliModel(BaseModel):
61
- copyright: Optional[StringCommand.type(my_copyright_string)] = Field(description=COPYRIGHT_DESCRIPTION)
64
+ @staticmethod
65
+ def make(display_string: str):
66
+ return StringCommand.make('CopyrightCommand', 'copyright', 'print the copyright and exit', display_string)
62
67
 
63
- See also the convenience constants ``COPYRIGHT_DESCRIPTION``,
64
- ``LICENSE_DESCRIPTION``, and ``VERSION_DESCRIPTION``.
65
- """
68
+
69
+ class LicenseCommand(StringCommand):
66
70
 
67
71
  @staticmethod
68
- def type(display_str: str):
69
- class _StringCommand(StringCommand):
70
- def __call__(self, file=sys.stdout, **kwargs):
71
- print(display_str, file=file)
72
- return _StringCommand
72
+ def make(display_string: str):
73
+ return StringCommand.make('LicenseCommand', 'license', 'print the software license and exit', display_string)
73
74
 
74
75
 
75
- COPYRIGHT_DESCRIPTION = 'print the copyright and exit'
76
- LICENSE_DESCRIPTION = 'print the software license and exit'
77
- VERSION_DESCRIPTION = 'print the version number and exit'
76
+ class VersionCommand(StringCommand):
77
+
78
+ @staticmethod
79
+ def make(display_string: str):
80
+ return StringCommand.make('VersionCommand', 'version', 'print the version number and exit', display_string)
78
81
 
79
82
 
80
83
  BaseModelT = TypeVar('BaseModelT', bound=BaseModel)
@@ -195,7 +198,7 @@ def at_most_one_from_enum(model_cls: type[BaseModel], values: Dict[str, Any], en
195
198
  enum_names = [field_name for field_name, model_field in model_cls.__fields__.items() if model_field.field_info.extra.get('enum') == enum_cls]
196
199
  ret = [field_name for field_name in enum_names if values.get(field_name)]
197
200
  if (length := len(ret)) > 1:
198
- raise ValueError(f'at most one of {', '.join([option_name(model_cls, enum_name) for enum_name in enum_names])} is allowed, got {length} ({', '.join([option_name(enum_name) for enum_name in ret])})')
201
+ raise ValueError(f'at most one of {', '.join([option_name(model_cls, enum_name) for enum_name in enum_names])} allowed; got {length} ({', '.join([option_name(enum_name) for enum_name in ret])})')
199
202
  return values
200
203
 
201
204
 
@@ -221,19 +224,19 @@ def get_from_enum(model_inst, enum_cls, default=None):
221
224
 
222
225
  def at_most_one(model_cls: type[BaseModel], values: Dict[str, Any], *names: str):
223
226
  if (length := _matchy_length(values, *names)) > 1:
224
- raise ValueError(f'at most one of {', '.join([option_name(model_cls, name) for name in names])} is allowed, got {length}')
227
+ raise ValueError(f'at most one of {', '.join([option_name(model_cls, name) for name in names])} allowed; got {length}')
225
228
  return values
226
229
 
227
230
 
228
231
  def exactly_one(model_cls: type[BaseModel], values: Dict[str, Any], *names: str):
229
232
  if (length := _matchy_length(values, *names)) != 1:
230
- raise ValueError(f'exactly one of {', '.join([option_name(model_cls, name) for name in names])} is required, got {length}')
233
+ raise ValueError(f'exactly one of {', '.join([option_name(model_cls, name) for name in names])} required; got {length}')
231
234
  return values
232
235
 
233
236
 
234
237
  def one_or_more(model_cls: type[BaseModel], values: Dict[str, Any], *names: str):
235
238
  if _matchy_length(values, *names) == 0:
236
- raise ValueError(f'one or more of {', '.join([option_name(model_cls, name) for name in names])} is required')
239
+ raise ValueError(f'one or more of {', '.join([option_name(model_cls, name) for name in names])} required')
237
240
  return values
238
241
 
239
242
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lockss-pybasic
3
- Version: 0.2.0.dev2
3
+ Version: 0.2.0.dev3
4
4
  Summary: Basic Python utilities
5
5
  License: BSD-3-Clause
6
6
  Author: Thib Guicherd-Callin
@@ -0,0 +1,9 @@
1
+ lockss/pybasic/__init__.py,sha256=MxiRIu7H0y8ISCRj4PtTzlNH0hPQ9wvEawdO1nMjFpA,1678
2
+ lockss/pybasic/cliutil.py,sha256=LppP6O1Ocj0d5bxtXUPShAYMOTeotQywKkaPd63xhQ0,11185
3
+ lockss/pybasic/errorutil.py,sha256=XI84PScZ851_-gfoazivJ8ceieMYWaxQr7qih5ltga0,1951
4
+ lockss/pybasic/fileutil.py,sha256=BpdoPWL70xYTuhyQRBEurScRVnPQg0mX-XW8yyKPGjw,2958
5
+ lockss/pybasic/outpututil.py,sha256=JyXKXlkaCcCGvonUvmDGRdI6PxwN5t7DPVIk64S8-2g,2345
6
+ lockss_pybasic-0.2.0.dev3.dist-info/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
7
+ lockss_pybasic-0.2.0.dev3.dist-info/METADATA,sha256=ijdZVGfvh1NBR4vHPYvUSOd02cqSbmLooDMEHZbpUAM,4247
8
+ lockss_pybasic-0.2.0.dev3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
9
+ lockss_pybasic-0.2.0.dev3.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- lockss/pybasic/__init__.py,sha256=5Oqd-wtsasL0pAV0ZY1gPORFhc5DQCAVD4eJgG0J_z8,1678
2
- lockss/pybasic/cliutil.py,sha256=oJ1j3y816i9Y6VlufP45I2h_k_bgCI51gehkPkuu_jQ,10842
3
- lockss/pybasic/errorutil.py,sha256=XI84PScZ851_-gfoazivJ8ceieMYWaxQr7qih5ltga0,1951
4
- lockss/pybasic/fileutil.py,sha256=BpdoPWL70xYTuhyQRBEurScRVnPQg0mX-XW8yyKPGjw,2958
5
- lockss/pybasic/outpututil.py,sha256=JyXKXlkaCcCGvonUvmDGRdI6PxwN5t7DPVIk64S8-2g,2345
6
- lockss_pybasic-0.2.0.dev2.dist-info/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
7
- lockss_pybasic-0.2.0.dev2.dist-info/METADATA,sha256=PTqTPK5-cGs_NNTcyO6XnsFq4_GFoWeBsYMMvgZ-MdM,4247
8
- lockss_pybasic-0.2.0.dev2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
9
- lockss_pybasic-0.2.0.dev2.dist-info/RECORD,,