omlish 0.0.0.dev283__py3-none-any.whl → 0.0.0.dev285__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 +4 -4
- omlish/dataclasses/__init__.py +58 -60
- omlish/dataclasses/api/__init__.py +25 -0
- omlish/dataclasses/api/classes/__init__.py +0 -0
- omlish/dataclasses/api/classes/conversion.py +30 -0
- omlish/dataclasses/api/classes/decorator.py +145 -0
- omlish/dataclasses/api/classes/make.py +109 -0
- omlish/dataclasses/api/classes/metadata.py +133 -0
- omlish/dataclasses/api/classes/params.py +78 -0
- omlish/dataclasses/api/fields/__init__.py +0 -0
- omlish/dataclasses/api/fields/building.py +120 -0
- omlish/dataclasses/api/fields/constructor.py +56 -0
- omlish/dataclasses/api/fields/conversion.py +191 -0
- omlish/dataclasses/api/fields/metadata.py +94 -0
- omlish/dataclasses/concerns/__init__.py +17 -0
- omlish/dataclasses/concerns/abc.py +15 -0
- omlish/dataclasses/concerns/copy.py +63 -0
- omlish/dataclasses/concerns/doc.py +53 -0
- omlish/dataclasses/concerns/eq.py +60 -0
- omlish/dataclasses/concerns/fields.py +119 -0
- omlish/dataclasses/concerns/frozen.py +133 -0
- omlish/dataclasses/concerns/hash.py +165 -0
- omlish/dataclasses/concerns/init.py +453 -0
- omlish/dataclasses/concerns/matchargs.py +27 -0
- omlish/dataclasses/concerns/mro.py +16 -0
- omlish/dataclasses/concerns/order.py +87 -0
- omlish/dataclasses/concerns/override.py +98 -0
- omlish/dataclasses/concerns/params.py +14 -0
- omlish/dataclasses/concerns/replace.py +48 -0
- omlish/dataclasses/concerns/repr.py +95 -0
- omlish/dataclasses/{impl → concerns}/slots.py +25 -1
- omlish/dataclasses/debug.py +2 -0
- omlish/dataclasses/errors.py +115 -0
- omlish/dataclasses/generation/__init__.py +0 -0
- omlish/dataclasses/generation/base.py +38 -0
- omlish/dataclasses/generation/compilation.py +258 -0
- omlish/dataclasses/generation/execution.py +195 -0
- omlish/dataclasses/generation/globals.py +83 -0
- omlish/dataclasses/generation/idents.py +6 -0
- omlish/dataclasses/generation/mangling.py +18 -0
- omlish/dataclasses/generation/manifests.py +20 -0
- omlish/dataclasses/generation/ops.py +97 -0
- omlish/dataclasses/generation/plans.py +35 -0
- omlish/dataclasses/generation/processor.py +174 -0
- omlish/dataclasses/generation/registry.py +42 -0
- omlish/dataclasses/generation/utils.py +83 -0
- omlish/dataclasses/{impl/reflect.py → inspect.py} +53 -90
- omlish/dataclasses/{impl/internals.py → internals.py} +26 -32
- omlish/dataclasses/metaclass/__init__.py +0 -0
- omlish/dataclasses/metaclass/bases.py +69 -0
- omlish/dataclasses/metaclass/confer.py +65 -0
- omlish/dataclasses/metaclass/meta.py +115 -0
- omlish/dataclasses/metaclass/specs.py +38 -0
- omlish/dataclasses/processing/__init__.py +0 -0
- omlish/dataclasses/processing/base.py +83 -0
- omlish/dataclasses/processing/driving.py +45 -0
- omlish/dataclasses/processing/priority.py +13 -0
- omlish/dataclasses/processing/registry.py +81 -0
- omlish/dataclasses/reflection.py +81 -0
- omlish/dataclasses/specs.py +224 -0
- omlish/dataclasses/tools/__init__.py +0 -0
- omlish/dataclasses/{impl → tools}/as_.py +23 -8
- omlish/dataclasses/tools/iter.py +27 -0
- omlish/dataclasses/tools/modifiers.py +52 -0
- omlish/dataclasses/tools/replace.py +17 -0
- omlish/dataclasses/tools/repr.py +12 -0
- omlish/dataclasses/{static.py → tools/static.py} +25 -4
- omlish/dataclasses/utils.py +54 -109
- omlish/diag/__init__.py +4 -4
- omlish/inject/bindings.py +1 -1
- omlish/inject/eagers.py +1 -1
- omlish/inject/impl/bindings.py +1 -1
- omlish/inject/impl/origins.py +1 -1
- omlish/inject/keys.py +1 -1
- omlish/inject/listeners.py +1 -1
- omlish/inject/multis.py +4 -4
- omlish/inject/origins.py +2 -2
- omlish/inject/overrides.py +1 -1
- omlish/inject/privates.py +2 -2
- omlish/inject/providers.py +4 -4
- omlish/inject/scopes.py +3 -3
- omlish/lang/__init__.py +6 -2
- omlish/lang/cached/function.py +13 -2
- omlish/lang/cached/property.py +3 -1
- omlish/lang/imports.py +68 -10
- omlish/lang/objects.py +0 -46
- omlish/lite/reprs.py +84 -0
- omlish/marshal/objects/dataclasses.py +5 -9
- omlish/marshal/objects/helpers.py +3 -3
- omlish/secrets/marshal.py +1 -1
- omlish/secrets/secrets.py +1 -1
- omlish/sql/queries/base.py +4 -4
- omlish/text/mangle.py +66 -7
- omlish/typedvalues/marshal.py +2 -2
- omlish/typedvalues/values.py +1 -1
- {omlish-0.0.0.dev283.dist-info → omlish-0.0.0.dev285.dist-info}/METADATA +3 -3
- {omlish-0.0.0.dev283.dist-info → omlish-0.0.0.dev285.dist-info}/RECORD +101 -60
- omlish/dataclasses/impl/LICENSE +0 -279
- omlish/dataclasses/impl/__init__.py +0 -33
- omlish/dataclasses/impl/api.py +0 -278
- omlish/dataclasses/impl/copy.py +0 -30
- omlish/dataclasses/impl/errors.py +0 -53
- omlish/dataclasses/impl/fields.py +0 -245
- omlish/dataclasses/impl/frozen.py +0 -93
- omlish/dataclasses/impl/hashing.py +0 -86
- omlish/dataclasses/impl/init.py +0 -199
- omlish/dataclasses/impl/main.py +0 -93
- omlish/dataclasses/impl/metaclass.py +0 -235
- omlish/dataclasses/impl/metadata.py +0 -75
- omlish/dataclasses/impl/order.py +0 -47
- omlish/dataclasses/impl/overrides.py +0 -53
- omlish/dataclasses/impl/params.py +0 -128
- omlish/dataclasses/impl/processing.py +0 -24
- omlish/dataclasses/impl/replace.py +0 -40
- omlish/dataclasses/impl/repr.py +0 -66
- omlish/dataclasses/impl/simple.py +0 -50
- omlish/dataclasses/impl/utils.py +0 -167
- {omlish-0.0.0.dev283.dist-info → omlish-0.0.0.dev285.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev283.dist-info → omlish-0.0.0.dev285.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev283.dist-info → omlish-0.0.0.dev285.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev283.dist-info → omlish-0.0.0.dev285.dist-info}/top_level.txt +0 -0
omlish/lang/imports.py
CHANGED
@@ -3,6 +3,7 @@ TODO:
|
|
3
3
|
- proxy_init 'as' alias support - attrs of (src, dst)
|
4
4
|
"""
|
5
5
|
import contextlib
|
6
|
+
import functools
|
6
7
|
import importlib.util
|
7
8
|
import sys
|
8
9
|
import types
|
@@ -254,6 +255,64 @@ def _trigger_conditional_imports(package: str) -> None:
|
|
254
255
|
##
|
255
256
|
|
256
257
|
|
258
|
+
class LazyGlobals:
|
259
|
+
def __init__(
|
260
|
+
self,
|
261
|
+
*,
|
262
|
+
globals: ta.MutableMapping[str, ta.Any] | None = None, # noqa
|
263
|
+
update_globals: bool = False,
|
264
|
+
) -> None:
|
265
|
+
super().__init__()
|
266
|
+
|
267
|
+
self._globals = globals
|
268
|
+
self._update_globals = update_globals
|
269
|
+
|
270
|
+
self._attr_fns: dict[str, ta.Callable[[], ta.Any]] = {}
|
271
|
+
|
272
|
+
@classmethod
|
273
|
+
def install(cls, globals: ta.MutableMapping[str, ta.Any]) -> 'LazyGlobals': # noqa
|
274
|
+
try:
|
275
|
+
xga = globals['__getattr__']
|
276
|
+
except KeyError:
|
277
|
+
pass
|
278
|
+
else:
|
279
|
+
if not isinstance(xga, cls):
|
280
|
+
raise RuntimeError(f'Module already has __getattr__ hook: {xga}') # noqa
|
281
|
+
return xga
|
282
|
+
|
283
|
+
lm = cls(
|
284
|
+
globals=globals,
|
285
|
+
update_globals=True,
|
286
|
+
)
|
287
|
+
|
288
|
+
globals['__getattr__'] = lm
|
289
|
+
|
290
|
+
return lm
|
291
|
+
|
292
|
+
def set_fn(self, attr: str, fn: ta.Callable[[], ta.Any]) -> 'LazyGlobals':
|
293
|
+
self._attr_fns[attr] = fn
|
294
|
+
return self
|
295
|
+
|
296
|
+
def get(self, attr: str) -> ta.Any:
|
297
|
+
try:
|
298
|
+
fn = self._attr_fns[attr]
|
299
|
+
except KeyError:
|
300
|
+
raise AttributeError(attr) from None
|
301
|
+
|
302
|
+
val = fn()
|
303
|
+
|
304
|
+
if self._update_globals and self._globals is not None:
|
305
|
+
self._globals[attr] = val
|
306
|
+
|
307
|
+
return val
|
308
|
+
|
309
|
+
def __call__(self, attr: str) -> ta.Any:
|
310
|
+
return self.get(attr)
|
311
|
+
|
312
|
+
|
313
|
+
##
|
314
|
+
|
315
|
+
|
257
316
|
class NamePackage(ta.NamedTuple):
|
258
317
|
name: str
|
259
318
|
package: str
|
@@ -266,16 +325,13 @@ class _ProxyInit:
|
|
266
325
|
|
267
326
|
def __init__(
|
268
327
|
self,
|
328
|
+
lazy_globals: LazyGlobals,
|
269
329
|
name_package: NamePackage,
|
270
|
-
*,
|
271
|
-
globals: ta.MutableMapping[str, ta.Any] | None = None, # noqa
|
272
|
-
update_globals: bool = False,
|
273
330
|
) -> None:
|
274
331
|
super().__init__()
|
275
332
|
|
333
|
+
self._lazy_globals = lazy_globals
|
276
334
|
self._name_package = name_package
|
277
|
-
self._globals = globals
|
278
|
-
self._update_globals = update_globals
|
279
335
|
|
280
336
|
self._imps_by_attr: dict[str, _ProxyInit._Import] = {}
|
281
337
|
self._mods_by_pkgs: dict[str, ta.Any] = {}
|
@@ -287,13 +343,17 @@ class _ProxyInit:
|
|
287
343
|
def add(self, package: str, attrs: ta.Iterable[str | tuple[str, str]]) -> None:
|
288
344
|
if isinstance(attrs, str):
|
289
345
|
raise TypeError(attrs)
|
346
|
+
|
290
347
|
for attr in attrs:
|
291
348
|
if isinstance(attr, tuple):
|
292
349
|
imp_attr, attr = attr
|
293
350
|
else:
|
294
351
|
imp_attr = attr
|
352
|
+
|
295
353
|
self._imps_by_attr[attr] = self._Import(package, imp_attr)
|
296
354
|
|
355
|
+
self._lazy_globals.set_fn(attr, functools.partial(self.get, attr))
|
356
|
+
|
297
357
|
def get(self, attr: str) -> ta.Any:
|
298
358
|
try:
|
299
359
|
imp = self._imps_by_attr[attr]
|
@@ -307,9 +367,6 @@ class _ProxyInit:
|
|
307
367
|
|
308
368
|
val = getattr(mod, imp.attr)
|
309
369
|
|
310
|
-
if self._update_globals and self._globals is not None:
|
311
|
-
self._globals[attr] = val
|
312
|
-
|
313
370
|
return val
|
314
371
|
|
315
372
|
|
@@ -329,13 +386,14 @@ def proxy_init(
|
|
329
386
|
pi: _ProxyInit
|
330
387
|
try:
|
331
388
|
pi = globals['__proxy_init__']
|
389
|
+
|
332
390
|
except KeyError:
|
333
391
|
pi = _ProxyInit(
|
392
|
+
LazyGlobals.install(globals),
|
334
393
|
init_name_package,
|
335
|
-
globals=globals,
|
336
394
|
)
|
337
395
|
globals['__proxy_init__'] = pi
|
338
|
-
|
396
|
+
|
339
397
|
else:
|
340
398
|
if pi.name_package != init_name_package:
|
341
399
|
raise Exception(f'Wrong init name: {pi.name_package=} != {init_name_package=}')
|
omlish/lang/objects.py
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- reprlib / recur guard (merge w/ defs.py)
|
4
|
-
"""
|
5
|
-
import dataclasses as dc
|
6
1
|
import types
|
7
2
|
import typing as ta
|
8
3
|
import weakref
|
@@ -16,47 +11,6 @@ T = ta.TypeVar('T')
|
|
16
11
|
##
|
17
12
|
|
18
13
|
|
19
|
-
@dc.dataclass(frozen=True)
|
20
|
-
class AttrRepr:
|
21
|
-
attrs: ta.Sequence[str]
|
22
|
-
|
23
|
-
_: dc.KW_ONLY
|
24
|
-
|
25
|
-
with_module: bool = False
|
26
|
-
use_qualname: bool = False
|
27
|
-
with_id: bool = False
|
28
|
-
value_filter: ta.Callable[[ta.Any], bool] | None = None
|
29
|
-
|
30
|
-
@classmethod
|
31
|
-
def of(cls, *attrs: str, **kwargs: ta.Any) -> 'AttrRepr':
|
32
|
-
return cls(attrs, **kwargs)
|
33
|
-
|
34
|
-
def __call__(self, obj: ta.Any) -> str:
|
35
|
-
vs = ', '.join(
|
36
|
-
f'{attr}={v!r}'
|
37
|
-
for attr in self.attrs
|
38
|
-
for v in [getattr(obj, attr)]
|
39
|
-
if self.value_filter is None or self.value_filter(v)
|
40
|
-
)
|
41
|
-
return (
|
42
|
-
f'{obj.__class__.__module__ + "." if self.with_module else ""}'
|
43
|
-
f'{obj.__class__.__qualname__ if self.use_qualname else obj.__class__.__name__}'
|
44
|
-
f'{("@" + hex(id(obj))[2:]) if self.with_id else ""}'
|
45
|
-
f'({vs})'
|
46
|
-
)
|
47
|
-
|
48
|
-
def __get__(self, instance, owner):
|
49
|
-
if instance is None:
|
50
|
-
return self
|
51
|
-
def __repr__(other): # noqa
|
52
|
-
return self(other)
|
53
|
-
return __repr__.__get__(instance, owner)
|
54
|
-
|
55
|
-
|
56
|
-
def attr_repr(obj: ta.Any, *attrs: str, **kwargs: ta.Any) -> str:
|
57
|
-
return AttrRepr(attrs, **kwargs)(obj)
|
58
|
-
|
59
|
-
|
60
14
|
def arg_repr(*args: ta.Any, **kwargs: ta.Any) -> str:
|
61
15
|
return ', '.join(*(
|
62
16
|
list(map(repr, args)) +
|
omlish/lite/reprs.py
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# ruff: noqa: UP007
|
2
|
+
import dataclasses as dc
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
|
6
|
+
##
|
7
|
+
|
8
|
+
|
9
|
+
@dc.dataclass(frozen=True)
|
10
|
+
class AttrRepr:
|
11
|
+
attrs: ta.Sequence[str]
|
12
|
+
|
13
|
+
# _: dc.KW_ONLY
|
14
|
+
|
15
|
+
with_module: bool = False
|
16
|
+
use_qualname: bool = False
|
17
|
+
with_id: bool = False
|
18
|
+
value_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None
|
19
|
+
recursive: bool = False
|
20
|
+
|
21
|
+
@classmethod
|
22
|
+
def of(cls, *attrs: str, **kwargs: ta.Any) -> 'AttrRepr':
|
23
|
+
return cls(attrs, **kwargs)
|
24
|
+
|
25
|
+
#
|
26
|
+
|
27
|
+
def _build_(self, obj: ta.Any) -> str:
|
28
|
+
vs = ', '.join(
|
29
|
+
f'{attr}={v!r}'
|
30
|
+
for attr in self.attrs
|
31
|
+
for v in [getattr(obj, attr)]
|
32
|
+
if self.value_filter is None or self.value_filter(v)
|
33
|
+
)
|
34
|
+
|
35
|
+
return (
|
36
|
+
f'{obj.__class__.__module__ + "." if self.with_module else ""}'
|
37
|
+
f'{obj.__class__.__qualname__ if self.use_qualname else obj.__class__.__name__}'
|
38
|
+
f'{("@" + hex(id(obj))[2:]) if self.with_id else ""}'
|
39
|
+
f'({vs})'
|
40
|
+
)
|
41
|
+
|
42
|
+
_build: ta.ClassVar[ta.Callable[[ta.Any], str]]
|
43
|
+
|
44
|
+
def __call__(self, obj: ta.Any) -> str:
|
45
|
+
try:
|
46
|
+
build: ta.Any = self._build
|
47
|
+
|
48
|
+
except AttributeError:
|
49
|
+
build = self._build_
|
50
|
+
if self.recursive:
|
51
|
+
build = self._reprlib().recursive_repr()(build)
|
52
|
+
object.__setattr__(self, '_build', build)
|
53
|
+
|
54
|
+
return build(obj)
|
55
|
+
|
56
|
+
#
|
57
|
+
|
58
|
+
def __get__(self, instance, owner):
|
59
|
+
if instance is None:
|
60
|
+
return self
|
61
|
+
|
62
|
+
def __repr__(other): # noqa
|
63
|
+
return self(other)
|
64
|
+
|
65
|
+
return __repr__.__get__(instance, owner)
|
66
|
+
|
67
|
+
#
|
68
|
+
|
69
|
+
_reprlib_: ta.ClassVar[ta.Any]
|
70
|
+
|
71
|
+
@classmethod
|
72
|
+
def _reprlib(cls) -> ta.Any:
|
73
|
+
try:
|
74
|
+
return cls._reprlib_
|
75
|
+
except AttributeError:
|
76
|
+
pass
|
77
|
+
|
78
|
+
reprlib = __import__('reprlib')
|
79
|
+
cls._reprlib_ = reprlib
|
80
|
+
return reprlib
|
81
|
+
|
82
|
+
|
83
|
+
def attr_repr(obj: ta.Any, *attrs: str, **kwargs: ta.Any) -> str:
|
84
|
+
return AttrRepr(attrs, **kwargs)(obj)
|
@@ -34,11 +34,7 @@ from .unmarshal import ObjectUnmarshaler
|
|
34
34
|
|
35
35
|
|
36
36
|
def get_dataclass_metadata(ty: type) -> ObjectMetadata:
|
37
|
-
return check.
|
38
|
-
e
|
39
|
-
for e in dc.get_merged_metadata(ty).get(dc.UserMetadata, [])
|
40
|
-
if isinstance(e, ObjectMetadata)
|
41
|
-
) or ObjectMetadata()
|
37
|
+
return check.single(dc.reflect(ty).spec.metadata_by_type.get(ObjectMetadata) or [ObjectMetadata()])
|
42
38
|
|
43
39
|
|
44
40
|
def get_dataclass_field_infos(
|
@@ -50,7 +46,7 @@ def get_dataclass_field_infos(
|
|
50
46
|
|
51
47
|
dc_md = get_dataclass_metadata(ty)
|
52
48
|
dc_naming = dc_md.field_naming or opts.get(Naming)
|
53
|
-
|
49
|
+
dc_rfl = dc.reflect(ty)
|
54
50
|
|
55
51
|
fi_defaults = {
|
56
52
|
k: v
|
@@ -66,7 +62,7 @@ def get_dataclass_field_infos(
|
|
66
62
|
type_hints = ta.get_type_hints(ty)
|
67
63
|
|
68
64
|
ret: list[FieldInfo] = []
|
69
|
-
for field in
|
65
|
+
for field in dc_rfl.instance_fields:
|
70
66
|
if (f_naming := field.metadata.get(Naming, dc_naming)) is not None:
|
71
67
|
um_name = translate_name(field.name, f_naming)
|
72
68
|
else:
|
@@ -76,10 +72,10 @@ def get_dataclass_field_infos(
|
|
76
72
|
|
77
73
|
f_ty: ta.Any
|
78
74
|
if (
|
79
|
-
|
75
|
+
dc_rfl.spec.generic_init or
|
80
76
|
(fmd is not None and fmd.options.generic_replace)
|
81
77
|
):
|
82
|
-
f_ty = rfl.to_annotation(
|
78
|
+
f_ty = rfl.to_annotation(dc_rfl.fields_inspection.generic_replaced_field_type(field.name))
|
83
79
|
else:
|
84
80
|
f_ty = type_hints[field.name]
|
85
81
|
|
@@ -14,7 +14,7 @@ T = ta.TypeVar('T')
|
|
14
14
|
def update_field_metadata(**kwargs: ta.Any) -> dc.field_modifier:
|
15
15
|
@dc.field_modifier
|
16
16
|
def inner(f: dc.Field) -> dc.Field:
|
17
|
-
return dc.
|
17
|
+
return dc.set_field_metadata(f, {
|
18
18
|
FieldMetadata: f.metadata.get(FieldMetadata, FieldMetadata()).update(**kwargs),
|
19
19
|
})
|
20
20
|
return inner
|
@@ -25,7 +25,7 @@ def update_fields_metadata(
|
|
25
25
|
**kwargs: ta.Any,
|
26
26
|
) -> ta.Callable[[type[T]], type[T]]:
|
27
27
|
def inner(a: str, f: dc.Field) -> dc.Field:
|
28
|
-
return dc.
|
28
|
+
return dc.set_field_metadata(f, {
|
29
29
|
FieldMetadata: f.metadata.get(FieldMetadata, FieldMetadata()).update(**kwargs),
|
30
30
|
})
|
31
31
|
|
@@ -37,7 +37,7 @@ def update_object_metadata(
|
|
37
37
|
**kwargs: ta.Any,
|
38
38
|
):
|
39
39
|
def inner(cls):
|
40
|
-
return dc.
|
40
|
+
return dc.append_class_metadata(cls, ObjectMetadata(**kwargs))
|
41
41
|
|
42
42
|
if cls is not None:
|
43
43
|
inner(cls)
|
omlish/secrets/marshal.py
CHANGED
@@ -44,7 +44,7 @@ class StrOrSecretRefMarshalerUnmarshaler(msh.Marshaler, msh.Unmarshaler):
|
|
44
44
|
def marshal_secret_field(f: dc.Field) -> dc.Field:
|
45
45
|
"""Mostly obsolete with auto-registration below."""
|
46
46
|
|
47
|
-
return dc.
|
47
|
+
return dc.set_field_metadata(f, {
|
48
48
|
msh.FieldMetadata: dc.replace(
|
49
49
|
f.metadata.get(msh.FieldMetadata, msh.FieldMetadata()),
|
50
50
|
marshaler=StrOrSecretRefMarshalerUnmarshaler(),
|
omlish/secrets/secrets.py
CHANGED
omlish/sql/queries/base.py
CHANGED
@@ -29,7 +29,7 @@ class Node(
|
|
29
29
|
lang.Abstract,
|
30
30
|
eq=False,
|
31
31
|
confer=frozenset([
|
32
|
-
*dc.
|
32
|
+
*dc.get_metaclass_spec(dc.Frozen).confer,
|
33
33
|
'eq',
|
34
34
|
]),
|
35
35
|
):
|
@@ -61,10 +61,10 @@ class Node(
|
|
61
61
|
except KeyError:
|
62
62
|
pass
|
63
63
|
|
64
|
-
|
64
|
+
dc_rfl = dc.reflect(cls)
|
65
65
|
fields = Node._Fields(
|
66
|
-
cmp_fields=tuple(f.name for f in
|
67
|
-
hash_fields=tuple(f.name for f in
|
66
|
+
cmp_fields=tuple(f.name for f in dc_rfl.instance_fields if f.compare),
|
67
|
+
hash_fields=tuple(f.name for f in dc_rfl.instance_fields if (f.compare if f.hash is None else f.hash)),
|
68
68
|
)
|
69
69
|
|
70
70
|
setattr(cls, '__node_fields__', fields)
|
omlish/text/mangle.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
# @omlish-lite
|
3
3
|
import dataclasses as dc
|
4
|
+
import re
|
4
5
|
import typing as ta
|
5
6
|
|
6
7
|
from ..lite.cached import cached_nullary
|
@@ -26,16 +27,74 @@ class StringMangler:
|
|
26
27
|
check.not_in(self.escape, self.escaped)
|
27
28
|
check.arg(len(set(self.escaped)) == len(self.escaped))
|
28
29
|
|
30
|
+
#
|
31
|
+
|
32
|
+
@cached_nullary
|
33
|
+
def replaced(self) -> ta.Tuple[str, ...]:
|
34
|
+
return (self.escape, *self.escaped)
|
35
|
+
|
36
|
+
@cached_nullary
|
37
|
+
def replaced_set(self) -> ta.FrozenSet[str]:
|
38
|
+
return frozenset(self.replaced())
|
39
|
+
|
40
|
+
@cached_nullary
|
41
|
+
def replaced_indexes(self) -> ta.Mapping[str, int]:
|
42
|
+
return {s: i for i, s in enumerate(self.replaced())}
|
43
|
+
|
44
|
+
@cached_nullary
|
45
|
+
def replaced_pat(self) -> re.Pattern:
|
46
|
+
return re.compile('|'.join(re.escape(k) for k in self.replaced()))
|
47
|
+
|
48
|
+
#
|
49
|
+
|
50
|
+
@cached_nullary
|
51
|
+
def replacement_pad(self) -> int:
|
52
|
+
return len('%x' % (len(self.replaced()),)) # noqa
|
53
|
+
|
29
54
|
@cached_nullary
|
30
55
|
def replacements(self) -> ta.Sequence[ta.Tuple[str, str]]:
|
31
|
-
|
56
|
+
fmt = f'%0{self.replacement_pad()}x'
|
57
|
+
return [
|
58
|
+
(l, self.escape + fmt % (i,))
|
59
|
+
for i, l in enumerate(self.replaced())
|
60
|
+
]
|
61
|
+
|
62
|
+
@cached_nullary
|
63
|
+
def replacements_dict(self) -> ta.Mapping[str, str]:
|
64
|
+
return dict(self.replacements())
|
65
|
+
|
66
|
+
@cached_nullary
|
67
|
+
def inverse_replacements_dict(self) -> ta.Mapping[str, str]:
|
68
|
+
return {v: k for k, v in self.replacements()}
|
69
|
+
|
70
|
+
@cached_nullary
|
71
|
+
def replacements_pat(self) -> re.Pattern:
|
72
|
+
return re.compile(''.join([re.escape(self.escape), '.' * self.replacement_pad()]))
|
73
|
+
|
74
|
+
#
|
75
|
+
|
76
|
+
# def mangle(self, s: str) -> str:
|
77
|
+
# ecs = sorted(
|
78
|
+
# frozenset(s) & self.replaced_set(),
|
79
|
+
# key=self.replaced_indexes().__getitem__,
|
80
|
+
# )
|
81
|
+
# rd = self.replacements_dict()
|
82
|
+
# for l in ecs:
|
83
|
+
# r = rd[l]
|
84
|
+
# s = s.replace(l, r)
|
85
|
+
# return s
|
32
86
|
|
33
87
|
def mangle(self, s: str) -> str:
|
34
|
-
|
35
|
-
|
36
|
-
|
88
|
+
rd = self.replacements_dict()
|
89
|
+
return self.replaced_pat().sub(lambda m: rd[m.group(0)], s)
|
90
|
+
|
91
|
+
#
|
92
|
+
|
93
|
+
# def unmangle(self, s: str) -> str:
|
94
|
+
# for l, r in reversed(self.replacements()):
|
95
|
+
# s = s.replace(r, l)
|
96
|
+
# return s
|
37
97
|
|
38
98
|
def unmangle(self, s: str) -> str:
|
39
|
-
|
40
|
-
|
41
|
-
return s
|
99
|
+
ird = self.inverse_replacements_dict()
|
100
|
+
return self.replacements_pat().sub(lambda m: ird[m.group(0)], s)
|
omlish/typedvalues/marshal.py
CHANGED
@@ -32,7 +32,7 @@ class TypedValueMarshalerFactory(msh.MarshalerFactoryMatchClass):
|
|
32
32
|
))
|
33
33
|
def _build_scalar(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
|
34
34
|
dc_rfl = dc.reflect(check.isinstance(rty, type))
|
35
|
-
v_rty = check.single(dc_rfl.generic_replaced_field_annotations.values())
|
35
|
+
v_rty = check.single(dc_rfl.fields_inspection.generic_replaced_field_annotations.values())
|
36
36
|
v_m = ctx.make(v_rty)
|
37
37
|
return msh.WrappedMarshaler(lambda _, o: o.v, v_m)
|
38
38
|
|
@@ -58,7 +58,7 @@ class TypedValueUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
|
|
58
58
|
def _build_scalar(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
|
59
59
|
rty = check.isinstance(rty, type)
|
60
60
|
dc_rfl = dc.reflect(rty)
|
61
|
-
v_rty = check.single(dc_rfl.generic_replaced_field_annotations.values())
|
61
|
+
v_rty = check.single(dc_rfl.fields_inspection.generic_replaced_field_annotations.values())
|
62
62
|
v_u = ctx.make(v_rty)
|
63
63
|
return msh.WrappedUnmarshaler(lambda _, v: rty(v), v_u)
|
64
64
|
|
omlish/typedvalues/values.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: omlish
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev285
|
4
4
|
Summary: omlish
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -15,7 +15,7 @@ License-File: LICENSE
|
|
15
15
|
Provides-Extra: all
|
16
16
|
Requires-Dist: anyio~=4.9; extra == "all"
|
17
17
|
Requires-Dist: sniffio~=1.3; extra == "all"
|
18
|
-
Requires-Dist: greenlet~=3.
|
18
|
+
Requires-Dist: greenlet~=3.2; extra == "all"
|
19
19
|
Requires-Dist: trio~=0.29; extra == "all"
|
20
20
|
Requires-Dist: trio-asyncio~=0.15; extra == "all"
|
21
21
|
Requires-Dist: lz4~=4.4; extra == "all"
|
@@ -53,7 +53,7 @@ Requires-Dist: wrapt~=1.17; extra == "all"
|
|
53
53
|
Provides-Extra: async
|
54
54
|
Requires-Dist: anyio~=4.9; extra == "async"
|
55
55
|
Requires-Dist: sniffio~=1.3; extra == "async"
|
56
|
-
Requires-Dist: greenlet~=3.
|
56
|
+
Requires-Dist: greenlet~=3.2; extra == "async"
|
57
57
|
Requires-Dist: trio~=0.29; extra == "async"
|
58
58
|
Requires-Dist: trio-asyncio~=0.15; extra == "async"
|
59
59
|
Provides-Extra: compress
|