omlish 0.0.0.dev148__py3-none-any.whl → 0.0.0.dev150__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.
- omlish/__about__.py +2 -2
- omlish/argparse/all.py +45 -0
- omlish/{argparse.py → argparse/cli.py} +59 -99
- omlish/check.py +49 -462
- omlish/http/__init__.py +0 -48
- omlish/http/all.py +48 -0
- omlish/{lite/http → http}/coroserver.py +11 -12
- omlish/{lite/http → http}/handlers.py +2 -1
- omlish/{lite/http → http}/parsing.py +1 -0
- omlish/{lite/http → http}/versions.py +1 -0
- omlish/io/__init__.py +0 -3
- omlish/{lite/io.py → io/buffers.py} +8 -9
- omlish/{lite → io}/fdio/corohttp.py +13 -16
- omlish/{lite → io}/fdio/handlers.py +3 -3
- omlish/lite/asyncio/subprocesses.py +9 -12
- omlish/lite/check.py +438 -75
- omlish/lite/contextmanagers.py +3 -4
- omlish/lite/inject.py +12 -16
- omlish/lite/marshal.py +7 -8
- omlish/lite/socketserver.py +2 -2
- {omlish-0.0.0.dev148.dist-info → omlish-0.0.0.dev150.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev148.dist-info → omlish-0.0.0.dev150.dist-info}/RECORD +31 -29
- /omlish/{lite/fdio → argparse}/__init__.py +0 -0
- /omlish/{lite/http → io/fdio}/__init__.py +0 -0
- /omlish/{lite → io}/fdio/kqueue.py +0 -0
- /omlish/{lite → io}/fdio/manager.py +0 -0
- /omlish/{lite → io}/fdio/pollers.py +0 -0
- {omlish-0.0.0.dev148.dist-info → omlish-0.0.0.dev150.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev148.dist-info → omlish-0.0.0.dev150.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev148.dist-info → omlish-0.0.0.dev150.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev148.dist-info → omlish-0.0.0.dev150.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
omlish/argparse/all.py
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# ruff: noqa: I001
|
2
|
+
import argparse
|
3
|
+
|
4
|
+
from .cli import ( # noqa
|
5
|
+
ArgparseArg as Arg,
|
6
|
+
argparse_arg as arg,
|
7
|
+
|
8
|
+
ArgparseCommandFn as CommandFn,
|
9
|
+
ArgparseCommand as Command,
|
10
|
+
argparse_command as command,
|
11
|
+
|
12
|
+
ArgparseCli as Cli,
|
13
|
+
)
|
14
|
+
|
15
|
+
|
16
|
+
##
|
17
|
+
|
18
|
+
|
19
|
+
SUPPRESS = argparse.SUPPRESS
|
20
|
+
|
21
|
+
OPTIONAL = argparse.OPTIONAL
|
22
|
+
ZERO_OR_MORE = argparse.ZERO_OR_MORE
|
23
|
+
ONE_OR_MORE = argparse.ONE_OR_MORE
|
24
|
+
PARSER = argparse.PARSER
|
25
|
+
REMAINDER = argparse.REMAINDER
|
26
|
+
|
27
|
+
HelpFormatter = argparse.HelpFormatter
|
28
|
+
RawDescriptionHelpFormatter = argparse.RawDescriptionHelpFormatter
|
29
|
+
RawTextHelpFormatter = argparse.RawTextHelpFormatter
|
30
|
+
ArgumentDefaultsHelpFormatter = argparse.ArgumentDefaultsHelpFormatter
|
31
|
+
|
32
|
+
MetavarTypeHelpFormatter = argparse.MetavarTypeHelpFormatter
|
33
|
+
|
34
|
+
ArgumentError = argparse.ArgumentError
|
35
|
+
ArgumentTypeError = argparse.ArgumentTypeError
|
36
|
+
|
37
|
+
Action = argparse.Action
|
38
|
+
BooleanOptionalAction = argparse.BooleanOptionalAction
|
39
|
+
SubParsersAction = argparse._SubParsersAction # noqa
|
40
|
+
|
41
|
+
FileType = argparse.FileType
|
42
|
+
|
43
|
+
Namespace = argparse.Namespace
|
44
|
+
|
45
|
+
ArgumentParser = argparse.ArgumentParser
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
# @omlish-lite
|
1
3
|
"""
|
2
4
|
TODO:
|
3
5
|
- default command
|
@@ -9,53 +11,23 @@ import functools
|
|
9
11
|
import sys
|
10
12
|
import typing as ta
|
11
13
|
|
12
|
-
from . import
|
13
|
-
from . import check
|
14
|
+
from ..lite.check import check
|
14
15
|
|
15
16
|
|
16
17
|
T = ta.TypeVar('T')
|
17
18
|
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
SUPPRESS = argparse.SUPPRESS
|
23
|
-
|
24
|
-
OPTIONAL = argparse.OPTIONAL
|
25
|
-
ZERO_OR_MORE = argparse.ZERO_OR_MORE
|
26
|
-
ONE_OR_MORE = argparse.ONE_OR_MORE
|
27
|
-
PARSER = argparse.PARSER
|
28
|
-
REMAINDER = argparse.REMAINDER
|
29
|
-
|
30
|
-
HelpFormatter = argparse.HelpFormatter
|
31
|
-
RawDescriptionHelpFormatter = argparse.RawDescriptionHelpFormatter
|
32
|
-
RawTextHelpFormatter = argparse.RawTextHelpFormatter
|
33
|
-
ArgumentDefaultsHelpFormatter = argparse.ArgumentDefaultsHelpFormatter
|
34
|
-
|
35
|
-
MetavarTypeHelpFormatter = argparse.MetavarTypeHelpFormatter
|
36
|
-
|
37
|
-
ArgumentError = argparse.ArgumentError
|
38
|
-
ArgumentTypeError = argparse.ArgumentTypeError
|
39
|
-
|
40
|
-
Action = argparse.Action
|
41
|
-
BooleanOptionalAction = argparse.BooleanOptionalAction
|
42
|
-
SubParsersAction = argparse._SubParsersAction # noqa
|
43
|
-
|
44
|
-
FileType = argparse.FileType
|
45
|
-
|
46
|
-
Namespace = argparse.Namespace
|
47
|
-
|
48
|
-
ArgumentParser = argparse.ArgumentParser
|
20
|
+
ArgparseCommandFn = ta.Callable[[], ta.Optional[int]] # ta.TypeAlias
|
49
21
|
|
50
22
|
|
51
23
|
##
|
52
24
|
|
53
25
|
|
54
26
|
@dc.dataclass(eq=False)
|
55
|
-
class
|
27
|
+
class ArgparseArg:
|
56
28
|
args: ta.Sequence[ta.Any]
|
57
29
|
kwargs: ta.Mapping[str, ta.Any]
|
58
|
-
dest: str
|
30
|
+
dest: ta.Optional[str] = None
|
59
31
|
|
60
32
|
def __get__(self, instance, owner=None):
|
61
33
|
if instance is None:
|
@@ -63,26 +35,23 @@ class Arg:
|
|
63
35
|
return getattr(instance.args, self.dest) # type: ignore
|
64
36
|
|
65
37
|
|
66
|
-
def
|
67
|
-
return
|
38
|
+
def argparse_arg(*args, **kwargs) -> ArgparseArg:
|
39
|
+
return ArgparseArg(args, kwargs)
|
68
40
|
|
69
41
|
|
70
42
|
#
|
71
43
|
|
72
44
|
|
73
|
-
CommandFn = ta.Callable[[], int | None]
|
74
|
-
|
75
|
-
|
76
45
|
@dc.dataclass(eq=False)
|
77
|
-
class
|
46
|
+
class ArgparseCommand:
|
78
47
|
name: str
|
79
|
-
fn:
|
80
|
-
args: ta.Sequence[
|
48
|
+
fn: ArgparseCommandFn
|
49
|
+
args: ta.Sequence[ArgparseArg] = () # noqa
|
81
50
|
|
82
|
-
_: dc.KW_ONLY
|
51
|
+
# _: dc.KW_ONLY
|
83
52
|
|
84
|
-
aliases: ta.Sequence[str]
|
85
|
-
parent: ta.Optional['
|
53
|
+
aliases: ta.Optional[ta.Sequence[str]] = None
|
54
|
+
parent: ta.Optional['ArgparseCommand'] = None
|
86
55
|
accepts_unknown: bool = False
|
87
56
|
|
88
57
|
def __post_init__(self) -> None:
|
@@ -95,9 +64,9 @@ class Command:
|
|
95
64
|
for a in self.aliases or []:
|
96
65
|
check_name(a)
|
97
66
|
|
98
|
-
check.callable(self.fn)
|
99
|
-
check.arg(all(isinstance(a,
|
100
|
-
check.isinstance(self.parent, (
|
67
|
+
check.arg(callable(self.fn))
|
68
|
+
check.arg(all(isinstance(a, ArgparseArg) for a in self.args))
|
69
|
+
check.isinstance(self.parent, (ArgparseCommand, type(None)))
|
101
70
|
check.isinstance(self.accepts_unknown, bool)
|
102
71
|
|
103
72
|
functools.update_wrapper(self, self.fn)
|
@@ -107,25 +76,25 @@ class Command:
|
|
107
76
|
return self
|
108
77
|
return dc.replace(self, fn=self.fn.__get__(instance, owner)) # noqa
|
109
78
|
|
110
|
-
def __call__(self, *args, **kwargs) -> int
|
79
|
+
def __call__(self, *args, **kwargs) -> ta.Optional[int]:
|
111
80
|
return self.fn(*args, **kwargs)
|
112
81
|
|
113
82
|
|
114
|
-
def
|
115
|
-
*args:
|
116
|
-
name: str
|
117
|
-
aliases: ta.Iterable[str]
|
118
|
-
parent:
|
83
|
+
def argparse_command(
|
84
|
+
*args: ArgparseArg,
|
85
|
+
name: ta.Optional[str] = None,
|
86
|
+
aliases: ta.Optional[ta.Iterable[str]] = None,
|
87
|
+
parent: ta.Optional[ArgparseCommand] = None,
|
119
88
|
accepts_unknown: bool = False,
|
120
|
-
) -> ta.Any: # ta.Callable[[
|
89
|
+
) -> ta.Any: # ta.Callable[[ArgparseCommandFn], ArgparseCommand]: # FIXME
|
121
90
|
for arg in args:
|
122
|
-
check.isinstance(arg,
|
123
|
-
check.isinstance(name, (str, None))
|
124
|
-
check.isinstance(parent, (
|
91
|
+
check.isinstance(arg, ArgparseArg)
|
92
|
+
check.isinstance(name, (str, type(None)))
|
93
|
+
check.isinstance(parent, (ArgparseCommand, type(None)))
|
125
94
|
check.not_isinstance(aliases, str)
|
126
95
|
|
127
96
|
def inner(fn):
|
128
|
-
return
|
97
|
+
return ArgparseCommand(
|
129
98
|
(name if name is not None else fn.__name__).replace('_', '-'),
|
130
99
|
fn,
|
131
100
|
args,
|
@@ -140,7 +109,7 @@ def command(
|
|
140
109
|
##
|
141
110
|
|
142
111
|
|
143
|
-
def
|
112
|
+
def _get_argparse_arg_ann_kwargs(ann: ta.Any) -> ta.Mapping[str, ta.Any]:
|
144
113
|
if ann is str:
|
145
114
|
return {}
|
146
115
|
elif ann is int:
|
@@ -153,48 +122,51 @@ def get_arg_ann_kwargs(ann: ta.Any) -> ta.Mapping[str, ta.Any]:
|
|
153
122
|
raise TypeError(ann)
|
154
123
|
|
155
124
|
|
156
|
-
class
|
157
|
-
|
125
|
+
class _ArgparseCliAnnotationBox:
|
158
126
|
def __init__(self, annotations: ta.Mapping[str, ta.Any]) -> None:
|
159
127
|
super().__init__()
|
160
128
|
self.__annotations__ = annotations # type: ignore
|
161
129
|
|
162
130
|
|
163
|
-
class
|
131
|
+
class ArgparseCli:
|
132
|
+
def __init__(self, argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
133
|
+
super().__init__()
|
134
|
+
|
135
|
+
self._argv = argv if argv is not None else sys.argv[1:]
|
164
136
|
|
165
|
-
|
166
|
-
if not bases:
|
167
|
-
return super().__new__(mcls, name, tuple(bases), dict(namespace))
|
137
|
+
self._args, self._unknown_args = self.get_parser().parse_known_args(self._argv)
|
168
138
|
|
169
|
-
|
170
|
-
|
139
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
140
|
+
super().__init_subclass__(**kwargs)
|
141
|
+
|
142
|
+
ns = cls.__dict__
|
171
143
|
|
172
144
|
objs = {}
|
173
|
-
mro =
|
174
|
-
for bns in [bcls.__dict__ for bcls in reversed(mro)] + [
|
145
|
+
mro = cls.__mro__[::-1]
|
146
|
+
for bns in [bcls.__dict__ for bcls in reversed(mro)] + [ns]:
|
175
147
|
bseen = set() # type: ignore
|
176
148
|
for k, v in bns.items():
|
177
|
-
if isinstance(v, (
|
149
|
+
if isinstance(v, (ArgparseCommand, ArgparseArg)):
|
178
150
|
check.not_in(v, bseen)
|
179
151
|
bseen.add(v)
|
180
152
|
objs[k] = v
|
181
153
|
elif k in objs:
|
182
154
|
del [k]
|
183
155
|
|
184
|
-
anns = ta.get_type_hints(
|
156
|
+
anns = ta.get_type_hints(_ArgparseCliAnnotationBox({
|
185
157
|
**{k: v for bcls in reversed(mro) for k, v in getattr(bcls, '__annotations__', {}).items()},
|
186
|
-
**
|
187
|
-
}), globalns=
|
158
|
+
**ns.get('__annotations__', {}),
|
159
|
+
}), globalns=ns.get('__globals__', {}))
|
188
160
|
|
189
|
-
if '
|
190
|
-
parser = check.isinstance(
|
161
|
+
if '_parser' in ns:
|
162
|
+
parser = check.isinstance(ns['_parser'], argparse.ArgumentParser)
|
191
163
|
else:
|
192
|
-
parser = ArgumentParser()
|
193
|
-
|
164
|
+
parser = argparse.ArgumentParser()
|
165
|
+
setattr(cls, '_parser', parser)
|
194
166
|
|
195
167
|
subparsers = parser.add_subparsers()
|
196
168
|
for att, obj in objs.items():
|
197
|
-
if isinstance(obj,
|
169
|
+
if isinstance(obj, ArgparseCommand):
|
198
170
|
if obj.parent is not None:
|
199
171
|
raise NotImplementedError
|
200
172
|
for cn in [obj.name, *(obj.aliases or [])]:
|
@@ -215,9 +187,9 @@ class _CliMeta(type):
|
|
215
187
|
cparser.add_argument(*arg.args, **arg.kwargs)
|
216
188
|
cparser.set_defaults(_cmd=obj)
|
217
189
|
|
218
|
-
elif isinstance(obj,
|
190
|
+
elif isinstance(obj, ArgparseArg):
|
219
191
|
if att in anns:
|
220
|
-
akwargs =
|
192
|
+
akwargs = _get_argparse_arg_ann_kwargs(anns[att])
|
221
193
|
obj.kwargs = {**akwargs, **obj.kwargs}
|
222
194
|
if not obj.dest:
|
223
195
|
if 'dest' in obj.kwargs:
|
@@ -229,22 +201,10 @@ class _CliMeta(type):
|
|
229
201
|
else:
|
230
202
|
raise TypeError(obj)
|
231
203
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
class Cli(metaclass=_CliMeta):
|
236
|
-
|
237
|
-
def __init__(self, argv: ta.Sequence[str] | None = None) -> None:
|
238
|
-
super().__init__()
|
239
|
-
|
240
|
-
self._argv = argv if argv is not None else sys.argv[1:]
|
241
|
-
|
242
|
-
self._args, self._unknown_args = self.get_parser().parse_known_args(self._argv)
|
243
|
-
|
244
|
-
_parser: ta.ClassVar[ArgumentParser]
|
204
|
+
_parser: ta.ClassVar[argparse.ArgumentParser]
|
245
205
|
|
246
206
|
@classmethod
|
247
|
-
def get_parser(cls) -> ArgumentParser:
|
207
|
+
def get_parser(cls) -> argparse.ArgumentParser:
|
248
208
|
return cls._parser
|
249
209
|
|
250
210
|
@property
|
@@ -252,17 +212,17 @@ class Cli(metaclass=_CliMeta):
|
|
252
212
|
return self._argv
|
253
213
|
|
254
214
|
@property
|
255
|
-
def args(self) -> Namespace:
|
215
|
+
def args(self) -> argparse.Namespace:
|
256
216
|
return self._args
|
257
217
|
|
258
218
|
@property
|
259
219
|
def unknown_args(self) -> ta.Sequence[str]:
|
260
220
|
return self._unknown_args
|
261
221
|
|
262
|
-
def _run_cmd(self, cmd:
|
222
|
+
def _run_cmd(self, cmd: ArgparseCommand) -> ta.Optional[int]:
|
263
223
|
return cmd.__get__(self, type(self))()
|
264
224
|
|
265
|
-
def __call__(self) -> int
|
225
|
+
def __call__(self) -> ta.Optional[int]:
|
266
226
|
cmd = getattr(self.args, '_cmd', None)
|
267
227
|
|
268
228
|
if self._unknown_args and not (cmd is not None and cmd.accepts_unknown):
|
@@ -270,7 +230,7 @@ class Cli(metaclass=_CliMeta):
|
|
270
230
|
if (parser := self.get_parser()).exit_on_error: # type: ignore
|
271
231
|
parser.error(msg)
|
272
232
|
else:
|
273
|
-
raise ArgumentError(None, msg)
|
233
|
+
raise argparse.ArgumentError(None, msg)
|
274
234
|
|
275
235
|
if cmd is None:
|
276
236
|
self.get_parser().print_help()
|