omlish 0.0.0.dev273__py3-none-any.whl → 0.0.0.dev275__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/.manifests.json +1 -1
- omlish/__about__.py +2 -2
- omlish/collections/identity.py +28 -5
- omlish/dataclasses/impl/api.py +6 -0
- omlish/dataclasses/impl/params.py +1 -0
- omlish/dataclasses/impl/reflect.py +10 -6
- omlish/dataclasses/impl/repr.py +10 -3
- omlish/marshal/objects/dataclasses.py +8 -3
- omlish/marshal/objects/metadata.py +2 -0
- omlish/secrets/all.py +8 -0
- omlish/secrets/marshal.py +3 -0
- omlish/secrets/pwgen.py +3 -0
- omlish/secrets/pwhash.py +3 -0
- omlish/secrets/ssl.py +3 -0
- omlish/secrets/subprocesses.py +3 -0
- omlish/secrets/tempssl.py +3 -0
- omlish/typedvalues/__init__.py +8 -0
- omlish/typedvalues/accessor.py +7 -0
- omlish/typedvalues/collection.py +105 -26
- omlish/typedvalues/marshal.py +139 -0
- omlish/typedvalues/values.py +6 -0
- {omlish-0.0.0.dev273.dist-info → omlish-0.0.0.dev275.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev273.dist-info → omlish-0.0.0.dev275.dist-info}/RECORD +27 -26
- {omlish-0.0.0.dev273.dist-info → omlish-0.0.0.dev275.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev273.dist-info → omlish-0.0.0.dev275.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev273.dist-info → omlish-0.0.0.dev275.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev273.dist-info → omlish-0.0.0.dev275.dist-info}/top_level.txt +0 -0
omlish/.manifests.json
CHANGED
omlish/__about__.py
CHANGED
omlish/collections/identity.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import contextlib
|
2
1
|
import operator as op
|
3
2
|
import typing as ta
|
4
3
|
import weakref
|
@@ -17,6 +16,7 @@ V = ta.TypeVar('V')
|
|
17
16
|
class IdentityWrapper(ta.Generic[T]):
|
18
17
|
def __init__(self, value: T) -> None:
|
19
18
|
super().__init__()
|
19
|
+
|
20
20
|
self._value = value
|
21
21
|
|
22
22
|
def __repr__(self) -> str:
|
@@ -39,6 +39,7 @@ class IdentityWrapper(ta.Generic[T]):
|
|
39
39
|
class IdentityKeyDict(ta.MutableMapping[K, V]):
|
40
40
|
def __init__(self, *args, **kwargs) -> None:
|
41
41
|
super().__init__()
|
42
|
+
|
42
43
|
self._dict: dict[int, tuple[K, V]] = {}
|
43
44
|
for k, v in lang.yield_dict_init(*args, **kwargs):
|
44
45
|
self[k] = v
|
@@ -75,6 +76,7 @@ class IdentityKeyDict(ta.MutableMapping[K, V]):
|
|
75
76
|
class IdentitySet(ta.MutableSet[T]):
|
76
77
|
def __init__(self, init: ta.Iterable[T] | None = None) -> None:
|
77
78
|
super().__init__()
|
79
|
+
|
78
80
|
self._dict: dict[int, T] = {}
|
79
81
|
if init is not None:
|
80
82
|
for item in init:
|
@@ -94,8 +96,10 @@ class IdentitySet(ta.MutableSet[T]):
|
|
94
96
|
self._dict[id(item)] = item
|
95
97
|
|
96
98
|
def discard(self, item: T) -> None:
|
97
|
-
|
99
|
+
try:
|
98
100
|
del self._dict[id(item)]
|
101
|
+
except KeyError:
|
102
|
+
pass
|
99
103
|
|
100
104
|
def update(self, items: ta.Iterable[T]) -> None:
|
101
105
|
for item in items:
|
@@ -111,7 +115,26 @@ class IdentitySet(ta.MutableSet[T]):
|
|
111
115
|
return iter(self._dict.values())
|
112
116
|
|
113
117
|
|
114
|
-
class IdentityWeakSet(
|
115
|
-
def __init__(self, init=None):
|
118
|
+
class IdentityWeakSet(ta.MutableSet[T]):
|
119
|
+
def __init__(self, init: ta.Iterable[T] | None = None) -> None:
|
116
120
|
super().__init__()
|
117
|
-
|
121
|
+
|
122
|
+
self._dict: weakref.WeakValueDictionary[int, T] = weakref.WeakValueDictionary()
|
123
|
+
|
124
|
+
def add(self, value):
|
125
|
+
self._dict[id(value)] = value
|
126
|
+
|
127
|
+
def discard(self, value):
|
128
|
+
try:
|
129
|
+
del self._dict[id(value)]
|
130
|
+
except KeyError:
|
131
|
+
pass
|
132
|
+
|
133
|
+
def __contains__(self, x):
|
134
|
+
return id(x) in self._dict
|
135
|
+
|
136
|
+
def __len__(self):
|
137
|
+
return len(self._dict)
|
138
|
+
|
139
|
+
def __iter__(self):
|
140
|
+
return self._dict.values()
|
omlish/dataclasses/impl/api.py
CHANGED
@@ -103,6 +103,7 @@ def dataclass( # noqa
|
|
103
103
|
cache_hash=MISSING,
|
104
104
|
generic_init=MISSING,
|
105
105
|
override=MISSING,
|
106
|
+
repr_id=MISSING,
|
106
107
|
):
|
107
108
|
def wrap(cls):
|
108
109
|
pkw = dict(
|
@@ -126,6 +127,7 @@ def dataclass( # noqa
|
|
126
127
|
cache_hash=cache_hash,
|
127
128
|
generic_init=generic_init,
|
128
129
|
override=override,
|
130
|
+
repr_id=repr_id,
|
129
131
|
)))
|
130
132
|
pex = ParamsExtras(**epk)
|
131
133
|
|
@@ -175,6 +177,7 @@ def make_dataclass( # noqa
|
|
175
177
|
cache_hash=MISSING,
|
176
178
|
generic_init=MISSING,
|
177
179
|
override=MISSING,
|
180
|
+
repr_id=MISSING,
|
178
181
|
):
|
179
182
|
if namespace is None:
|
180
183
|
namespace = {}
|
@@ -236,6 +239,7 @@ def make_dataclass( # noqa
|
|
236
239
|
cache_hash=cache_hash,
|
237
240
|
generic_init=generic_init,
|
238
241
|
override=override,
|
242
|
+
repr_id=repr_id,
|
239
243
|
)
|
240
244
|
|
241
245
|
|
@@ -249,6 +253,7 @@ def extra_params( # noqa
|
|
249
253
|
cache_hash=MISSING,
|
250
254
|
generic_init=MISSING,
|
251
255
|
override=MISSING,
|
256
|
+
repr_id=MISSING,
|
252
257
|
):
|
253
258
|
def inner(cls):
|
254
259
|
if PARAMS_ATTR in cls.__dict__:
|
@@ -266,6 +271,7 @@ def extra_params( # noqa
|
|
266
271
|
cache_hash=cache_hash,
|
267
272
|
generic_init=generic_init,
|
268
273
|
override=override,
|
274
|
+
repr_id=repr_id,
|
269
275
|
))
|
270
276
|
|
271
277
|
return cls
|
@@ -149,16 +149,20 @@ class ClassInfo:
|
|
149
149
|
def generic_mro_lookup(self) -> ta.Mapping[type, rfl.Type]:
|
150
150
|
return col.make_map(((check.not_none(rfl.get_concrete_type(g)), g) for g in self.generic_mro), strict=True)
|
151
151
|
|
152
|
+
def generic_replaced_field_type(self, fn: str) -> rfl.Type:
|
153
|
+
f = self.fields[fn]
|
154
|
+
fo = self.field_owners[f.name]
|
155
|
+
go = self.generic_mro_lookup[fo]
|
156
|
+
tvr = rfl.get_type_var_replacements(go)
|
157
|
+
fty = rfl.type_(f.type)
|
158
|
+
rty = rfl.replace_type_vars(fty, tvr, update_aliases=True)
|
159
|
+
return rty
|
160
|
+
|
152
161
|
@cached.property
|
153
162
|
def generic_replaced_field_types(self) -> ta.Mapping[str, rfl.Type]:
|
154
163
|
ret: dict[str, ta.Any] = {}
|
155
164
|
for f in self.fields.values():
|
156
|
-
|
157
|
-
go = self.generic_mro_lookup[fo]
|
158
|
-
tvr = rfl.get_type_var_replacements(go)
|
159
|
-
fty = rfl.type_(f.type)
|
160
|
-
rty = rfl.replace_type_vars(fty, tvr, update_aliases=True)
|
161
|
-
ret[f.name] = rty
|
165
|
+
ret[f.name] = self.generic_replaced_field_type(f.name)
|
162
166
|
return ret
|
163
167
|
|
164
168
|
@cached.property
|
omlish/dataclasses/impl/repr.py
CHANGED
@@ -12,11 +12,17 @@ from .utils import set_new_attribute
|
|
12
12
|
def repr_fn(
|
13
13
|
fields: ta.Sequence[dc.Field],
|
14
14
|
globals: Namespace, # noqa
|
15
|
+
*,
|
16
|
+
repr_id: bool = False,
|
15
17
|
) -> ta.Callable:
|
16
18
|
locals: dict[str, ta.Any] = {} # noqa
|
17
19
|
|
18
20
|
fields = sorted(fields, key=lambda f: get_field_extras(f).repr_priority or 0)
|
19
21
|
|
22
|
+
prefix_src = '{self.__class__.__qualname__}'
|
23
|
+
if repr_id:
|
24
|
+
prefix_src += '@{hex(id(self))[2:]}'
|
25
|
+
|
20
26
|
if any(get_field_extras(f).repr_fn is not None for f in fields):
|
21
27
|
lst: list[str] = []
|
22
28
|
for f in fields:
|
@@ -29,12 +35,12 @@ def repr_fn(
|
|
29
35
|
src = [
|
30
36
|
'l = []',
|
31
37
|
*lst,
|
32
|
-
'return f"{
|
38
|
+
f'return f"{prefix_src}({{", ".join(l)}})"',
|
33
39
|
]
|
34
40
|
|
35
41
|
else:
|
36
42
|
src = [
|
37
|
-
'return f"{
|
43
|
+
f'return f"{prefix_src}(' +
|
38
44
|
', '.join([f'{f.name}={{self.{f.name}!r}}' for f in fields]) +
|
39
45
|
')"',
|
40
46
|
]
|
@@ -56,4 +62,5 @@ class ReprProcessor(Processor):
|
|
56
62
|
return
|
57
63
|
|
58
64
|
flds = [f for f in self._info.instance_fields if f.repr]
|
59
|
-
|
65
|
+
rfn = repr_fn(flds, self._info.globals, repr_id=self._info.params_extras.repr_id)
|
66
|
+
set_new_attribute(self._cls, '__repr__', rfn) # noqa
|
@@ -72,9 +72,14 @@ def get_dataclass_field_infos(
|
|
72
72
|
else:
|
73
73
|
um_name = field.name
|
74
74
|
|
75
|
+
fmd: FieldMetadata | None = field.metadata.get(FieldMetadata)
|
76
|
+
|
75
77
|
f_ty: ta.Any
|
76
|
-
if (
|
77
|
-
|
78
|
+
if (
|
79
|
+
((cpx := dc_rf.cls_params_extras) is not None and cpx.generic_init) or
|
80
|
+
(fmd is not None and fmd.options.generic_replace)
|
81
|
+
):
|
82
|
+
f_ty = rfl.to_annotation(dc_rf.generic_replaced_field_type(field.name))
|
78
83
|
else:
|
79
84
|
f_ty = type_hints[field.name]
|
80
85
|
|
@@ -91,7 +96,7 @@ def get_dataclass_field_infos(
|
|
91
96
|
)
|
92
97
|
|
93
98
|
has_set_name = False
|
94
|
-
if
|
99
|
+
if fmd is not None:
|
95
100
|
fi_kw.update(
|
96
101
|
metadata=fmd,
|
97
102
|
)
|
omlish/secrets/all.py
CHANGED
omlish/secrets/marshal.py
CHANGED
@@ -16,6 +16,9 @@ from .secrets import SecretRef
|
|
16
16
|
from .secrets import SecretRefOrStr
|
17
17
|
|
18
18
|
|
19
|
+
##
|
20
|
+
|
21
|
+
|
19
22
|
class StrOrSecretRefMarshalerUnmarshaler(msh.Marshaler, msh.Unmarshaler):
|
20
23
|
def marshal(self, ctx: msh.MarshalContext, o: ta.Any) -> msh.Value:
|
21
24
|
if isinstance(o, str):
|
omlish/secrets/pwgen.py
CHANGED
omlish/secrets/pwhash.py
CHANGED
omlish/secrets/ssl.py
CHANGED
omlish/secrets/subprocesses.py
CHANGED
omlish/secrets/tempssl.py
CHANGED
omlish/typedvalues/__init__.py
CHANGED
omlish/typedvalues/accessor.py
CHANGED
@@ -23,6 +23,13 @@ UniqueTypedValueU = ta.TypeVar('UniqueTypedValueU', bound='UniqueTypedValue')
|
|
23
23
|
|
24
24
|
|
25
25
|
class TypedValuesAccessor(lang.Abstract, ta.Generic[TypedValueT]):
|
26
|
+
def __iter__(self):
|
27
|
+
raise TypeError(
|
28
|
+
'TypedValuesAccessor does not implement __iter__ - it is reserved for implementation by subclasses.',
|
29
|
+
)
|
30
|
+
|
31
|
+
#
|
32
|
+
|
26
33
|
@ta.final
|
27
34
|
def __contains__(self, cls: type[TypedValueU]) -> bool:
|
28
35
|
raise NotImplementedError
|
omlish/typedvalues/collection.py
CHANGED
@@ -29,23 +29,29 @@ class TypedValues(
|
|
29
29
|
ta.Generic[TypedValueT],
|
30
30
|
):
|
31
31
|
def __init__(self, *tvs: TypedValueT, override: bool = False) -> None:
|
32
|
+
if hasattr(self, '_tup'):
|
33
|
+
# When __new__ returns the empty singleton __init__ will still be called.
|
34
|
+
if self is not self._EMPTY:
|
35
|
+
raise RuntimeError
|
36
|
+
return
|
37
|
+
|
32
38
|
super().__init__()
|
33
39
|
|
34
40
|
tmp: list = []
|
35
41
|
udct: dict = {}
|
36
42
|
for tv in tvs:
|
37
43
|
if isinstance(tv, UniqueTypedValue):
|
38
|
-
|
44
|
+
utvc = tv._unique_typed_value_cls # noqa
|
39
45
|
if not override:
|
40
46
|
try:
|
41
|
-
exu = udct[
|
47
|
+
exu = udct[utvc]
|
42
48
|
except KeyError:
|
43
49
|
pass
|
44
50
|
else:
|
45
|
-
raise DuplicateUniqueTypedValueError(
|
46
|
-
ulst = udct.setdefault(
|
51
|
+
raise DuplicateUniqueTypedValueError(utvc, tv, check.single(exu))
|
52
|
+
ulst = udct.setdefault(utvc, [])
|
47
53
|
ulst.append(tv)
|
48
|
-
tmp.append((tv, len(ulst)))
|
54
|
+
tmp.append((utvc, tv, ulst, len(ulst)))
|
49
55
|
elif isinstance(tv, TypedValue):
|
50
56
|
tmp.append(tv)
|
51
57
|
else:
|
@@ -53,42 +59,105 @@ class TypedValues(
|
|
53
59
|
|
54
60
|
lst: list = []
|
55
61
|
dct: dict = {}
|
56
|
-
for
|
57
|
-
if isinstance(
|
58
|
-
|
59
|
-
ulst = udct[uo._unique_typed_value_cls] # noqa
|
62
|
+
for obj in tmp:
|
63
|
+
if isinstance(obj, tuple):
|
64
|
+
utvc, tv, ulst, idx = obj
|
60
65
|
if idx == len(ulst):
|
61
|
-
lst.append(
|
62
|
-
dct[
|
63
|
-
dct[type(
|
66
|
+
lst.append(tv)
|
67
|
+
dct[utvc] = tv
|
68
|
+
dct[type(tv)] = tv
|
64
69
|
else:
|
70
|
+
tv = obj
|
65
71
|
lst.append(tv)
|
66
72
|
dct.setdefault(type(tv), []).append(tv)
|
67
73
|
|
68
|
-
self.
|
69
|
-
self._dct =
|
74
|
+
self._tup: tuple[TypedValueT, ...] = tuple(lst)
|
75
|
+
self._dct: dict[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]] = {
|
76
|
+
k: tuple(v) if isinstance(v, list) else v
|
77
|
+
for k, v in dct.items()
|
78
|
+
}
|
79
|
+
|
80
|
+
#
|
81
|
+
|
82
|
+
_EMPTY: ta.ClassVar['TypedValues']
|
70
83
|
|
71
|
-
|
84
|
+
@classmethod
|
85
|
+
def empty(cls) -> 'TypedValues':
|
86
|
+
return cls._EMPTY
|
87
|
+
|
88
|
+
def __new__(cls, *tvs, **kwargs): # noqa
|
89
|
+
if not tvs:
|
90
|
+
try:
|
91
|
+
return cls._EMPTY
|
92
|
+
except AttributeError:
|
93
|
+
pass
|
94
|
+
return super().__new__(cls)
|
95
|
+
|
96
|
+
#
|
72
97
|
|
73
98
|
def without(self, *tys: type) -> ta.Iterator[TypedValueT]:
|
74
|
-
for o in self.
|
99
|
+
for o in self._tup:
|
75
100
|
if isinstance(o, tys):
|
76
101
|
continue
|
77
102
|
yield o
|
78
103
|
|
104
|
+
#
|
105
|
+
|
106
|
+
def update(self, *tvs, override: bool = False) -> 'TypedValues':
|
107
|
+
return TypedValues(*self._tup, *tvs, override=override)
|
108
|
+
|
109
|
+
def discard(self, *tys: type) -> 'TypedValues':
|
110
|
+
return TypedValues(*self.without(*tys))
|
111
|
+
|
112
|
+
#
|
113
|
+
|
79
114
|
def __repr__(self) -> str:
|
80
|
-
return f'{self.__class__.__name__}({", ".join(map(repr, self.
|
115
|
+
return f'{self.__class__.__name__}({", ".join(map(repr, self._tup))})'
|
116
|
+
|
117
|
+
#
|
118
|
+
|
119
|
+
_set: frozenset[TypedValueT]
|
120
|
+
|
121
|
+
def to_set(self) -> frozenset[TypedValueT]:
|
122
|
+
try:
|
123
|
+
return self._set
|
124
|
+
except AttributeError:
|
125
|
+
pass
|
126
|
+
s = frozenset(self._tup)
|
127
|
+
self._set = s
|
128
|
+
return s
|
129
|
+
|
130
|
+
#
|
131
|
+
|
132
|
+
_hash: int
|
133
|
+
|
134
|
+
def __hash__(self) -> int:
|
135
|
+
try:
|
136
|
+
return self._hash
|
137
|
+
except AttributeError:
|
138
|
+
pass
|
139
|
+
h = hash(self._tup)
|
140
|
+
self._hash = h
|
141
|
+
return h
|
142
|
+
|
143
|
+
def __eq__(self, other):
|
144
|
+
if not isinstance(other, type(self)):
|
145
|
+
return NotImplemented
|
146
|
+
return (
|
147
|
+
other is self or
|
148
|
+
other._tup == self._tup
|
149
|
+
)
|
81
150
|
|
82
151
|
#
|
83
152
|
|
84
153
|
def __iter__(self) -> ta.Iterator[TypedValueT]:
|
85
|
-
return iter(self.
|
154
|
+
return iter(self._tup)
|
86
155
|
|
87
156
|
def __len__(self) -> int:
|
88
|
-
return len(self.
|
157
|
+
return len(self._tup)
|
89
158
|
|
90
159
|
def __bool__(self) -> bool:
|
91
|
-
return bool(self.
|
160
|
+
return bool(self._tup)
|
92
161
|
|
93
162
|
#
|
94
163
|
|
@@ -97,7 +166,7 @@ class TypedValues(
|
|
97
166
|
|
98
167
|
def _typed_value_getitem(self, key):
|
99
168
|
if isinstance(key, int):
|
100
|
-
return self.
|
169
|
+
return self._tup[key]
|
101
170
|
elif isinstance(key, type):
|
102
171
|
return self._dct[check.issubclass(key, TypedValue)]
|
103
172
|
else:
|
@@ -111,15 +180,25 @@ class TypedValues(
|
|
111
180
|
if issubclass(key, UniqueTypedValue):
|
112
181
|
return default
|
113
182
|
elif default is not None:
|
114
|
-
return
|
183
|
+
return tuple(default)
|
115
184
|
else:
|
116
|
-
return
|
185
|
+
return ()
|
186
|
+
|
187
|
+
_any_dct: dict[type, tuple[TypedValueT, ...]]
|
117
188
|
|
118
189
|
def _typed_value_get_any(self, cls):
|
119
190
|
try:
|
120
|
-
|
191
|
+
any_dct = self._any_dct
|
192
|
+
except AttributeError:
|
193
|
+
any_dct = {}
|
194
|
+
self._any_dct = any_dct
|
195
|
+
try:
|
196
|
+
return any_dct[cls]
|
121
197
|
except KeyError:
|
122
198
|
pass
|
123
|
-
ret =
|
124
|
-
|
199
|
+
ret = tuple(tv for tv in self if isinstance(tv, cls))
|
200
|
+
any_dct[cls] = ret
|
125
201
|
return ret
|
202
|
+
|
203
|
+
|
204
|
+
TypedValues._EMPTY = TypedValues() # noqa
|
@@ -0,0 +1,139 @@
|
|
1
|
+
from omlish import check
|
2
|
+
from omlish import dataclasses as dc
|
3
|
+
from omlish import lang
|
4
|
+
from omlish import marshal as msh
|
5
|
+
from omlish import reflect as rfl
|
6
|
+
from omlish.funcs import match as mfs
|
7
|
+
|
8
|
+
from .collection import TypedValues
|
9
|
+
from .values import ScalarTypedValue
|
10
|
+
from .values import TypedValue
|
11
|
+
|
12
|
+
|
13
|
+
##
|
14
|
+
|
15
|
+
|
16
|
+
def _build_typed_value_poly(rty: rfl.Type) -> msh.Polymorphism:
|
17
|
+
ty: type[TypedValue] = check.issubclass(check.isinstance(rty, type), TypedValue)
|
18
|
+
check.state(lang.is_abstract_class(ty))
|
19
|
+
return msh.polymorphism_from_subclasses(
|
20
|
+
ty,
|
21
|
+
naming=msh.Naming.SNAKE,
|
22
|
+
strip_suffix='auto',
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
class TypedValueMarshalerFactory(msh.MarshalerFactoryMatchClass):
|
27
|
+
@mfs.simple(lambda _, ctx, rty: (
|
28
|
+
isinstance(rty, type) and
|
29
|
+
issubclass(rty, ScalarTypedValue) and
|
30
|
+
not lang.is_abstract_class(rty)
|
31
|
+
))
|
32
|
+
def _build_scalar(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
|
33
|
+
dc_rfl = dc.reflect(check.isinstance(rty, type))
|
34
|
+
v_rty = check.single(dc_rfl.generic_replaced_field_annotations.values())
|
35
|
+
v_m = ctx.make(v_rty)
|
36
|
+
return msh.WrappedMarshaler(lambda _, o: o.v, v_m)
|
37
|
+
|
38
|
+
@mfs.simple(lambda _, ctx, rty: (
|
39
|
+
isinstance(rty, type) and
|
40
|
+
issubclass(rty, TypedValue) and
|
41
|
+
lang.is_abstract_class(rty)
|
42
|
+
))
|
43
|
+
def _build_abstract(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
|
44
|
+
return msh.make_polymorphism_marshaler(
|
45
|
+
_build_typed_value_poly(rty).impls,
|
46
|
+
msh.WrapperTypeTagging(),
|
47
|
+
ctx,
|
48
|
+
)
|
49
|
+
|
50
|
+
|
51
|
+
class TypedValueUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
|
52
|
+
@mfs.simple(lambda _, ctx, rty: (
|
53
|
+
isinstance(rty, type) and
|
54
|
+
issubclass(rty, ScalarTypedValue) and
|
55
|
+
not lang.is_abstract_class(rty)
|
56
|
+
))
|
57
|
+
def _build_scalar(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
|
58
|
+
rty = check.isinstance(rty, type)
|
59
|
+
dc_rfl = dc.reflect(rty)
|
60
|
+
v_rty = check.single(dc_rfl.generic_replaced_field_annotations.values())
|
61
|
+
v_u = ctx.make(v_rty)
|
62
|
+
return msh.WrappedUnmarshaler(lambda _, v: rty(v), v_u)
|
63
|
+
|
64
|
+
@mfs.simple(lambda _, ctx, rty: (
|
65
|
+
isinstance(rty, type) and
|
66
|
+
issubclass(rty, TypedValue) and
|
67
|
+
lang.is_abstract_class(rty)
|
68
|
+
))
|
69
|
+
def _build_abstract(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
|
70
|
+
return msh.make_polymorphism_unmarshaler(
|
71
|
+
_build_typed_value_poly(rty).impls,
|
72
|
+
msh.WrapperTypeTagging(),
|
73
|
+
ctx,
|
74
|
+
)
|
75
|
+
|
76
|
+
|
77
|
+
##
|
78
|
+
|
79
|
+
|
80
|
+
def _build_typed_values_impls(rty: rfl.Type) -> msh.Impls:
|
81
|
+
gty = check.isinstance(rty, rfl.Generic)
|
82
|
+
check.is_(gty.cls, TypedValues)
|
83
|
+
|
84
|
+
opt_cls_set: set[type[TypedValue]] = set()
|
85
|
+
|
86
|
+
todo = [check.single(gty.args)]
|
87
|
+
seen = set()
|
88
|
+
while todo:
|
89
|
+
cur = todo.pop()
|
90
|
+
if cur in seen:
|
91
|
+
continue
|
92
|
+
seen.add(cur)
|
93
|
+
|
94
|
+
if isinstance(cur, rfl.Union):
|
95
|
+
todo.extend(cur.args)
|
96
|
+
else:
|
97
|
+
opt_cls_set.add(check.issubclass(check.isinstance(cur, type), TypedValue))
|
98
|
+
|
99
|
+
opt_impls: list[msh.Impl] = []
|
100
|
+
for opt_cls in opt_cls_set:
|
101
|
+
opt_impls.extend(_build_typed_value_poly(opt_cls).impls)
|
102
|
+
|
103
|
+
return msh.Impls(opt_impls)
|
104
|
+
|
105
|
+
|
106
|
+
class TypedValuesMarshalerFactory(msh.MarshalerFactoryMatchClass):
|
107
|
+
@mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Generic) and rty.cls is TypedValues)
|
108
|
+
def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
|
109
|
+
opt_m = msh.make_polymorphism_marshaler(
|
110
|
+
msh.Impls(_build_typed_values_impls(rty)),
|
111
|
+
msh.WrapperTypeTagging(),
|
112
|
+
ctx,
|
113
|
+
)
|
114
|
+
return msh.IterableMarshaler(opt_m)
|
115
|
+
|
116
|
+
|
117
|
+
class TypedValuesUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
|
118
|
+
@mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Generic) and rty.cls is TypedValues)
|
119
|
+
def _build(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
|
120
|
+
opt_u = msh.make_polymorphism_unmarshaler(
|
121
|
+
msh.Impls(_build_typed_values_impls(rty)),
|
122
|
+
msh.WrapperTypeTagging(),
|
123
|
+
ctx,
|
124
|
+
)
|
125
|
+
return msh.IterableUnmarshaler(lambda it: TypedValues(*it), opt_u) # noqa
|
126
|
+
|
127
|
+
|
128
|
+
##
|
129
|
+
|
130
|
+
|
131
|
+
@lang.static_init
|
132
|
+
def _install_standard_marshalling() -> None:
|
133
|
+
msh.install_standard_factories(
|
134
|
+
TypedValueMarshalerFactory(),
|
135
|
+
TypedValueUnmarshalerFactory(),
|
136
|
+
|
137
|
+
TypedValuesMarshalerFactory(),
|
138
|
+
TypedValuesUnmarshalerFactory(),
|
139
|
+
)
|
omlish/typedvalues/values.py
CHANGED
@@ -42,3 +42,9 @@ class ScalarTypedValue(TypedValue, lang.Abstract, ta.Generic[T]):
|
|
42
42
|
|
43
43
|
def __repr__(self) -> str:
|
44
44
|
return f'{self.__class__.__name__}({self.v!r})'
|
45
|
+
|
46
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
47
|
+
super().__init_subclass__(**kwargs)
|
48
|
+
|
49
|
+
if UniqueTypedValue in (mro := cls.__mro__) and mro.index(ScalarTypedValue) > mro.index(UniqueTypedValue):
|
50
|
+
raise TypeError(f'Class {cls} must have UniqueTypedValue before ScalarTypedValue in mro')
|
@@ -1,5 +1,5 @@
|
|
1
|
-
omlish/.manifests.json,sha256=
|
2
|
-
omlish/__about__.py,sha256=
|
1
|
+
omlish/.manifests.json,sha256=pjGUyLHaoWpPqRP3jz2u1fC1qoRc2lvrEcpU_Ax2tdg,8253
|
2
|
+
omlish/__about__.py,sha256=lF4UMo4JKgTQYbwgQIGekUW4rRztnuwQfTy1Wa-z9kQ,3380
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=rer-TPOFDU6fYq_AWio_AmA-ckZ8JDY5shIzQ_yXfzA,8414
|
5
5
|
omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
|
@@ -149,7 +149,7 @@ omlish/collections/coerce.py,sha256=tAls15v_7p5bUN33R7Zbko87KW5toWHl9fRialCqyNY,
|
|
149
149
|
omlish/collections/exceptions.py,sha256=shcS-NCnEUudF8qC_SmO2TQyjivKlS4TDjaz_faqQ0c,44
|
150
150
|
omlish/collections/frozen.py,sha256=LMbAHYDENIQk1hvjCTvpnx66m1TalrHa4CSn8n_tsXQ,4142
|
151
151
|
omlish/collections/hasheq.py,sha256=swOBPEnU_C0SU3VqWJX9mr0BfZLD0A-4Ke9Vahj3fE4,3669
|
152
|
-
omlish/collections/identity.py,sha256=
|
152
|
+
omlish/collections/identity.py,sha256=cIcvGORpKAWpNxEleAiPxJJsMA9RmZ7LUSKacexgCxE,3276
|
153
153
|
omlish/collections/mappings.py,sha256=u0UrB550nBM_RNXQV0YnBTbRZEWrplZe9ZxcCN3H65M,2789
|
154
154
|
omlish/collections/ordered.py,sha256=7zTbrAt12rf6i33XHkQERKar258fJacaw_WbtGEBgWo,2338
|
155
155
|
omlish/collections/ranked.py,sha256=rg6DL36oOUiG5JQEAkGnT8b6f9mSndQlIovtt8GQj_w,2229
|
@@ -206,7 +206,7 @@ omlish/dataclasses/static.py,sha256=6pZG2iTR9NN8pKm-5ukDABnaVlTKFOzMwkg-rbxURoo,
|
|
206
206
|
omlish/dataclasses/utils.py,sha256=BTXYyH0enSEP5kWxMnPTJ8_UPd7h4wF2RVPITNC8H4M,3872
|
207
207
|
omlish/dataclasses/impl/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936
|
208
208
|
omlish/dataclasses/impl/__init__.py,sha256=zqGBC5gSbjJxaqG_zS1LL1PX-zAfhIua8UqOE4IwO2k,789
|
209
|
-
omlish/dataclasses/impl/api.py,sha256=
|
209
|
+
omlish/dataclasses/impl/api.py,sha256=BkwGQYBdl9D8sq9pNmraqOfr5F0fpYF_CbD_s0ESEU8,7007
|
210
210
|
omlish/dataclasses/impl/as_.py,sha256=CD-t7hkC1EP2F_jvZKIA_cVoDuwZ-Ln_xC4fJumPYX0,2598
|
211
211
|
omlish/dataclasses/impl/copy.py,sha256=Tn8_n6Vohs-w4otbGdubBEvhd3TsSTaM3EfNGdS2LYo,591
|
212
212
|
omlish/dataclasses/impl/descriptors.py,sha256=jSYNkKdy2rKddGpQqRwNuhw-ggpcvp_SWHpLwIWPOzc,2474
|
@@ -221,11 +221,11 @@ omlish/dataclasses/impl/metaclass.py,sha256=ebxJr3j8d_wz-fc7mvhWtJ6wJgnxVV6rVOQd
|
|
221
221
|
omlish/dataclasses/impl/metadata.py,sha256=4veWwTr-aA0KP-Y1cPEeOcXHup9EKJTYNJ0ozIxtzD4,1401
|
222
222
|
omlish/dataclasses/impl/order.py,sha256=zWvWDkSTym8cc7vO1cLHqcBhhjOlucHOCUVJcdh4jt0,1369
|
223
223
|
omlish/dataclasses/impl/overrides.py,sha256=g9aCzaDDKyek8-yXRvtAcu1B1nCphWDYr4InHDlgbKk,1732
|
224
|
-
omlish/dataclasses/impl/params.py,sha256=
|
224
|
+
omlish/dataclasses/impl/params.py,sha256=HMhvtsPup6WQOPLEVXTHgVvDWHk-kX-E2GAZxWXa6R0,3009
|
225
225
|
omlish/dataclasses/impl/processing.py,sha256=DFxyFjL_h3awRyF_5eyTnB8QkuApx7Zc4QFnVoltlao,459
|
226
|
-
omlish/dataclasses/impl/reflect.py,sha256=
|
226
|
+
omlish/dataclasses/impl/reflect.py,sha256=ndX22d9bd9m_GAajPFQdnrw98AGw75lH9_tb-kdHwAs,5597
|
227
227
|
omlish/dataclasses/impl/replace.py,sha256=wS9GHX4fIwaPv1JBJzIewdBfXyK3X3V7_t55Da87dYo,1217
|
228
|
-
omlish/dataclasses/impl/repr.py,sha256=
|
228
|
+
omlish/dataclasses/impl/repr.py,sha256=hk6HwKTLA0tb698CfiO8RYAqtpHQbGCpymm_Eo-B-2Y,1876
|
229
229
|
omlish/dataclasses/impl/simple.py,sha256=Q272TYXifB5iKtydByxyzraeQHX6aXDY0VKO1-AKBF4,1771
|
230
230
|
omlish/dataclasses/impl/slots.py,sha256=qXRLbtFWUs_2UV1fFUdv53_6fBLKJ_8McjNiP9YQlGM,5264
|
231
231
|
omlish/dataclasses/impl/utils.py,sha256=aER2iL3UAtgS1BdLuEvTr9Tr2wC28wk1kiOeO-jIymw,6138
|
@@ -514,10 +514,10 @@ omlish/marshal/composite/newtypes.py,sha256=5-te247TiPYf84oFhf59tqIOOByXj8i9KaHT
|
|
514
514
|
omlish/marshal/composite/optionals.py,sha256=MnecrmrJYjQvYJipIHNCDq78oH09dOjnw5pvaMKqoeU,1537
|
515
515
|
omlish/marshal/composite/wrapped.py,sha256=jOsn3h1vLIqcoSTB-0KObnsdbV8jSVWJYbf7Kg9AUwg,750
|
516
516
|
omlish/marshal/objects/__init__.py,sha256=F4wej8L_tedC8ETYxAnmKfdPR9TjsqIus9Z3nZofYuc,182
|
517
|
-
omlish/marshal/objects/dataclasses.py,sha256=
|
517
|
+
omlish/marshal/objects/dataclasses.py,sha256=zs0yE0gi3tKHLiZGPf8FEMhPOc505vnHMjpp92MOX5k,8658
|
518
518
|
omlish/marshal/objects/helpers.py,sha256=85GZp4h3Yo0GYGmnZpKgNxkWnSk8h2R21nfDLU2DtM0,1110
|
519
519
|
omlish/marshal/objects/marshal.py,sha256=JarKGecMgaFYSUHUj-ZUYVP9HK6u2rjpBb3DWX9Uhh0,2648
|
520
|
-
omlish/marshal/objects/metadata.py,sha256=
|
520
|
+
omlish/marshal/objects/metadata.py,sha256=2_rESnslP5fwtEW1xy9ECJg64uA4cQBuYcGkRfPElts,3342
|
521
521
|
omlish/marshal/objects/namedtuples.py,sha256=8de8L7rwmvr_LLBHHfOl2wHObxc_1yZ8fC_J25yZi7Q,2866
|
522
522
|
omlish/marshal/objects/unmarshal.py,sha256=IXIl_iokvVCSWYhkRORrWP_sE1DVklnrUErGWg_3MDc,3632
|
523
523
|
omlish/marshal/polymorphism/__init__.py,sha256=e2UTrSL0qp7w_1vkdxDWd7sXlWhep2KPV49-BB64ma8,130
|
@@ -573,16 +573,16 @@ omlish/reflect/ops.py,sha256=RJ6jzrM4ieFsXzWyNXWV43O_WgzEaUvlHSc5N2ezW2A,2044
|
|
573
573
|
omlish/reflect/subst.py,sha256=g3q7NmNWsmc67mcchmCE3WFPCMDSBq-FXn4ah-DWL_U,3622
|
574
574
|
omlish/reflect/types.py,sha256=lYxK_hlC4kVDMKeDYJp0mymSth21quwuFAMAEFBznyE,9151
|
575
575
|
omlish/secrets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
576
|
-
omlish/secrets/all.py,sha256=
|
576
|
+
omlish/secrets/all.py,sha256=SGB1KrlNrxlNpazEHYy95NTzteLi8ndoEgMhU7luBl8,420
|
577
577
|
omlish/secrets/crypto.py,sha256=9D21lnvPhStwu8arD4ssT0ih0bDG-nlqIRdVgYL40xA,3708
|
578
|
-
omlish/secrets/marshal.py,sha256=
|
578
|
+
omlish/secrets/marshal.py,sha256=Jat6jTr0Fv3YBwqmq_DO2xahwn9qIeILrIybJ0vk34U,1989
|
579
579
|
omlish/secrets/openssl.py,sha256=UT_dXJ4zA1s9e-UHoW_NLGHQO7iouUNPnJNkkpuw3JI,6213
|
580
|
-
omlish/secrets/pwgen.py,sha256=
|
581
|
-
omlish/secrets/pwhash.py,sha256=
|
580
|
+
omlish/secrets/pwgen.py,sha256=5k7QMSysUfv9F65TDMdDlrhTIKy6QbMG3KT2HNVmnVg,1712
|
581
|
+
omlish/secrets/pwhash.py,sha256=Jctv3QzcMvVPXJsWA3w3LDUlzmyUDGEWG9sLiJz1xaw,4107
|
582
582
|
omlish/secrets/secrets.py,sha256=QNgOmRcIRK2fx49bIbBBM2rYbe6IhhLgk8fKvq8guoI,7963
|
583
|
-
omlish/secrets/ssl.py,sha256=
|
584
|
-
omlish/secrets/subprocesses.py,sha256=
|
585
|
-
omlish/secrets/tempssl.py,sha256=
|
583
|
+
omlish/secrets/ssl.py,sha256=_72xTNP6a1Xw0Pweuow9WK5yveqJ7hmjhala9iMnrAk,152
|
584
|
+
omlish/secrets/subprocesses.py,sha256=ZdShw4jrGDdyQW8mRMgl106-9qpCEq2J6w_x7ruz1wk,1217
|
585
|
+
omlish/secrets/tempssl.py,sha256=X_cAQbeaz-YcH8SzQ0luYTktIGJv4KMpfTD3t9l9Gqk,1879
|
586
586
|
omlish/sockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
587
587
|
omlish/sockets/addresses.py,sha256=vbVeQBkzI513H4vRv-JS89QtRbr9U8v5zqkm3oODl_s,1869
|
588
588
|
omlish/sockets/bind.py,sha256=J1SfFFFnVf3H5nqESDX2NGEY8DmjyIMUXZciZM33zQY,8003
|
@@ -776,15 +776,16 @@ omlish/text/parts.py,sha256=Q9NvoyEGQKIWgiPD4D_Qc66cWAuyEKE033dT9m7c3Wk,6662
|
|
776
776
|
omlish/text/random.py,sha256=8feS5JE_tSjYlMl-lp0j93kCfzBae9AM2cXlRLebXMA,199
|
777
777
|
omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
778
778
|
omlish/text/go/quoting.py,sha256=N9EYdnFdEX_A8fOviH-1w4jwV3XOQ7VU2WsoUNubYVY,9137
|
779
|
-
omlish/typedvalues/__init__.py,sha256=
|
780
|
-
omlish/typedvalues/accessor.py,sha256=
|
781
|
-
omlish/typedvalues/collection.py,sha256=
|
779
|
+
omlish/typedvalues/__init__.py,sha256=YalNleXS2vQX_3dOIMwfb4n_uBkENTT4QXHnsHatGGM,496
|
780
|
+
omlish/typedvalues/accessor.py,sha256=0k21N-CkjGaY6zCwugsRfOC_CDkqk7wNz4oxO1_6EEA,2919
|
781
|
+
omlish/typedvalues/collection.py,sha256=jsXSggmMMvGATcJgQkUXt5Guwq8aquw73_OIC-e6U0I,5300
|
782
782
|
omlish/typedvalues/generic.py,sha256=byWG_gMXhNelckUwdmOoJE9FKkL71Q4BSi4ZLyy0XZ0,788
|
783
783
|
omlish/typedvalues/holder.py,sha256=4SwRezsmuDDEO5gENGx8kTm30pblF5UktoEAu02i-Gk,1554
|
784
|
-
omlish/typedvalues/
|
785
|
-
omlish
|
786
|
-
omlish-0.0.0.
|
787
|
-
omlish-0.0.0.
|
788
|
-
omlish-0.0.0.
|
789
|
-
omlish-0.0.0.
|
790
|
-
omlish-0.0.0.
|
784
|
+
omlish/typedvalues/marshal.py,sha256=BuFQMoaLSDbEm32nj_hkBSClPvC0euNFU7_EhsrfBck,4487
|
785
|
+
omlish/typedvalues/values.py,sha256=Acyf6xSdNHxrkRXLXrFqJouk35YOveso1VqTbyPwQW4,1223
|
786
|
+
omlish-0.0.0.dev275.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
787
|
+
omlish-0.0.0.dev275.dist-info/METADATA,sha256=UZAxSmm4fOzFFAc7qszP_AvnFcJB1Sp3UwcpxUQ9V6w,4198
|
788
|
+
omlish-0.0.0.dev275.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
789
|
+
omlish-0.0.0.dev275.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
790
|
+
omlish-0.0.0.dev275.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
791
|
+
omlish-0.0.0.dev275.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|