paramspecli 0.2.2__tar.gz → 0.3.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paramspecli
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Type-safe facade for the venerable argparse
5
5
  Author: jkmnt
6
6
  Requires-Python: >=3.12
@@ -64,6 +64,7 @@ ignore = [
64
64
  ]
65
65
 
66
66
  [tool.pyright]
67
+ include = ["src", "tests"]
67
68
  # typeCheckingMode = "strict"
68
69
  typeCheckingMode = "standard"
69
70
  useLibraryCodeForTypes = true
@@ -1,11 +1,12 @@
1
1
  """Type-safe facade for the venerable argparse"""
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.3.0"
4
4
 
5
5
 
6
+ from .acts import custom_action as custom_action
7
+ from .acts import version_action as version_action
6
8
  from .args import argument as argument
7
9
  from .cli import MISSING as MISSING
8
- from .cli import Action as Action
9
10
  from .cli import CallableGroup as CallableGroup
10
11
  from .cli import Command as Command
11
12
  from .cli import Config as Config
@@ -14,9 +15,9 @@ from .cli import Handler as Handler
14
15
  from .cli import Missing as Missing
15
16
  from .cli import Route as Route
16
17
  from .cli import help_action as help_action
17
- from .cli import version_action as version_action
18
+ from .const import const as const
18
19
  from .conv import PathConv as PathConv
19
- from .fake import Const as Const
20
+ from .exc import ParseAgain as ParseAgain
20
21
  from .fake import Context as Context
21
22
  from .fake import deprecated as deprecated
22
23
  from .fake import required as required
@@ -27,3 +28,6 @@ from .flags import repeated_flag as repeated_flag
27
28
  from .flags import switch as switch
28
29
  from .opts import option as option
29
30
  from .opts import repeated_option as repeated_option
31
+
32
+ # compat
33
+ Const = const
@@ -0,0 +1,159 @@
1
+ import argparse
2
+ from typing import Any, Iterable, Literal, NoReturn, overload
3
+
4
+ from . import util
5
+ from .apstub import TypeConverter
6
+ from .cli import MISSING, Action, ActionHandler, Markup, Missing
7
+
8
+
9
+ @overload
10
+ def custom_action(
11
+ *names: str,
12
+ handler: ActionHandler[str],
13
+ default: Any = None,
14
+ #
15
+ help: str | bool | Markup | None = None,
16
+ choices: Iterable[Any] | None = None,
17
+ metavar: str | tuple[str, ...] | None = None,
18
+ show_default: bool | str | None = False,
19
+ ) -> Action[str]: ...
20
+
21
+
22
+ # nargs=0
23
+ @overload
24
+ def custom_action(
25
+ *names: str,
26
+ handler: ActionHandler[None],
27
+ nargs: Literal[0],
28
+ default: Any = None,
29
+ #
30
+ help: str | bool | Markup | None = None,
31
+ show_default: bool | str | None = False,
32
+ ) -> Action[None]: ...
33
+
34
+
35
+ # nargs
36
+ @overload
37
+ def custom_action(
38
+ *names: str,
39
+ handler: ActionHandler[list[str]],
40
+ nargs: int | Literal["+", "*"],
41
+ default: Any = None,
42
+ #
43
+ help: str | bool | Markup | None = None,
44
+ choices: Iterable[Any] | None = None,
45
+ metavar: str | tuple[str, ...] | None = None,
46
+ show_default: bool | str | None = False,
47
+ ) -> Action[list[str]]: ...
48
+
49
+
50
+ # optional
51
+ @overload
52
+ def custom_action(
53
+ *names: str,
54
+ handler: ActionHandler[str],
55
+ nargs: Literal["?"],
56
+ default: Any = None,
57
+ #
58
+ help: str | bool | Markup | None = None,
59
+ choices: Iterable[Any] | None = None,
60
+ metavar: str | tuple[str, ...] | None = None,
61
+ show_default: bool | str | None = False,
62
+ ) -> Action[str | Missing]: ...
63
+
64
+
65
+ # T
66
+ @overload
67
+ def custom_action[T](
68
+ *names: str,
69
+ handler: ActionHandler[T],
70
+ type: TypeConverter[T],
71
+ default: Any = None,
72
+ #
73
+ help: str | bool | Markup | None = None,
74
+ choices: Iterable[Any] | None = None,
75
+ metavar: str | tuple[str, ...] | None = None,
76
+ show_default: bool | str | None = False,
77
+ ) -> Action[T]: ...
78
+
79
+
80
+ # T, nargs
81
+ @overload
82
+ def custom_action[T](
83
+ *names: str,
84
+ handler: ActionHandler[list[T]],
85
+ type: TypeConverter[T],
86
+ nargs: int | Literal["+", "*"],
87
+ default: Any = None,
88
+ #
89
+ help: str | bool | Markup | None = None,
90
+ choices: Iterable[Any] | None = None,
91
+ metavar: str | tuple[str, ...] | None = None,
92
+ show_default: bool | str | None = False,
93
+ ) -> Action[list[T]]: ...
94
+
95
+
96
+ # T, optional
97
+ @overload
98
+ def custom_action[T](
99
+ *names: str,
100
+ handler: ActionHandler[T | Missing],
101
+ type: TypeConverter[T],
102
+ nargs: Literal["?"],
103
+ default: Any = None,
104
+ #
105
+ help: str | bool | Markup | None = None,
106
+ choices: Iterable[Any] | None = None,
107
+ metavar: str | tuple[str, ...] | None = None,
108
+ show_default: bool | str | None = False,
109
+ ) -> Action[T | Missing]: ...
110
+
111
+
112
+ def custom_action(
113
+ *names: str,
114
+ handler: ActionHandler[Any],
115
+ type: TypeConverter[Any] | None = None,
116
+ nargs: int | Literal["+", "*", "?"] | None = None,
117
+ default: Any = None,
118
+ #
119
+ help: str | bool | Markup | None = None,
120
+ choices: Iterable[Any] | None = None,
121
+ metavar: str | tuple[str, ...] | None = None,
122
+ show_default: bool | str | None = False,
123
+ ) -> Action[Any]:
124
+ """Custom action calling the `handler` upon the option match"""
125
+ if metavar is None and choices is None and nargs != 0:
126
+ metavar = names[0].lstrip("-").upper()
127
+
128
+ return Action(
129
+ names,
130
+ handler=handler,
131
+ help=help,
132
+ conv=type,
133
+ nargs=nargs,
134
+ default=default,
135
+ const=MISSING if nargs == "?" else None,
136
+ choices=choices,
137
+ metavar=metavar,
138
+ #
139
+ hard_show_default=show_default,
140
+ soft_show_default=default is not None and default != [],
141
+ )
142
+
143
+
144
+ class _VersionPrinter:
145
+ def __init__(self, version: str):
146
+ self.version = version
147
+
148
+ def __call__(self, *, parser: argparse.ArgumentParser, **kwargs: Any) -> NoReturn:
149
+ util.echo(self.version)
150
+ parser.exit(0)
151
+
152
+
153
+ def version_action(
154
+ version: str,
155
+ *,
156
+ help: str | Markup | bool = "Show program's version number and exit",
157
+ names: tuple[str, ...] = ("--version",),
158
+ ) -> Action[None]:
159
+ return Action(names, help=help, nargs=0, handler=_VersionPrinter(version))
@@ -1,110 +1,164 @@
1
1
  from typing import Any, Iterable, Literal, overload
2
2
 
3
3
  from .apstub import TypeConverter
4
+ from .cli import Markup
4
5
  from .fake import Argument
5
6
 
6
7
 
7
- ##
8
+ # 1.
9
+ # {'type': 'None', 'nargs': 'None'}
8
10
  @overload
9
11
  def argument(
10
12
  metavar: str,
11
13
  *,
12
- help: str | Literal[False] | None = None,
14
+ #
15
+ type: None = None,
16
+ nargs: None = None,
17
+ #
18
+ help: str | bool | Markup | None = None,
13
19
  choices: Iterable[str] | None = None,
14
20
  ) -> Argument[str, str]: ...
15
21
 
16
22
 
17
- ## nargs
23
+ # 2.
24
+ # {'type': 'None', 'nargs': 'int | Literal["*", "+"]'}
18
25
  @overload
19
26
  def argument(
20
27
  metavar: str,
21
28
  *,
29
+ #
30
+ type: None = None,
22
31
  nargs: int | Literal["*", "+"],
23
- help: str | Literal[False] | None = None,
32
+ #
33
+ help: str | bool | Markup | None = None,
24
34
  choices: Iterable[str] | None = None,
25
35
  ) -> Argument[list[str], list[str]]: ...
26
36
 
27
37
 
28
- ## optional
38
+ # 3.
39
+ # {'type': 'None', 'nargs': 'Literal["?"]', 'default': 'None'}
29
40
  @overload
30
41
  def argument(
31
42
  metavar: str,
32
43
  *,
44
+ #
45
+ type: None = None,
33
46
  nargs: Literal["?"],
34
- help: str | Literal[False] | None = None,
47
+ default: None = None,
48
+ #
49
+ help: str | bool | Markup | None = None,
35
50
  choices: Iterable[str] | None = None,
36
51
  ) -> Argument[str, None]: ...
37
52
 
38
53
 
39
- ## optional, default: D
54
+ # 4.
55
+ # {'type': 'None', 'nargs': 'Literal["?"]', 'default': 'D'}
40
56
  @overload
41
57
  def argument[D](
42
58
  metavar: str,
43
59
  *,
60
+ #
61
+ type: None = None,
44
62
  nargs: Literal["?"],
45
63
  default: D,
46
- help: str | Literal[False] | None = None,
64
+ #
65
+ help: str | bool | Markup | None = None,
47
66
  choices: Iterable[str] | None = None,
48
67
  ) -> Argument[str, D]: ...
49
68
 
50
69
 
51
- ## type: T
70
+ # 5.
71
+ # {'type': 'TypeConverter[T]', 'nargs': 'None'}
52
72
  @overload
53
73
  def argument[T](
54
74
  metavar: str,
55
75
  *,
76
+ #
56
77
  type: TypeConverter[T],
57
- help: str | Literal[False] | None = None,
78
+ nargs: None = None,
79
+ #
80
+ help: str | bool | Markup | None = None,
58
81
  choices: Iterable[T] | None = None,
59
82
  ) -> Argument[T, T]: ...
60
83
 
61
84
 
62
- ## type: T, nargs
85
+ # 6.
86
+ # {'type': 'TypeConverter[T]', 'nargs': 'int | Literal["*", "+"]'}
63
87
  @overload
64
88
  def argument[T](
65
89
  metavar: str,
66
90
  *,
91
+ #
67
92
  type: TypeConverter[T],
68
93
  nargs: int | Literal["*", "+"],
69
- help: str | Literal[False] | None = None,
94
+ #
95
+ help: str | bool | Markup | None = None,
70
96
  choices: Iterable[T] | None = None,
71
97
  ) -> Argument[list[T], list[T]]: ...
72
98
 
73
99
 
74
- ## type: T, optional
100
+ # 7.
101
+ # {'type': 'TypeConverter[T]', 'nargs': 'Literal["?"', 'default': 'None'}
75
102
  @overload
76
103
  def argument[T](
77
104
  metavar: str,
78
105
  *,
106
+ #
79
107
  type: TypeConverter[T],
80
108
  nargs: Literal["?"],
81
- help: str | Literal[False] | None = None,
109
+ default: None = None,
110
+ #
111
+ help: str | bool | Markup | None = None,
82
112
  choices: Iterable[T] | None = None,
83
113
  ) -> Argument[T, None]: ...
84
114
 
85
115
 
86
- ## type: T, optional, default: str | D
87
- # default is parsed if string
116
+ # 8.
117
+ # {'type': 'TypeConverter[T]', 'nargs': 'Literal["?"', 'default': 'str'}
88
118
  @overload
89
119
  def argument[T, D](
90
120
  metavar: str,
91
121
  *,
122
+ #
92
123
  type: TypeConverter[T],
93
124
  nargs: Literal["?"],
94
- help: str | Literal[False] | None = None,
95
- default: str | D,
125
+ default: str,
126
+ #
127
+ help: str | bool | Markup | None = None,
96
128
  choices: Iterable[T] | None = None,
97
- ) -> Argument[T, T | D]: ...
129
+ ) -> Argument[T, T]: ...
130
+
131
+
132
+ # 8.
133
+ # {'type': 'TypeConverter[T]', 'nargs': 'Literal["?"', 'default': 'D'}
134
+ @overload
135
+ def argument[T, D](
136
+ metavar: str,
137
+ *,
138
+ #
139
+ type: TypeConverter[T],
140
+ nargs: Literal["?"],
141
+ default: D,
142
+ #
143
+ help: str | bool | Markup | None = None,
144
+ choices: Iterable[T] | None = None,
145
+ ) -> Argument[T, D]: ...
98
146
 
99
147
 
100
148
  def argument(
101
149
  metavar: str,
102
150
  *,
151
+ #
103
152
  type: TypeConverter[Any] | None = None,
104
- help: str | Literal[False] | None = None,
105
153
  nargs: int | Literal["*", "+", "?"] | None = None,
106
154
  default: Any | None = None,
155
+ #
156
+ help: str | bool | Markup | None = None,
107
157
  choices: Iterable[Any] | None = None,
108
158
  ) -> Argument[Any, Any]:
109
159
  """Positional argument. Always required, unless made optional via `nargs="?"`."""
160
+
161
+ if isinstance(nargs, int) and nargs <= 0:
162
+ raise ValueError("Arguments could not have nargs == 0")
163
+
110
164
  return Argument(metavar, help=help, conv=type, choices=choices, nargs=nargs, default=default)