lockss-pybasic 0.2.0.dev7__py3-none-any.whl → 0.2.0.dev8__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-dev7'
39
+ __version__ = '0.2.0-dev8'
lockss/pybasic/cliutil.py CHANGED
@@ -31,18 +31,21 @@
31
31
  """
32
32
  Command line utilities.
33
33
  """
34
-
34
+ import pathlib
35
35
  from collections.abc import Callable
36
36
  import sys
37
37
  from typing import Any, Dict, Generic, Optional, TypeVar
38
38
 
39
- from pydantic.v1 import BaseModel
39
+ import click
40
+ from pydantic.v1 import BaseModel as BaseModel1
40
41
  from pydantic_argparse import ArgumentParser
41
42
  from pydantic_argparse.argparse.actions import SubParsersAction
42
43
  from rich_argparse import RichHelpFormatter
43
44
 
45
+ from .fileutil import path
46
+
44
47
 
45
- class ActionCommand(Callable, BaseModel):
48
+ class ActionCommand(Callable, BaseModel1):
46
49
  """
47
50
  Base class for a pydantic-argparse style command.
48
51
  """
@@ -77,7 +80,7 @@ LICENSE_DESCRIPTION = 'print the software license and exit'
77
80
  VERSION_DESCRIPTION = 'print the version number and exit'
78
81
 
79
82
 
80
- BaseModelT = TypeVar('BaseModelT', bound=BaseModel)
83
+ BaseModelT = TypeVar('BaseModelT', bound=BaseModel1)
81
84
 
82
85
 
83
86
  class BaseCli(Generic[BaseModelT]):
@@ -135,11 +138,11 @@ class BaseCli(Generic[BaseModelT]):
135
138
  """
136
139
  self._dispatch_recursive(self._args, [])
137
140
 
138
- def _dispatch_recursive(self, base_model: BaseModel, subcommands: list[str]) -> None:
141
+ def _dispatch_recursive(self, base_model: BaseModel1, subcommands: list[str]) -> None:
139
142
  field_names = base_model.__class__.__fields__.keys()
140
143
  for field_name in field_names:
141
144
  field_value = getattr(base_model, field_name)
142
- if issubclass(type(field_value), BaseModel):
145
+ if issubclass(type(field_value), BaseModel1):
143
146
  self._dispatch_recursive(field_value, [*subcommands, field_name])
144
147
  return
145
148
  func_name = ''.join(f'_{sub}' for sub in subcommands)
@@ -237,7 +240,7 @@ def one_or_more(values: Dict[str, Any], *names: str):
237
240
  return values
238
241
 
239
242
 
240
- def option_name(model_cls: type[BaseModel], name: str) -> str:
243
+ def option_name(model_cls: type[BaseModel1], name: str) -> str:
241
244
  if (info := model_cls.__fields__.get(name)) is None:
242
245
  raise RuntimeError(f'invalid name: {name}')
243
246
  if alias := info.alias:
@@ -247,3 +250,63 @@ def option_name(model_cls: type[BaseModel], name: str) -> str:
247
250
 
248
251
  def _matchy_length(values: Dict[str, Any], *names: str) -> int:
249
252
  return len([name for name in names if values.get(name)])
253
+
254
+
255
+ def click_path(spec: Optional[str]) -> click.Path:
256
+ if spec is None:
257
+ spec = ''
258
+ allow_dash = False
259
+ dir_okay = True
260
+ executable = False
261
+ exists = False
262
+ file_okay = True
263
+ path_type = path
264
+ readable = True
265
+ resolve_path = False
266
+ writable = False
267
+ for char in spec:
268
+ if char == 'd':
269
+ if 'f' in spec:
270
+ raise ValueError(f'"d" and "f" are mutually exclusive: {spec}')
271
+ dir_okay = True
272
+ file_okay = False
273
+ elif char == 'e':
274
+ exists = True
275
+ elif char == 'f':
276
+ if 'd' in spec:
277
+ raise ValueError(f'"f" and "d" are mutually exclusive: {spec}')
278
+ dir_okay = False
279
+ file_okay = True
280
+ elif char == 'p':
281
+ if 'P' in spec or 's' in spec:
282
+ raise ValueError(f'"p", "P", and "s" are mutually exclusive: {spec}')
283
+ path_type = path
284
+ elif char == 'P':
285
+ if 'p' in spec or 's' in spec:
286
+ raise ValueError(f'"P", "p", and "s" are mutually exclusive: {spec}')
287
+ path_type = pathlib.Path
288
+ elif char == 'r':
289
+ readable = True
290
+ elif char == 's':
291
+ if 'p' in spec or 'P' in spec:
292
+ raise ValueError(f'"s", "p", and "P" are mutually exclusive: {spec}')
293
+ path_type = str
294
+ elif char == 'w':
295
+ writable = True
296
+ elif char == 'x':
297
+ executable = True
298
+ elif char == 'z':
299
+ resolve_path = True
300
+ elif char == '-':
301
+ allow_dash = True
302
+ else:
303
+ raise ValueError(f'unknown specification character "{char}": {spec}')
304
+ return click.Path(allow_dash=allow_dash,
305
+ dir_okay=dir_okay,
306
+ executable=executable,
307
+ exists=exists,
308
+ file_okay=file_okay,
309
+ path_type=path_type,
310
+ readable=readable,
311
+ resolve_path=resolve_path,
312
+ writable=writable)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lockss-pybasic
3
- Version: 0.2.0.dev7
3
+ Version: 0.2.0.dev8
4
4
  Summary: Basic Python utilities
5
5
  License: BSD-3-Clause
6
6
  License-File: LICENSE
@@ -8,7 +8,7 @@ Author: Thib Guicherd-Callin
8
8
  Author-email: thib@cs.stanford.edu
9
9
  Maintainer: Thib Guicherd-Callin
10
10
  Maintainer-email: thib@cs.stanford.edu
11
- Requires-Python: >=3.9,<4.0
11
+ Requires-Python: >=3.10,<4.0
12
12
  Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Framework :: Pydantic :: 2
@@ -16,7 +16,8 @@ Classifier: Intended Audience :: Developers
16
16
  Classifier: License :: OSI Approved :: BSD License
17
17
  Classifier: Programming Language :: Python
18
18
  Classifier: Topic :: Software Development :: Libraries
19
- Requires-Dist: pydantic (>=2.11.0,<3.0.0)
19
+ Requires-Dist: click-extra (>=7.5.0,<7.6.0)
20
+ Requires-Dist: pydantic (>=2.11.0,<2.12.0)
20
21
  Requires-Dist: pydantic-argparse (>=0.10.0,<0.11.0)
21
22
  Requires-Dist: rich-argparse (>=1.7.0,<1.8.0)
22
23
  Requires-Dist: tabulate (>=0.9.0,<0.10.0)
@@ -27,8 +28,8 @@ Description-Content-Type: text/x-rst
27
28
  lockss-pybasic
28
29
  ==============
29
30
 
30
- .. |RELEASE| replace:: 0.1.1
31
- .. |RELEASE_DATE| replace:: 2025-10-02
31
+ .. |RELEASE| replace:: 0.2.0-dev8
32
+ .. |RELEASE_DATE| replace:: NOT YET RELEASED
32
33
 
33
34
  **Latest release:** |RELEASE| (|RELEASE_DATE|)
34
35
 
@@ -0,0 +1,10 @@
1
+ lockss/pybasic/__init__.py,sha256=A-Y9xGDnzeI7ZG2J4KT3DCP7lDVCAzlvJ1dJD87420E,1678
2
+ lockss/pybasic/auidutil.py,sha256=o5IsRLEYROXRVS6oTO1VFtdzw7SImYSR5VcqAMHY4To,13921
3
+ lockss/pybasic/cliutil.py,sha256=vf8lxc-m6p6if5D7uWIBynIxvCiG6uZg44pHCMSiSzs,12866
4
+ lockss/pybasic/errorutil.py,sha256=XI84PScZ851_-gfoazivJ8ceieMYWaxQr7qih5ltga0,1951
5
+ lockss/pybasic/fileutil.py,sha256=BpdoPWL70xYTuhyQRBEurScRVnPQg0mX-XW8yyKPGjw,2958
6
+ lockss/pybasic/outpututil.py,sha256=8naQEZ1rM6vOFNL-9mWoK4dMBWokHmzQ0FkHaz8dyuM,2345
7
+ lockss_pybasic-0.2.0.dev8.dist-info/METADATA,sha256=xucIusdQQSQBwgcbNN2uS-6nb4hHDzBMxh_0m1_B7rs,4326
8
+ lockss_pybasic-0.2.0.dev8.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
9
+ lockss_pybasic-0.2.0.dev8.dist-info/licenses/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
10
+ lockss_pybasic-0.2.0.dev8.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- lockss/pybasic/__init__.py,sha256=zBCFbOy0mzMxX4ofmKT5pq7i2s5bTNX5ECUCi02W2M4,1678
2
- lockss/pybasic/auidutil.py,sha256=o5IsRLEYROXRVS6oTO1VFtdzw7SImYSR5VcqAMHY4To,13921
3
- lockss/pybasic/cliutil.py,sha256=BFOijSrTByMHno3bbDmtICLQfREJpD7lVGUAuzvrHBY,10697
4
- lockss/pybasic/errorutil.py,sha256=XI84PScZ851_-gfoazivJ8ceieMYWaxQr7qih5ltga0,1951
5
- lockss/pybasic/fileutil.py,sha256=BpdoPWL70xYTuhyQRBEurScRVnPQg0mX-XW8yyKPGjw,2958
6
- lockss/pybasic/outpututil.py,sha256=8naQEZ1rM6vOFNL-9mWoK4dMBWokHmzQ0FkHaz8dyuM,2345
7
- lockss_pybasic-0.2.0.dev7.dist-info/METADATA,sha256=ReyRdrU3vbGjOcdjkz4r2nqNCHXHWLK0tsN7g_2b2_s,4269
8
- lockss_pybasic-0.2.0.dev7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
9
- lockss_pybasic-0.2.0.dev7.dist-info/licenses/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
10
- lockss_pybasic-0.2.0.dev7.dist-info/RECORD,,