omlish 0.0.0.dev1__py3-none-any.whl → 0.0.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.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/__about__.py +2 -3
- omlish/argparse.py +8 -8
- omlish/asyncs/__init__.py +2 -2
- omlish/asyncs/anyio.py +64 -1
- omlish/asyncs/asyncs.py +1 -3
- omlish/asyncs/futures.py +16 -15
- omlish/c3.py +5 -5
- omlish/check.py +8 -8
- omlish/collections/__init__.py +98 -63
- omlish/collections/_abc.py +2 -0
- omlish/collections/_io_abc.py +4 -2
- omlish/collections/cache/__init__.py +1 -1
- omlish/collections/cache/descriptor.py +12 -12
- omlish/collections/cache/impl.py +27 -20
- omlish/collections/cache/types.py +1 -1
- omlish/collections/coerce.py +44 -44
- omlish/collections/frozen.py +9 -9
- omlish/collections/identity.py +4 -5
- omlish/collections/mappings.py +5 -5
- omlish/collections/ordered.py +8 -8
- omlish/collections/skiplist.py +7 -7
- omlish/collections/sorted.py +4 -4
- omlish/collections/treap.py +42 -17
- omlish/collections/treapmap.py +59 -7
- omlish/collections/unmodifiable.py +25 -24
- omlish/collections/utils.py +1 -1
- omlish/configs/flattening.py +8 -7
- omlish/configs/props.py +3 -3
- omlish/dataclasses/__init__.py +1 -1
- omlish/dataclasses/impl/__init__.py +18 -0
- omlish/dataclasses/impl/api.py +15 -24
- omlish/dataclasses/impl/as_.py +4 -4
- omlish/dataclasses/impl/exceptions.py +1 -1
- omlish/dataclasses/impl/fields.py +8 -8
- omlish/dataclasses/impl/frozen.py +2 -2
- omlish/dataclasses/impl/init.py +6 -6
- omlish/dataclasses/impl/internals.py +16 -1
- omlish/dataclasses/impl/main.py +4 -4
- omlish/dataclasses/impl/metaclass.py +2 -2
- omlish/dataclasses/impl/metadata.py +1 -1
- omlish/dataclasses/impl/order.py +2 -2
- omlish/dataclasses/impl/params.py +4 -38
- omlish/dataclasses/impl/reflect.py +1 -7
- omlish/dataclasses/impl/replace.py +1 -1
- omlish/dataclasses/impl/repr.py +24 -6
- omlish/dataclasses/impl/simple.py +2 -2
- omlish/dataclasses/impl/slots.py +2 -2
- omlish/dataclasses/impl/utils.py +7 -7
- omlish/defs.py +13 -17
- omlish/diag/procfs.py +334 -0
- omlish/diag/ps.py +47 -0
- omlish/{replserver → diag/replserver}/console.py +26 -28
- omlish/{replserver → diag/replserver}/server.py +12 -12
- omlish/dispatch/dispatch.py +14 -16
- omlish/dispatch/functions.py +1 -1
- omlish/dispatch/methods.py +6 -7
- omlish/docker.py +8 -6
- omlish/dynamic.py +13 -13
- omlish/fnpairs.py +311 -0
- omlish/graphs/dot/items.py +1 -1
- omlish/graphs/trees.py +25 -31
- omlish/inject/__init__.py +7 -7
- omlish/inject/elements.py +2 -2
- omlish/inject/exceptions.py +8 -8
- omlish/inject/impl/elements.py +4 -4
- omlish/inject/impl/injector.py +6 -6
- omlish/inject/impl/inspect.py +3 -3
- omlish/inject/impl/scopes.py +9 -9
- omlish/inject/injector.py +1 -1
- omlish/inject/providers.py +2 -2
- omlish/inject/proxy.py +5 -5
- omlish/iterators.py +62 -26
- omlish/json.py +7 -6
- omlish/lang/__init__.py +172 -112
- omlish/lang/cached.py +15 -10
- omlish/lang/classes/__init__.py +35 -24
- omlish/lang/classes/abstract.py +3 -3
- omlish/lang/classes/restrict.py +14 -14
- omlish/lang/classes/simple.py +2 -2
- omlish/lang/classes/virtual.py +5 -5
- omlish/lang/clsdct.py +2 -2
- omlish/lang/cmp.py +2 -2
- omlish/lang/contextmanagers.py +31 -25
- omlish/lang/datetimes.py +1 -1
- omlish/lang/descriptors.py +51 -6
- omlish/lang/exceptions.py +2 -0
- omlish/lang/functions.py +101 -35
- omlish/lang/imports.py +25 -30
- omlish/lang/iterables.py +2 -2
- omlish/lang/maybes.py +2 -1
- omlish/lang/objects.py +17 -11
- omlish/lang/resolving.py +1 -1
- omlish/lang/strings.py +1 -1
- omlish/lang/timeouts.py +53 -0
- omlish/lang/typing.py +5 -5
- omlish/libc.py +15 -11
- omlish/logs/_abc.py +5 -1
- omlish/logs/filters.py +2 -0
- omlish/logs/formatters.py +6 -2
- omlish/logs/utils.py +1 -1
- omlish/marshal/base.py +9 -9
- omlish/marshal/dataclasses.py +2 -2
- omlish/marshal/enums.py +2 -2
- omlish/marshal/exceptions.py +1 -1
- omlish/marshal/factories.py +10 -10
- omlish/marshal/global_.py +10 -4
- omlish/marshal/iterables.py +2 -2
- omlish/marshal/mappings.py +2 -2
- omlish/marshal/objects.py +1 -2
- omlish/marshal/optionals.py +4 -4
- omlish/marshal/polymorphism.py +4 -4
- omlish/marshal/registries.py +3 -3
- omlish/marshal/standard.py +6 -6
- omlish/marshal/utils.py +3 -3
- omlish/marshal/values.py +1 -1
- omlish/math.py +9 -9
- omlish/os.py +13 -4
- omlish/reflect.py +5 -15
- omlish/sql/__init__.py +0 -0
- omlish/sql/_abc.py +65 -0
- omlish/sql/dbs.py +90 -0
- omlish/stats.py +7 -8
- omlish/term.py +1 -1
- omlish/testing/pydevd.py +30 -12
- omlish/testing/pytest/inject/__init__.py +7 -0
- omlish/testing/pytest/inject/harness.py +24 -2
- omlish/testing/pytest/plugins/__init__.py +1 -1
- omlish/testing/pytest/plugins/pydevd.py +12 -0
- omlish/testing/pytest/plugins/switches.py +3 -3
- omlish/testing/testing.py +5 -5
- omlish/text/delimit.py +3 -6
- omlish/text/parts.py +3 -3
- omlish-0.0.0.dev3.dist-info/METADATA +31 -0
- omlish-0.0.0.dev3.dist-info/RECORD +191 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/WHEEL +1 -1
- omlish/lang/classes/test/test_abstract.py +0 -89
- omlish/lang/classes/test/test_restrict.py +0 -71
- omlish/lang/classes/test/test_simple.py +0 -58
- omlish/lang/classes/test/test_virtual.py +0 -72
- omlish/testing/pytest/plugins/pycharm.py +0 -54
- omlish-0.0.0.dev1.dist-info/METADATA +0 -17
- omlish-0.0.0.dev1.dist-info/RECORD +0 -187
- /omlish/{lang/classes/test → diag}/__init__.py +0 -0
- /omlish/{replserver → diag/replserver}/__init__.py +0 -0
- /omlish/{replserver → diag/replserver}/__main__.py +0 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/top_level.txt +0 -0
omlish/lang/objects.py
CHANGED
|
@@ -9,18 +9,22 @@ T = ta.TypeVar('T')
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def attr_repr(obj: ta.Any, *attrs: str) -> str:
|
|
12
|
-
return '
|
|
13
|
-
type(obj).__name__,
|
|
14
|
-
', '.join('%s=%r' % (attr, getattr(obj, attr)) for attr in attrs))
|
|
12
|
+
return f'{type(obj).__name__}({", ".join(f"{attr}={getattr(obj, attr)!r}" for attr in attrs)})'
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
def arg_repr(*args, **kwargs) -> str:
|
|
18
16
|
return ', '.join(*(
|
|
19
17
|
list(map(repr, args)) +
|
|
20
|
-
[f'{k}={
|
|
18
|
+
[f'{k}={v!r}' for k, v in kwargs.items()]
|
|
21
19
|
))
|
|
22
20
|
|
|
23
21
|
|
|
22
|
+
def opt_repr(obj: ta.Any) -> str | None:
|
|
23
|
+
if obj is None:
|
|
24
|
+
return None
|
|
25
|
+
return repr(obj)
|
|
26
|
+
|
|
27
|
+
|
|
24
28
|
##
|
|
25
29
|
|
|
26
30
|
|
|
@@ -28,8 +32,8 @@ def new_type(
|
|
|
28
32
|
name: str,
|
|
29
33
|
bases: ta.Sequence[ta.Any],
|
|
30
34
|
namespace: ta.Mapping[str, ta.Any],
|
|
31
|
-
**kwargs
|
|
32
|
-
) ->
|
|
35
|
+
**kwargs,
|
|
36
|
+
) -> type:
|
|
33
37
|
return types.new_class(
|
|
34
38
|
name,
|
|
35
39
|
tuple(bases),
|
|
@@ -40,12 +44,12 @@ def new_type(
|
|
|
40
44
|
|
|
41
45
|
def super_meta(
|
|
42
46
|
super_meta: ta.Any,
|
|
43
|
-
meta:
|
|
47
|
+
meta: type,
|
|
44
48
|
name: str,
|
|
45
49
|
bases: ta.Sequence[ta.Any],
|
|
46
50
|
namespace: ta.MutableMapping[str, ta.Any],
|
|
47
|
-
**kwargs
|
|
48
|
-
) ->
|
|
51
|
+
**kwargs,
|
|
52
|
+
) -> type:
|
|
49
53
|
"""Per types.new_class"""
|
|
50
54
|
resolved_bases = types.resolve_bases(bases)
|
|
51
55
|
if resolved_bases is not bases:
|
|
@@ -75,19 +79,21 @@ class SimpleProxy(ta.Generic[T]):
|
|
|
75
79
|
if instance is None:
|
|
76
80
|
return self
|
|
77
81
|
setattr(object.__getattribute__(instance, '__wrapped__'), self._attr, value)
|
|
82
|
+
return None
|
|
78
83
|
|
|
79
84
|
def __delete__(self, instance):
|
|
80
85
|
if instance is None:
|
|
81
86
|
return self
|
|
82
87
|
delattr(object.__getattribute__(instance, '__wrapped__'), self._attr)
|
|
88
|
+
return None
|
|
83
89
|
|
|
84
|
-
__wrapped_attrs__: ta.Iterable[str] =
|
|
90
|
+
__wrapped_attrs__: ta.ClassVar[ta.Iterable[str]] = ()
|
|
85
91
|
|
|
86
92
|
def __init__(self, wrapped: T) -> None:
|
|
87
93
|
super().__init__()
|
|
88
94
|
object.__setattr__(self, '__wrapped__', wrapped)
|
|
89
95
|
|
|
90
|
-
def __init_subclass__(cls, **kwargs):
|
|
96
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
91
97
|
super().__init_subclass__(**kwargs)
|
|
92
98
|
|
|
93
99
|
for attr in cls.__wrapped_attrs__:
|
omlish/lang/resolving.py
CHANGED
omlish/lang/strings.py
CHANGED
|
@@ -22,7 +22,7 @@ def camel_case(name: str) -> str:
|
|
|
22
22
|
|
|
23
23
|
def snake_case(name: str) -> str:
|
|
24
24
|
uppers: list[int | None] = [i for i, c in enumerate(name) if c.isupper()]
|
|
25
|
-
return '_'.join([name[l:r].lower() for l, r in zip([None
|
|
25
|
+
return '_'.join([name[l:r].lower() for l, r in zip([None, *uppers], [*uppers, None])]).strip('_')
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def is_dunder(name: str) -> bool:
|
omlish/lang/timeouts.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import time
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
TimeoutLike: ta.TypeAlias = ta.Union['Timeout', float]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Timeout(abc.ABC):
|
|
10
|
+
@abc.abstractmethod
|
|
11
|
+
def __call__(self) -> float:
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
|
|
14
|
+
@abc.abstractmethod
|
|
15
|
+
def or_(self, o: ta.Any) -> ta.Any:
|
|
16
|
+
raise NotImplementedError
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DeadlineTimeout(Timeout):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
deadline: float,
|
|
23
|
+
exc: type[BaseException] | BaseException = TimeoutError,
|
|
24
|
+
) -> None:
|
|
25
|
+
super().__init__()
|
|
26
|
+
self.deadline = deadline
|
|
27
|
+
self.exc = exc
|
|
28
|
+
|
|
29
|
+
def __call__(self) -> float:
|
|
30
|
+
if (rem := self.deadline - time.time()) > 0:
|
|
31
|
+
return rem
|
|
32
|
+
raise self.exc
|
|
33
|
+
|
|
34
|
+
def or_(self, o: ta.Any) -> ta.Any:
|
|
35
|
+
return self()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class InfiniteTimeout(Timeout):
|
|
39
|
+
def __call__(self) -> float:
|
|
40
|
+
return float('inf')
|
|
41
|
+
|
|
42
|
+
def or_(self, o: ta.Any) -> ta.Any:
|
|
43
|
+
return o
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def timeout(t: TimeoutLike | None) -> Timeout:
|
|
47
|
+
if t is None:
|
|
48
|
+
return InfiniteTimeout()
|
|
49
|
+
if isinstance(t, Timeout):
|
|
50
|
+
return t
|
|
51
|
+
if isinstance(t, (float, int)):
|
|
52
|
+
return DeadlineTimeout(time.time() + t)
|
|
53
|
+
raise TypeError(t)
|
omlish/lang/typing.py
CHANGED
|
@@ -12,7 +12,7 @@ import typing as ta
|
|
|
12
12
|
Ty = ta.TypeVar('Ty', bound=type)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
BytesLike: ta.TypeAlias =
|
|
15
|
+
BytesLike: ta.TypeAlias = bytes | bytearray
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
##
|
|
@@ -37,13 +37,13 @@ def _update_wrapper_no_anns(wrapper, wrapped):
|
|
|
37
37
|
return wrapper
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
def typed_lambda(ret=_MISSING, **kw):
|
|
40
|
+
def typed_lambda(ret=_MISSING, **kw): # noqa
|
|
41
41
|
def inner(fn):
|
|
42
42
|
ns = {}
|
|
43
43
|
ns['__fn'] = fn
|
|
44
44
|
proto = ['def __lam(']
|
|
45
45
|
call = ['return __fn(']
|
|
46
|
-
pkw =
|
|
46
|
+
pkw = dict(kw)
|
|
47
47
|
for i, (n, t) in enumerate(pkw.items()):
|
|
48
48
|
if i:
|
|
49
49
|
call.append(', ')
|
|
@@ -69,7 +69,7 @@ def typed_lambda(ret=_MISSING, **kw):
|
|
|
69
69
|
return inner
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
def typed_partial(obj, **kw):
|
|
72
|
+
def typed_partial(obj, **kw): # noqa
|
|
73
73
|
for k in kw:
|
|
74
74
|
if k.startswith('__'):
|
|
75
75
|
raise NameError(k)
|
|
@@ -87,6 +87,6 @@ def typed_partial(obj, **kw):
|
|
|
87
87
|
for n, p in sig.parameters.items()
|
|
88
88
|
if n not in kw
|
|
89
89
|
and p.annotation is not inspect.Signature.empty
|
|
90
|
-
}
|
|
90
|
+
},
|
|
91
91
|
)(inner)
|
|
92
92
|
return _update_wrapper_no_anns(lam, obj)
|
omlish/libc.py
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# ruff: noqa: ANN201
|
|
2
|
+
# ruff: noqa: N801
|
|
3
|
+
# ruff: noqa: N802
|
|
4
|
+
|
|
1
5
|
import ctypes as ct
|
|
2
6
|
import errno
|
|
3
7
|
import platform
|
|
@@ -37,14 +41,14 @@ def lasterr() -> tuple[int, str]:
|
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
# int raise(int sig);
|
|
40
|
-
libc._raise = libc['raise'] # type: ignore
|
|
41
|
-
libc._raise.restype = ct.c_int
|
|
42
|
-
libc._raise.argtypes = [ct.c_int]
|
|
43
|
-
_raise = libc._raise
|
|
44
|
+
libc._raise = libc['raise'] # type: ignore # noqa
|
|
45
|
+
libc._raise.restype = ct.c_int # noqa
|
|
46
|
+
libc._raise.argtypes = [ct.c_int] # noqa
|
|
47
|
+
_raise = libc._raise # noqa
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
def sigtrap() -> None:
|
|
47
|
-
libc._raise(signal.SIGTRAP)
|
|
51
|
+
libc._raise(signal.SIGTRAP) # noqa
|
|
48
52
|
|
|
49
53
|
|
|
50
54
|
##
|
|
@@ -94,7 +98,7 @@ libc.mmap.argtypes = [
|
|
|
94
98
|
ct.c_int,
|
|
95
99
|
ct.c_int,
|
|
96
100
|
ct.c_int,
|
|
97
|
-
ct.c_size_t
|
|
101
|
+
ct.c_size_t,
|
|
98
102
|
]
|
|
99
103
|
mmap = libc.mmap
|
|
100
104
|
|
|
@@ -138,7 +142,7 @@ elif DARWIN:
|
|
|
138
142
|
libc.munmap.restype = ct.c_int
|
|
139
143
|
libc.munmap.argtypes = [
|
|
140
144
|
ct.c_void_p,
|
|
141
|
-
ct.c_size_t
|
|
145
|
+
ct.c_size_t,
|
|
142
146
|
]
|
|
143
147
|
munmap = libc.munmap
|
|
144
148
|
|
|
@@ -148,7 +152,7 @@ libc.mprotect.restype = ct.c_int
|
|
|
148
152
|
libc.mprotect.argtypes = [
|
|
149
153
|
ct.c_void_p,
|
|
150
154
|
ct.c_size_t,
|
|
151
|
-
ct.c_int
|
|
155
|
+
ct.c_int,
|
|
152
156
|
]
|
|
153
157
|
mprotect = libc.mprotect
|
|
154
158
|
|
|
@@ -164,7 +168,7 @@ if LINUX:
|
|
|
164
168
|
ct.c_void_p,
|
|
165
169
|
ct.c_size_t,
|
|
166
170
|
ct.c_size_t,
|
|
167
|
-
ct.c_int
|
|
171
|
+
ct.c_int,
|
|
168
172
|
]
|
|
169
173
|
mremap = libc.mremap
|
|
170
174
|
|
|
@@ -179,7 +183,7 @@ class Mmap:
|
|
|
179
183
|
length: int,
|
|
180
184
|
*,
|
|
181
185
|
prot: int = PROT_READ | PROT_WRITE,
|
|
182
|
-
flags:
|
|
186
|
+
flags: int | None = None,
|
|
183
187
|
fd: int = -1,
|
|
184
188
|
offset: int = 0,
|
|
185
189
|
desired_base: int = 0,
|
|
@@ -205,7 +209,7 @@ class Mmap:
|
|
|
205
209
|
self._is_mapped = False
|
|
206
210
|
|
|
207
211
|
@property
|
|
208
|
-
def base(self) ->
|
|
212
|
+
def base(self) -> int | None:
|
|
209
213
|
return self._base
|
|
210
214
|
|
|
211
215
|
def __enter__(self) -> 'Mmap':
|
omlish/logs/_abc.py
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# ruff: noqa: A002
|
|
2
|
+
# ruff: noqa: N802
|
|
3
|
+
# ruff: noqa: N815
|
|
4
|
+
|
|
1
5
|
import types
|
|
2
6
|
import typing as ta
|
|
3
7
|
|
|
@@ -181,7 +185,7 @@ class Logger(Filterer, ta.Protocol):
|
|
|
181
185
|
|
|
182
186
|
def log(self, level: Level, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
183
187
|
|
|
184
|
-
def findCaller(self, stack_info: bool = False, stacklevel: int = 1) -> Caller: ...
|
|
188
|
+
def findCaller(self, stack_info: bool = False, stacklevel: int = 1) -> Caller: ...
|
|
185
189
|
|
|
186
190
|
def makeRecord(
|
|
187
191
|
self,
|
omlish/logs/filters.py
CHANGED
omlish/logs/formatters.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
# ruff: noqa: ANN201
|
|
2
|
+
# ruff: noqa: N802
|
|
3
|
+
|
|
1
4
|
import datetime
|
|
2
5
|
import logging
|
|
6
|
+
import typing as ta
|
|
3
7
|
|
|
4
8
|
from .. import json
|
|
5
9
|
from .. import term
|
|
@@ -20,7 +24,7 @@ class StandardLogFormatter(logging.Formatter):
|
|
|
20
24
|
|
|
21
25
|
class ColorLogFormatter(StandardLogFormatter):
|
|
22
26
|
|
|
23
|
-
LEVEL_COLORS = {
|
|
27
|
+
LEVEL_COLORS: ta.Mapping[int, term.SGRs.FG] = {
|
|
24
28
|
logging.WARNING: term.SGRs.FG.BRIGHT_YELLOW,
|
|
25
29
|
logging.ERROR: term.SGRs.FG.BRIGHT_RED,
|
|
26
30
|
logging.CRITICAL: term.SGRs.FG.BRIGHT_RED,
|
|
@@ -39,7 +43,7 @@ class ColorLogFormatter(StandardLogFormatter):
|
|
|
39
43
|
|
|
40
44
|
class JsonLogFormatter(logging.Formatter):
|
|
41
45
|
|
|
42
|
-
KEYS = {
|
|
46
|
+
KEYS: ta.Mapping[str, bool] = {
|
|
43
47
|
'name': False,
|
|
44
48
|
'msg': False,
|
|
45
49
|
'args': False,
|
omlish/logs/utils.py
CHANGED
omlish/marshal/base.py
CHANGED
|
@@ -81,7 +81,7 @@ from .. import check
|
|
|
81
81
|
from .. import collections as col
|
|
82
82
|
from .. import lang
|
|
83
83
|
from .. import reflect as rfl
|
|
84
|
-
from .exceptions import
|
|
84
|
+
from .exceptions import UnhandledTypeError
|
|
85
85
|
from .factories import Factory
|
|
86
86
|
from .factories import RecursiveTypeFactory
|
|
87
87
|
from .registries import Registry
|
|
@@ -146,24 +146,24 @@ class BaseContext(lang.Abstract):
|
|
|
146
146
|
|
|
147
147
|
@dc.dataclass(frozen=True)
|
|
148
148
|
class MarshalContext(BaseContext, lang.Final):
|
|
149
|
-
factory:
|
|
149
|
+
factory: MarshalerFactory | None = None
|
|
150
150
|
|
|
151
151
|
def make(self, o: ta.Any) -> Marshaler:
|
|
152
152
|
rty = rfl.type_(o)
|
|
153
153
|
if (m := check.not_none(self.factory)(self, rty)) is not None: # noqa
|
|
154
154
|
return m
|
|
155
|
-
raise
|
|
155
|
+
raise UnhandledTypeError(rty)
|
|
156
156
|
|
|
157
157
|
|
|
158
158
|
@dc.dataclass(frozen=True)
|
|
159
159
|
class UnmarshalContext(BaseContext, lang.Final):
|
|
160
|
-
factory:
|
|
160
|
+
factory: UnmarshalerFactory | None = None
|
|
161
161
|
|
|
162
162
|
def make(self, o: ta.Any) -> Unmarshaler:
|
|
163
163
|
rty = rfl.type_(o)
|
|
164
164
|
if (m := check.not_none(self.factory)(self, rty)) is not None: # noqa
|
|
165
165
|
return m
|
|
166
|
-
raise
|
|
166
|
+
raise UnhandledTypeError(rty)
|
|
167
167
|
|
|
168
168
|
|
|
169
169
|
##
|
|
@@ -194,8 +194,8 @@ class RecursiveUnmarshalerFactory(RecursiveTypeFactory[Unmarshaler, UnmarshalCon
|
|
|
194
194
|
|
|
195
195
|
@dc.dataclass(frozen=True)
|
|
196
196
|
class SetType(RegistryItem, lang.Final):
|
|
197
|
-
marshaler:
|
|
198
|
-
marshaler_factory:
|
|
197
|
+
marshaler: Marshaler | None = None
|
|
198
|
+
marshaler_factory: MarshalerFactory | None = None
|
|
199
199
|
|
|
200
|
-
unmarshaler:
|
|
201
|
-
unmarshaler_factory:
|
|
200
|
+
unmarshaler: Unmarshaler | None = None
|
|
201
|
+
unmarshaler_factory: UnmarshalerFactory | None = None
|
omlish/marshal/dataclasses.py
CHANGED
|
@@ -79,7 +79,7 @@ def _make_field_obj(ctx, ty, obj, fac):
|
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
class DataclassMarshalerFactory(MarshalerFactory):
|
|
82
|
-
def __call__(self, ctx: MarshalContext, rty: rfl.Type) ->
|
|
82
|
+
def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
|
|
83
83
|
if isinstance(rty, type) and dc.is_dataclass(rty):
|
|
84
84
|
dc_md = get_dataclass_metadata(rty)
|
|
85
85
|
fields = [
|
|
@@ -97,7 +97,7 @@ class DataclassMarshalerFactory(MarshalerFactory):
|
|
|
97
97
|
|
|
98
98
|
|
|
99
99
|
class DataclassUnmarshalerFactory(UnmarshalerFactory):
|
|
100
|
-
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) ->
|
|
100
|
+
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
|
|
101
101
|
if isinstance(rty, type) and dc.is_dataclass(rty):
|
|
102
102
|
dc_md = get_dataclass_metadata(rty)
|
|
103
103
|
d: dict[str, tuple[FieldInfo, Unmarshaler]] = {}
|
omlish/marshal/enums.py
CHANGED
|
@@ -22,7 +22,7 @@ class EnumMarshaler(Marshaler):
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class EnumMarshalerFactory(MarshalerFactory):
|
|
25
|
-
def __call__(self, ctx: MarshalContext, rty: rfl.Type) ->
|
|
25
|
+
def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
|
|
26
26
|
if isinstance(rty, type) and issubclass(rty, enum.Enum):
|
|
27
27
|
return EnumMarshaler(rty)
|
|
28
28
|
return None
|
|
@@ -37,7 +37,7 @@ class EnumUnmarshaler(Unmarshaler):
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class EnumUnmarshalerFactory(UnmarshalerFactory):
|
|
40
|
-
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) ->
|
|
40
|
+
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
|
|
41
41
|
if isinstance(rty, type) and issubclass(rty, enum.Enum):
|
|
42
42
|
return EnumUnmarshaler(rty)
|
|
43
43
|
return None
|
omlish/marshal/exceptions.py
CHANGED
omlish/marshal/factories.py
CHANGED
|
@@ -17,7 +17,7 @@ A = ta.TypeVar('A')
|
|
|
17
17
|
|
|
18
18
|
class Factory(abc.ABC, ta.Generic[R, C, A]):
|
|
19
19
|
@abc.abstractmethod
|
|
20
|
-
def __call__(self, ctx: C, arg: A) ->
|
|
20
|
+
def __call__(self, ctx: C, arg: A) -> R | None:
|
|
21
21
|
raise NotImplementedError
|
|
22
22
|
|
|
23
23
|
|
|
@@ -26,9 +26,9 @@ class Factory(abc.ABC, ta.Generic[R, C, A]):
|
|
|
26
26
|
|
|
27
27
|
@dc.dataclass(frozen=True)
|
|
28
28
|
class FuncFactory(ta.Generic[R, C, A]):
|
|
29
|
-
fn: ta.Callable[[C, A],
|
|
29
|
+
fn: ta.Callable[[C, A], R | None]
|
|
30
30
|
|
|
31
|
-
def __call__(self, ctx: C, arg: A) ->
|
|
31
|
+
def __call__(self, ctx: C, arg: A) -> R | None:
|
|
32
32
|
return self.fn(ctx, arg)
|
|
33
33
|
|
|
34
34
|
|
|
@@ -39,7 +39,7 @@ class FuncFactory(ta.Generic[R, C, A]):
|
|
|
39
39
|
class TypeMapFactory(Factory[R, C, rfl.Type]):
|
|
40
40
|
m: ta.Mapping[rfl.Type, R] = dc.field(default_factory=dict)
|
|
41
41
|
|
|
42
|
-
def __call__(self, ctx: C, rty: rfl.Type) ->
|
|
42
|
+
def __call__(self, ctx: C, rty: rfl.Type) -> R | None:
|
|
43
43
|
return self.m.get(rty)
|
|
44
44
|
|
|
45
45
|
|
|
@@ -50,10 +50,10 @@ class TypeCacheFactory(Factory[R, C, rfl.Type]):
|
|
|
50
50
|
def __init__(self, f: Factory[R, C, rfl.Type]) -> None:
|
|
51
51
|
super().__init__()
|
|
52
52
|
self._f = f
|
|
53
|
-
self._dct: dict[rfl.Type,
|
|
53
|
+
self._dct: dict[rfl.Type, R | None] = {}
|
|
54
54
|
self._mtx = threading.RLock()
|
|
55
55
|
|
|
56
|
-
def __call__(self, ctx: C, rty: rfl.Type) ->
|
|
56
|
+
def __call__(self, ctx: C, rty: rfl.Type) -> R | None:
|
|
57
57
|
try:
|
|
58
58
|
return self._dct[rty]
|
|
59
59
|
except KeyError:
|
|
@@ -73,14 +73,14 @@ class RecursiveTypeFactory(Factory[R, C, rfl.Type]):
|
|
|
73
73
|
def __init__(
|
|
74
74
|
self,
|
|
75
75
|
f: Factory[R, C, rfl.Type],
|
|
76
|
-
prx: ta.Callable[[], tuple[
|
|
76
|
+
prx: ta.Callable[[], tuple[R | None, ta.Callable[[R | None], None]]],
|
|
77
77
|
) -> None:
|
|
78
78
|
super().__init__()
|
|
79
79
|
self._f = f
|
|
80
80
|
self._prx = prx
|
|
81
|
-
self._dct: dict[rfl.Type,
|
|
81
|
+
self._dct: dict[rfl.Type, R | None] = {}
|
|
82
82
|
|
|
83
|
-
def __call__(self, ctx: C, rty: rfl.Type) ->
|
|
83
|
+
def __call__(self, ctx: C, rty: rfl.Type) -> R | None:
|
|
84
84
|
try:
|
|
85
85
|
return self._dct[rty]
|
|
86
86
|
except KeyError:
|
|
@@ -108,7 +108,7 @@ class CompositeFactory(Factory[R, C, A]):
|
|
|
108
108
|
self._fs = fs
|
|
109
109
|
self._st = strategy
|
|
110
110
|
|
|
111
|
-
def __call__(self, ctx: C, arg: A) ->
|
|
111
|
+
def __call__(self, ctx: C, arg: A) -> R | None:
|
|
112
112
|
w: list[R] = []
|
|
113
113
|
for c in self._fs:
|
|
114
114
|
if (r := c(ctx, arg)) is None:
|
omlish/marshal/global_.py
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
3
|
from .base import MarshalContext
|
|
4
4
|
from .base import UnmarshalContext
|
|
5
|
+
from .registries import Registry
|
|
6
|
+
from .standard import new_standard_marshaler_factory
|
|
5
7
|
from .standard import new_standard_unmarshaler_factory
|
|
8
|
+
from .values import Value
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
T = ta.TypeVar('T')
|
|
6
12
|
|
|
7
13
|
|
|
8
14
|
##
|
|
@@ -17,7 +23,7 @@ GLOBAL_REGISTRY = Registry()
|
|
|
17
23
|
GLOBAL_MARSHALER_FACTORY = new_standard_marshaler_factory()
|
|
18
24
|
|
|
19
25
|
|
|
20
|
-
def marshal(obj, ty=None, **kwargs):
|
|
26
|
+
def marshal(obj: ta.Any, ty: type | None = None, **kwargs: ta.Any) -> Value:
|
|
21
27
|
mc = MarshalContext(GLOBAL_REGISTRY, factory=GLOBAL_MARSHALER_FACTORY, **kwargs)
|
|
22
28
|
return mc.make(ty if ty is not None else type(obj)).marshal(mc, obj)
|
|
23
29
|
|
|
@@ -28,6 +34,6 @@ def marshal(obj, ty=None, **kwargs):
|
|
|
28
34
|
GLOBAL_UNMARSHALER_FACTORY = new_standard_unmarshaler_factory()
|
|
29
35
|
|
|
30
36
|
|
|
31
|
-
def unmarshal(v, ty, **kwargs):
|
|
37
|
+
def unmarshal(v: Value, ty: type[T], **kwargs: ta.Any) -> T:
|
|
32
38
|
uc = UnmarshalContext(GLOBAL_REGISTRY, factory=GLOBAL_UNMARSHALER_FACTORY, **kwargs)
|
|
33
39
|
return uc.make(ty).unmarshal(uc, v)
|
omlish/marshal/iterables.py
CHANGED
|
@@ -23,7 +23,7 @@ class IterableMarshaler(Marshaler):
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class IterableMarshalerFactory(MarshalerFactory):
|
|
26
|
-
def __call__(self, ctx: MarshalContext, rty: rfl.Type) ->
|
|
26
|
+
def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
|
|
27
27
|
if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Iterable):
|
|
28
28
|
if (e := ctx.make(check.single(rty.args))) is None:
|
|
29
29
|
return None # type: ignore
|
|
@@ -45,7 +45,7 @@ class IterableUnmarshaler(Unmarshaler):
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class IterableUnmarshalerFactory(UnmarshalerFactory):
|
|
48
|
-
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) ->
|
|
48
|
+
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
|
|
49
49
|
if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Iterable):
|
|
50
50
|
if (e := ctx.make(check.single(rty.args))) is None:
|
|
51
51
|
return None # type: ignore
|
omlish/marshal/mappings.py
CHANGED
|
@@ -26,7 +26,7 @@ class MappingMarshaler(Marshaler):
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class MappingMarshalerFactory(MarshalerFactory):
|
|
29
|
-
def __call__(self, ctx: MarshalContext, rty: rfl.Type) ->
|
|
29
|
+
def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
|
|
30
30
|
if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping):
|
|
31
31
|
kt, vt = rty.args
|
|
32
32
|
if (ke := ctx.make(kt)) is None or (ve := ctx.make(vt)) is None:
|
|
@@ -53,7 +53,7 @@ class MappingUnmarshaler(Unmarshaler):
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
class MappingUnmarshalerFactory(UnmarshalerFactory):
|
|
56
|
-
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) ->
|
|
56
|
+
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
|
|
57
57
|
if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping):
|
|
58
58
|
kt, vt = rty.args
|
|
59
59
|
if (ke := ctx.make(kt)) is None or (ve := ctx.make(vt)) is None:
|
omlish/marshal/objects.py
CHANGED
|
@@ -98,8 +98,7 @@ class ObjectUnmarshaler(Unmarshaler):
|
|
|
98
98
|
if ukf is not None:
|
|
99
99
|
ukf[ks] = mv # FIXME: unmarshal?
|
|
100
100
|
continue
|
|
101
|
-
|
|
102
|
-
raise
|
|
101
|
+
raise
|
|
103
102
|
if fi.name in kw:
|
|
104
103
|
raise KeyError(f'Duplicate keys for field {fi.name!r}: {ks!r}')
|
|
105
104
|
kw[fi.name] = u.unmarshal(ctx, mv)
|
omlish/marshal/optionals.py
CHANGED
|
@@ -15,14 +15,14 @@ from .values import Value
|
|
|
15
15
|
class OptionalMarshaler(Marshaler):
|
|
16
16
|
e: Marshaler
|
|
17
17
|
|
|
18
|
-
def marshal(self, ctx: MarshalContext, o: ta.
|
|
18
|
+
def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
|
|
19
19
|
if o is None:
|
|
20
20
|
return None
|
|
21
21
|
return self.e.marshal(ctx, o)
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class OptionalMarshalerFactory(MarshalerFactory):
|
|
25
|
-
def __call__(self, ctx: MarshalContext, rty: rfl.Type) ->
|
|
25
|
+
def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
|
|
26
26
|
if isinstance(rty, rfl.Union) and rty.is_optional:
|
|
27
27
|
if (e := ctx.make(rty.without_none())) is None:
|
|
28
28
|
return None # type: ignore
|
|
@@ -34,14 +34,14 @@ class OptionalMarshalerFactory(MarshalerFactory):
|
|
|
34
34
|
class OptionalUnmarshaler(Unmarshaler):
|
|
35
35
|
e: Unmarshaler
|
|
36
36
|
|
|
37
|
-
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.
|
|
37
|
+
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
|
|
38
38
|
if v is None:
|
|
39
39
|
return None
|
|
40
40
|
return self.e.unmarshal(ctx, v)
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class OptionalUnmarshalerFactory(UnmarshalerFactory):
|
|
44
|
-
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) ->
|
|
44
|
+
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
|
|
45
45
|
if isinstance(rty, rfl.Union) and rty.is_optional:
|
|
46
46
|
if (e := ctx.make(rty.without_none())) is None:
|
|
47
47
|
return None # type: ignore
|
omlish/marshal/polymorphism.py
CHANGED
|
@@ -100,7 +100,7 @@ def polymorphism_from_subclasses(ty: type, *, naming: Naming | None = None) -> P
|
|
|
100
100
|
class PolymorphismMarshaler(Marshaler):
|
|
101
101
|
m: ta.Mapping[type, tuple[str, Marshaler]]
|
|
102
102
|
|
|
103
|
-
def marshal(self, ctx: MarshalContext, o: ta.
|
|
103
|
+
def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
|
|
104
104
|
tag, m = self.m[type(o)]
|
|
105
105
|
return {tag: m.marshal(ctx, o)}
|
|
106
106
|
|
|
@@ -109,7 +109,7 @@ class PolymorphismMarshaler(Marshaler):
|
|
|
109
109
|
class PolymorphismMarshalerFactory(MarshalerFactory):
|
|
110
110
|
p: Polymorphism
|
|
111
111
|
|
|
112
|
-
def __call__(self, ctx: MarshalContext, rty: rfl.Type) ->
|
|
112
|
+
def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
|
|
113
113
|
if rty is self.p.ty:
|
|
114
114
|
return PolymorphismMarshaler({
|
|
115
115
|
i.ty: (i.tag, ctx.make(i.ty))
|
|
@@ -125,7 +125,7 @@ class PolymorphismMarshalerFactory(MarshalerFactory):
|
|
|
125
125
|
class PolymorphismUnmarshaler(Unmarshaler):
|
|
126
126
|
m: ta.Mapping[str, Unmarshaler]
|
|
127
127
|
|
|
128
|
-
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.
|
|
128
|
+
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
|
|
129
129
|
ma = check.isinstance(v, collections.abc.Mapping)
|
|
130
130
|
[(tag, iv)] = ma.items()
|
|
131
131
|
u = self.m[tag] # type: ignore
|
|
@@ -136,7 +136,7 @@ class PolymorphismUnmarshaler(Unmarshaler):
|
|
|
136
136
|
class PolymorphismUnmarshalerFactory(UnmarshalerFactory):
|
|
137
137
|
p: Polymorphism
|
|
138
138
|
|
|
139
|
-
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) ->
|
|
139
|
+
def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
|
|
140
140
|
if rty is self.p.ty:
|
|
141
141
|
return PolymorphismUnmarshaler({
|
|
142
142
|
t: u
|