omlish 0.0.0.dev414__py3-none-any.whl → 0.0.0.dev416__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 -3
- omlish/codecs/registry.py +1 -1
- omlish/dataclasses/__init__.py +139 -113
- omlish/dataclasses/impl/api/classes/make.py +5 -3
- omlish/dataclasses/impl/configs.py +29 -29
- omlish/lang/__init__.py +486 -473
- omlish/lang/imports/proxyinit.py +161 -48
- omlish/lang/maybes.py +8 -0
- omlish/lite/maysyncs.py +1 -0
- omlish/manifests/base.py +1 -1
- omlish/marshal/__init__.py +98 -57
- omlish/marshal/base/__init__.py +0 -0
- omlish/marshal/base/contexts.py +78 -0
- omlish/marshal/{errors.py → base/errors.py} +1 -1
- omlish/marshal/base/options.py +2 -0
- omlish/marshal/base/overrides.py +34 -0
- omlish/marshal/{registries.py → base/registries.py} +11 -9
- omlish/marshal/base/types.py +122 -0
- omlish/marshal/{values.py → base/values.py} +1 -13
- omlish/marshal/composite/iterables.py +7 -7
- omlish/marshal/composite/literals.py +7 -7
- omlish/marshal/composite/mappings.py +7 -7
- omlish/marshal/composite/maybes.py +7 -7
- omlish/marshal/composite/newtypes.py +6 -6
- omlish/marshal/composite/optionals.py +7 -7
- omlish/marshal/composite/special.py +6 -6
- omlish/marshal/composite/wrapped.py +5 -5
- omlish/marshal/factories/__init__.py +0 -0
- omlish/marshal/factories/func.py +28 -0
- omlish/marshal/factories/match.py +34 -0
- omlish/marshal/factories/multi.py +55 -0
- omlish/marshal/factories/recursive.py +120 -0
- omlish/marshal/factories/simple.py +28 -0
- omlish/marshal/factories/typecache.py +91 -0
- omlish/marshal/factories/typemap.py +65 -0
- omlish/marshal/globals.py +35 -25
- omlish/marshal/naming.py +1 -1
- omlish/marshal/objects/dataclasses.py +7 -7
- omlish/marshal/objects/marshal.py +4 -4
- omlish/marshal/objects/metadata.py +4 -4
- omlish/marshal/objects/namedtuples.py +7 -7
- omlish/marshal/objects/unmarshal.py +4 -4
- omlish/marshal/polymorphism/marshal.py +4 -4
- omlish/marshal/polymorphism/metadata.py +1 -1
- omlish/marshal/polymorphism/standard.py +2 -2
- omlish/marshal/polymorphism/unions.py +7 -7
- omlish/marshal/polymorphism/unmarshal.py +4 -4
- omlish/marshal/singular/base64.py +7 -7
- omlish/marshal/singular/datetimes.py +7 -7
- omlish/marshal/singular/enums.py +7 -7
- omlish/marshal/singular/numbers.py +7 -7
- omlish/marshal/singular/primitives.py +7 -7
- omlish/marshal/singular/uuids.py +7 -7
- omlish/marshal/standard.py +8 -8
- omlish/marshal/trivial/any.py +7 -7
- omlish/marshal/trivial/forbidden.py +7 -7
- omlish/marshal/trivial/nop.py +5 -5
- omlish/reflect/__init__.py +57 -47
- omlish/reflect/types.py +144 -15
- {omlish-0.0.0.dev414.dist-info → omlish-0.0.0.dev416.dist-info}/METADATA +14 -9
- {omlish-0.0.0.dev414.dist-info → omlish-0.0.0.dev416.dist-info}/RECORD +65 -56
- omlish/inject/.dataclasses.json +0 -3
- omlish/marshal/.dataclasses.json +0 -3
- omlish/marshal/base.py +0 -472
- omlish/marshal/factories.py +0 -116
- omlish/marshal/proxy.py +0 -26
- {omlish-0.0.0.dev414.dist-info → omlish-0.0.0.dev416.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev414.dist-info → omlish-0.0.0.dev416.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev414.dist-info → omlish-0.0.0.dev416.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev414.dist-info → omlish-0.0.0.dev416.dist-info}/top_level.txt +0 -0
omlish/lang/imports/proxyinit.py
CHANGED
@@ -183,6 +183,9 @@ class AutoProxyInitErrors:
|
|
183
183
|
def __repr__(self) -> str:
|
184
184
|
return f'{self.__class__.__qualname__}(unreferenced={self.unreferenced!r})'
|
185
185
|
|
186
|
+
class CaptureInProgressError(AutoProxyInitError):
|
187
|
+
pass
|
188
|
+
|
186
189
|
|
187
190
|
class _AutoProxyInitCapture:
|
188
191
|
class ModuleSpec(ta.NamedTuple):
|
@@ -418,20 +421,12 @@ class _AutoProxyInitCapture:
|
|
418
421
|
|
419
422
|
#
|
420
423
|
|
421
|
-
class ProxyInit(ta.NamedTuple):
|
422
|
-
package: str
|
423
|
-
attrs: ta.Sequence[tuple[str | None, str]]
|
424
|
-
|
425
|
-
class BuiltProxyInits(ta.NamedTuple):
|
426
|
-
proxy_inits: ta.Sequence['_AutoProxyInitCapture.ProxyInit']
|
427
|
-
unreferenced: ta.Mapping[str, ta.Sequence[str | None]] | None
|
428
|
-
|
429
424
|
def build_proxy_inits(
|
430
425
|
self,
|
431
426
|
init_globals: ta.MutableMapping[str, ta.Any], # noqa
|
432
427
|
*,
|
433
428
|
collect_unreferenced: bool = False,
|
434
|
-
) ->
|
429
|
+
) -> 'AutoProxyInit.CapturedProxyInits':
|
435
430
|
dct: dict[_AutoProxyInitCapture._Module, list[tuple[str | None, str]]] = {}
|
436
431
|
|
437
432
|
rem_whole_mods: set[_AutoProxyInitCapture._Module] = set()
|
@@ -462,7 +457,7 @@ class _AutoProxyInitCapture:
|
|
462
457
|
dct.setdefault(m, []).append((None, attr))
|
463
458
|
rem_whole_mods.discard(m)
|
464
459
|
|
465
|
-
lst: list[
|
460
|
+
lst: list[AutoProxyInit.ProxyInit] = []
|
466
461
|
for m, ts in dct.items():
|
467
462
|
if not m.spec.name:
|
468
463
|
if not m.spec.level:
|
@@ -470,13 +465,13 @@ class _AutoProxyInitCapture:
|
|
470
465
|
for imp_attr, as_attr in ts:
|
471
466
|
if not imp_attr:
|
472
467
|
raise RuntimeError
|
473
|
-
lst.append(
|
468
|
+
lst.append(AutoProxyInit.ProxyInit(
|
474
469
|
'.' * m.spec.level + imp_attr,
|
475
470
|
[(None, as_attr)],
|
476
471
|
))
|
477
472
|
|
478
473
|
else:
|
479
|
-
lst.append(
|
474
|
+
lst.append(AutoProxyInit.ProxyInit(
|
480
475
|
str(m.spec),
|
481
476
|
ts,
|
482
477
|
))
|
@@ -490,12 +485,152 @@ class _AutoProxyInitCapture:
|
|
490
485
|
m, a = self._attrs[ma]
|
491
486
|
unreferenced.setdefault(str(m.spec), []).append(a)
|
492
487
|
|
493
|
-
return
|
488
|
+
return AutoProxyInit.CapturedProxyInits(
|
494
489
|
lst,
|
495
490
|
unreferenced,
|
496
491
|
)
|
497
492
|
|
498
493
|
|
494
|
+
class AutoProxyInit:
|
495
|
+
class ProxyInit(ta.NamedTuple):
|
496
|
+
package: str
|
497
|
+
attrs: ta.Sequence[tuple[str | None, str]]
|
498
|
+
|
499
|
+
class CapturedProxyInits(ta.NamedTuple):
|
500
|
+
proxy_inits: ta.Sequence['AutoProxyInit.ProxyInit']
|
501
|
+
unreferenced: ta.Mapping[str, ta.Sequence[str | None]] | None
|
502
|
+
|
503
|
+
@property
|
504
|
+
def attrs(self) -> ta.Iterator[str]:
|
505
|
+
for pi in self.proxy_inits:
|
506
|
+
for _, a in pi.attrs:
|
507
|
+
yield a
|
508
|
+
|
509
|
+
#
|
510
|
+
|
511
|
+
def __init__(
|
512
|
+
self,
|
513
|
+
init_globals: ta.MutableMapping[str, ta.Any],
|
514
|
+
*,
|
515
|
+
disable: bool,
|
516
|
+
eager: bool,
|
517
|
+
) -> None:
|
518
|
+
super().__init__()
|
519
|
+
|
520
|
+
self._init_globals = init_globals
|
521
|
+
|
522
|
+
self._disable = disable
|
523
|
+
self._eager = eager
|
524
|
+
|
525
|
+
@property
|
526
|
+
def disable(self) -> bool:
|
527
|
+
return self._disable
|
528
|
+
|
529
|
+
@property
|
530
|
+
def eager(self) -> bool:
|
531
|
+
return self._eager
|
532
|
+
|
533
|
+
#
|
534
|
+
|
535
|
+
class _Result(ta.NamedTuple):
|
536
|
+
captured: 'AutoProxyInit.CapturedProxyInits'
|
537
|
+
|
538
|
+
_result_: _Result | None = None
|
539
|
+
|
540
|
+
@property
|
541
|
+
def _result(self) -> _Result:
|
542
|
+
if (rs := self._result_) is None:
|
543
|
+
raise AutoProxyInitErrors.CaptureInProgressError
|
544
|
+
return rs
|
545
|
+
|
546
|
+
@property
|
547
|
+
def is_complete(self) -> bool:
|
548
|
+
return self._result_ is not None
|
549
|
+
|
550
|
+
@property
|
551
|
+
def captured(self) -> CapturedProxyInits:
|
552
|
+
return self._result.captured
|
553
|
+
|
554
|
+
#
|
555
|
+
|
556
|
+
@contextlib.contextmanager
|
557
|
+
def _capture(
|
558
|
+
self,
|
559
|
+
*,
|
560
|
+
unreferenced_callback: ta.Callable[[ta.Mapping[str, ta.Sequence[str | None]]], None] | None = None,
|
561
|
+
raise_unreferenced: bool = False,
|
562
|
+
) -> ta.Iterator[None]:
|
563
|
+
if self._result_ is not None:
|
564
|
+
raise AutoProxyInitError('capture already complete')
|
565
|
+
|
566
|
+
if self._disable:
|
567
|
+
self._result_ = AutoProxyInit._Result(
|
568
|
+
AutoProxyInit.CapturedProxyInits(
|
569
|
+
[],
|
570
|
+
None,
|
571
|
+
),
|
572
|
+
)
|
573
|
+
yield
|
574
|
+
return
|
575
|
+
|
576
|
+
cap = _AutoProxyInitCapture()
|
577
|
+
|
578
|
+
with cap.hook_context(self._init_globals):
|
579
|
+
yield
|
580
|
+
|
581
|
+
cap.verify_state(self._init_globals)
|
582
|
+
|
583
|
+
blt = cap.build_proxy_inits(
|
584
|
+
self._init_globals,
|
585
|
+
collect_unreferenced=unreferenced_callback is not None or raise_unreferenced,
|
586
|
+
)
|
587
|
+
|
588
|
+
if blt.unreferenced:
|
589
|
+
if unreferenced_callback:
|
590
|
+
unreferenced_callback(blt.unreferenced)
|
591
|
+
if raise_unreferenced:
|
592
|
+
raise AutoProxyInitErrors.UnreferencedImportsError(blt.unreferenced)
|
593
|
+
|
594
|
+
for pi in blt.proxy_inits:
|
595
|
+
for _, a in pi.attrs:
|
596
|
+
del self._init_globals[a]
|
597
|
+
|
598
|
+
proxy_init(
|
599
|
+
self._init_globals,
|
600
|
+
pi.package,
|
601
|
+
pi.attrs,
|
602
|
+
)
|
603
|
+
|
604
|
+
if self._eager:
|
605
|
+
lg = LazyGlobals.install(self._init_globals)
|
606
|
+
|
607
|
+
for a in blt.attrs:
|
608
|
+
lg.get(a)
|
609
|
+
|
610
|
+
self._result_ = AutoProxyInit._Result(
|
611
|
+
blt,
|
612
|
+
)
|
613
|
+
|
614
|
+
#
|
615
|
+
|
616
|
+
def update_exports(self) -> None:
|
617
|
+
cap = self._result.captured
|
618
|
+
|
619
|
+
try:
|
620
|
+
al: ta.Any = self._init_globals['__all__']
|
621
|
+
except KeyError:
|
622
|
+
al = self._init_globals['__all__'] = [k for k in self._init_globals if not k.startswith('_')]
|
623
|
+
else:
|
624
|
+
if not isinstance(al, ta.MutableSequence):
|
625
|
+
al = self._init_globals['__all__'] = list(al)
|
626
|
+
|
627
|
+
al_s = set(al)
|
628
|
+
for a in cap.attrs:
|
629
|
+
if a not in al_s:
|
630
|
+
al.append(a)
|
631
|
+
al_s.add(a)
|
632
|
+
|
633
|
+
|
499
634
|
@contextlib.contextmanager
|
500
635
|
def auto_proxy_init(
|
501
636
|
init_globals: ta.MutableMapping[str, ta.Any],
|
@@ -505,48 +640,26 @@ def auto_proxy_init(
|
|
505
640
|
|
506
641
|
unreferenced_callback: ta.Callable[[ta.Mapping[str, ta.Sequence[str | None]]], None] | None = None,
|
507
642
|
raise_unreferenced: bool = False,
|
508
|
-
|
643
|
+
|
644
|
+
update_exports: bool = False,
|
645
|
+
) -> ta.Iterator[AutoProxyInit]:
|
509
646
|
"""
|
510
647
|
This is a bit extreme - use sparingly. It relies on an interpreter-global import lock, but much of the ecosystem
|
511
648
|
implicitly does anyway. It further relies on temporarily patching `__builtins__.__import__`, but could be switched
|
512
649
|
to use any number of other import hooks.
|
513
650
|
"""
|
514
651
|
|
515
|
-
|
516
|
-
yield
|
517
|
-
return
|
518
|
-
|
519
|
-
cap = _AutoProxyInitCapture()
|
520
|
-
|
521
|
-
with cap.hook_context(init_globals):
|
522
|
-
yield
|
523
|
-
|
524
|
-
cap.verify_state(init_globals)
|
525
|
-
|
526
|
-
blt = cap.build_proxy_inits(
|
652
|
+
inst = AutoProxyInit(
|
527
653
|
init_globals,
|
528
|
-
|
654
|
+
disable=disable,
|
655
|
+
eager=eager,
|
529
656
|
)
|
530
657
|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
for pi in blt.proxy_inits:
|
538
|
-
for _, a in pi.attrs:
|
539
|
-
del init_globals[a]
|
540
|
-
|
541
|
-
proxy_init(
|
542
|
-
init_globals,
|
543
|
-
pi.package,
|
544
|
-
pi.attrs,
|
545
|
-
)
|
546
|
-
|
547
|
-
if eager:
|
548
|
-
lg = LazyGlobals.install(init_globals)
|
658
|
+
with inst._capture( # noqa
|
659
|
+
unreferenced_callback=unreferenced_callback,
|
660
|
+
raise_unreferenced=raise_unreferenced,
|
661
|
+
):
|
662
|
+
yield inst
|
549
663
|
|
550
|
-
|
551
|
-
|
552
|
-
lg.get(a)
|
664
|
+
if update_exports:
|
665
|
+
inst.update_exports()
|
omlish/lang/maybes.py
ADDED
omlish/lite/maysyncs.py
CHANGED
omlish/manifests/base.py
CHANGED
omlish/marshal/__init__.py
CHANGED
@@ -1,4 +1,48 @@
|
|
1
|
-
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- redacted
|
4
|
+
- strongly typed MarshalerFactory base class?
|
5
|
+
- strongly typed Composite/Cached Marshaler/Unmarshaler factories - footgun
|
6
|
+
- streaming? Start/EndObject, etc..
|
7
|
+
- lang.Marker - class name, handle type[Foo]
|
8
|
+
- can't disambiguate from str - can't coexist in bare union
|
9
|
+
- factories being free MatchFns does more harm than good - in practice these are such big guns you want to write a
|
10
|
+
class body if only ceremonially
|
11
|
+
|
12
|
+
See:
|
13
|
+
- https://github.com/python-attrs/cattrs
|
14
|
+
- https://github.com/jcrist/msgspec
|
15
|
+
- https://github.com/Fatal1ty/mashumaro
|
16
|
+
- https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#custom-serializers
|
17
|
+
"""
|
18
|
+
|
19
|
+
|
20
|
+
from .base.contexts import ( # noqa
|
21
|
+
BaseContext,
|
22
|
+
MarshalContext,
|
23
|
+
UnmarshalContext,
|
24
|
+
)
|
25
|
+
|
26
|
+
from .base.errors import ( # noqa
|
27
|
+
ForbiddenTypeError,
|
28
|
+
MarshalError,
|
29
|
+
UnhandledTypeError,
|
30
|
+
)
|
31
|
+
|
32
|
+
from .base.options import ( # noqa
|
33
|
+
Option,
|
34
|
+
)
|
35
|
+
|
36
|
+
from .base.overrides import ( # noqa
|
37
|
+
Override,
|
38
|
+
ReflectOverride,
|
39
|
+
)
|
40
|
+
|
41
|
+
from .base.registries import ( # noqa
|
42
|
+
Registry,
|
43
|
+
)
|
44
|
+
|
45
|
+
from .base.types import ( # noqa
|
2
46
|
Marshaler,
|
3
47
|
Unmarshaler,
|
4
48
|
|
@@ -10,67 +54,55 @@ from .base import ( # noqa
|
|
10
54
|
|
11
55
|
MarshalerFactory_,
|
12
56
|
UnmarshalerFactory_,
|
57
|
+
)
|
58
|
+
|
59
|
+
from .base.values import ( # noqa
|
60
|
+
Value,
|
61
|
+
)
|
13
62
|
|
63
|
+
from .composite.iterables import ( # noqa
|
64
|
+
IterableMarshaler,
|
65
|
+
IterableUnmarshaler,
|
66
|
+
)
|
67
|
+
|
68
|
+
from .composite.wrapped import ( # noqa
|
69
|
+
WrappedMarshaler,
|
70
|
+
WrappedUnmarshaler,
|
71
|
+
)
|
72
|
+
|
73
|
+
from .factories.simple import ( # noqa
|
14
74
|
SimpleMarshalerFactory,
|
15
75
|
SimpleUnmarshalerFactory,
|
76
|
+
)
|
16
77
|
|
78
|
+
from .factories.match import ( # noqa
|
17
79
|
MarshalerFactoryMatchClass,
|
18
80
|
UnmarshalerFactoryMatchClass,
|
81
|
+
)
|
19
82
|
|
83
|
+
from .factories.multi import ( # noqa
|
20
84
|
MultiMarshalerFactory,
|
21
85
|
MultiUnmarshalerFactory,
|
86
|
+
)
|
22
87
|
|
88
|
+
from .factories.typemap import ( # noqa
|
23
89
|
TypeMapMarshalerFactory,
|
24
90
|
TypeMapUnmarshalerFactory,
|
91
|
+
)
|
25
92
|
|
93
|
+
from .factories.typecache import ( # noqa
|
26
94
|
TypeCacheMarshalerFactory,
|
27
95
|
TypeCacheUnmarshalerFactory,
|
96
|
+
)
|
28
97
|
|
98
|
+
from .factories.func import ( # noqa
|
29
99
|
FuncMarshaler,
|
30
100
|
FuncUnmarshaler,
|
101
|
+
)
|
31
102
|
|
32
|
-
|
33
|
-
MarshalContext,
|
34
|
-
UnmarshalContext,
|
35
|
-
|
103
|
+
from .factories.recursive import ( # noqa
|
36
104
|
RecursiveMarshalerFactory,
|
37
105
|
RecursiveUnmarshalerFactory,
|
38
|
-
|
39
|
-
Override,
|
40
|
-
ReflectOverride,
|
41
|
-
)
|
42
|
-
|
43
|
-
from .composite.iterables import ( # noqa
|
44
|
-
IterableMarshaler,
|
45
|
-
IterableUnmarshaler,
|
46
|
-
)
|
47
|
-
|
48
|
-
from .composite.wrapped import ( # noqa
|
49
|
-
WrappedMarshaler,
|
50
|
-
WrappedUnmarshaler,
|
51
|
-
)
|
52
|
-
|
53
|
-
from .errors import ( # noqa
|
54
|
-
ForbiddenTypeError,
|
55
|
-
MarshalError,
|
56
|
-
UnhandledTypeError,
|
57
|
-
)
|
58
|
-
|
59
|
-
from .globals import ( # noqa
|
60
|
-
GLOBAL_REGISTRY,
|
61
|
-
|
62
|
-
global_marshaler_factory,
|
63
|
-
marshal,
|
64
|
-
|
65
|
-
global_unmarshaler_factory,
|
66
|
-
unmarshal,
|
67
|
-
|
68
|
-
register_global,
|
69
|
-
)
|
70
|
-
|
71
|
-
from .naming import ( # noqa
|
72
|
-
Naming,
|
73
|
-
translate_name,
|
74
106
|
)
|
75
107
|
|
76
108
|
from .objects.dataclasses import ( # noqa
|
@@ -152,20 +184,6 @@ from .singular.primitives import ( # noqa
|
|
152
184
|
PRIMITIVE_TYPES,
|
153
185
|
)
|
154
186
|
|
155
|
-
from .registries import ( # noqa
|
156
|
-
Registry,
|
157
|
-
)
|
158
|
-
|
159
|
-
from .standard import ( # noqa
|
160
|
-
STANDARD_MARSHALER_FACTORIES,
|
161
|
-
new_standard_marshaler_factory,
|
162
|
-
|
163
|
-
STANDARD_UNMARSHALER_FACTORIES,
|
164
|
-
new_standard_unmarshaler_factory,
|
165
|
-
|
166
|
-
install_standard_factories,
|
167
|
-
)
|
168
|
-
|
169
187
|
from .trivial.forbidden import ( # noqa
|
170
188
|
ForbiddenTypeMarshalerFactory,
|
171
189
|
ForbiddenTypeUnmarshalerFactory,
|
@@ -176,8 +194,31 @@ from .trivial.nop import ( # noqa
|
|
176
194
|
NopMarshalerUnmarshaler,
|
177
195
|
)
|
178
196
|
|
179
|
-
from .
|
180
|
-
|
197
|
+
from .globals import ( # noqa
|
198
|
+
global_registry,
|
199
|
+
global_marshaler_factory,
|
200
|
+
global_unmarshaler_factory,
|
201
|
+
global_marshaling,
|
202
|
+
|
203
|
+
marshal,
|
204
|
+
unmarshal,
|
205
|
+
|
206
|
+
register_global,
|
207
|
+
)
|
208
|
+
|
209
|
+
from .naming import ( # noqa
|
210
|
+
Naming,
|
211
|
+
translate_name,
|
212
|
+
)
|
213
|
+
|
214
|
+
from .standard import ( # noqa
|
215
|
+
STANDARD_MARSHALER_FACTORIES,
|
216
|
+
new_standard_marshaler_factory,
|
217
|
+
|
218
|
+
STANDARD_UNMARSHALER_FACTORIES,
|
219
|
+
new_standard_unmarshaler_factory,
|
220
|
+
|
221
|
+
install_standard_factories,
|
181
222
|
)
|
182
223
|
|
183
224
|
|
File without changes
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from ... import check
|
4
|
+
from ... import collections as col
|
5
|
+
from ... import dataclasses as dc
|
6
|
+
from ... import lang
|
7
|
+
from ... import reflect as rfl
|
8
|
+
from ...funcs import match as mfs
|
9
|
+
from .errors import UnhandledTypeError
|
10
|
+
from .options import Option
|
11
|
+
from .overrides import ReflectOverride
|
12
|
+
|
13
|
+
|
14
|
+
if ta.TYPE_CHECKING:
|
15
|
+
from .registries import Registry
|
16
|
+
from .types import Marshaler
|
17
|
+
from .types import MarshalerFactory
|
18
|
+
from .types import Unmarshaler
|
19
|
+
from .types import UnmarshalerFactory
|
20
|
+
from .values import Value
|
21
|
+
|
22
|
+
|
23
|
+
T = ta.TypeVar('T')
|
24
|
+
|
25
|
+
|
26
|
+
##
|
27
|
+
|
28
|
+
|
29
|
+
@dc.dataclass(frozen=True)
|
30
|
+
class BaseContext(lang.Abstract):
|
31
|
+
registry: 'Registry'
|
32
|
+
options: col.TypeMap[Option] = col.TypeMap()
|
33
|
+
|
34
|
+
def _reflect(self, o: ta.Any) -> rfl.Type:
|
35
|
+
def override(o):
|
36
|
+
if (ovr := self.registry.get_of(o, ReflectOverride)):
|
37
|
+
return ovr[-1].rty
|
38
|
+
return None
|
39
|
+
|
40
|
+
return rfl.Reflector(override=override).type(o)
|
41
|
+
|
42
|
+
|
43
|
+
@dc.dataclass(frozen=True)
|
44
|
+
class MarshalContext(BaseContext, lang.Final):
|
45
|
+
factory: ta.Optional['MarshalerFactory'] = None
|
46
|
+
|
47
|
+
def make(self, o: ta.Any) -> 'Marshaler':
|
48
|
+
rty = self._reflect(o)
|
49
|
+
try:
|
50
|
+
return check.not_none(self.factory).make_marshaler(self, rty)
|
51
|
+
except mfs.MatchGuardError:
|
52
|
+
raise UnhandledTypeError(rty) # noqa
|
53
|
+
|
54
|
+
def marshal(self, obj: ta.Any, ty: ta.Any | None = None) -> 'Value':
|
55
|
+
return self.make(ty if ty is not None else type(obj)).marshal(self, obj)
|
56
|
+
|
57
|
+
|
58
|
+
@dc.dataclass(frozen=True)
|
59
|
+
class UnmarshalContext(BaseContext, lang.Final):
|
60
|
+
factory: ta.Optional['UnmarshalerFactory'] = None
|
61
|
+
|
62
|
+
def make(self, o: ta.Any) -> 'Unmarshaler':
|
63
|
+
rty = self._reflect(o)
|
64
|
+
try:
|
65
|
+
return check.not_none(self.factory).make_unmarshaler(self, rty)
|
66
|
+
except mfs.MatchGuardError:
|
67
|
+
raise UnhandledTypeError(rty) # noqa
|
68
|
+
|
69
|
+
@ta.overload
|
70
|
+
def unmarshal(self, v: 'Value', ty: type[T]) -> T:
|
71
|
+
...
|
72
|
+
|
73
|
+
@ta.overload
|
74
|
+
def unmarshal(self, v: 'Value', ty: ta.Any) -> ta.Any:
|
75
|
+
...
|
76
|
+
|
77
|
+
def unmarshal(self, v, ty):
|
78
|
+
return self.make(ty).unmarshal(self, v)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from ... import dataclasses as dc
|
4
|
+
from ... import lang
|
5
|
+
from ... import reflect as rfl
|
6
|
+
from .registries import RegistryItem
|
7
|
+
|
8
|
+
|
9
|
+
if ta.TYPE_CHECKING:
|
10
|
+
from . import types as _types
|
11
|
+
from .types import Marshaler
|
12
|
+
from .types import MarshalerFactory
|
13
|
+
from .types import Unmarshaler
|
14
|
+
from .types import UnmarshalerFactory
|
15
|
+
|
16
|
+
else:
|
17
|
+
_types = lang.proxy_import('.types', __package__)
|
18
|
+
|
19
|
+
|
20
|
+
##
|
21
|
+
|
22
|
+
|
23
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
24
|
+
class Override(RegistryItem, lang.Final):
|
25
|
+
marshaler: ta.Optional['Marshaler'] = dc.xfield(None, validate=lambda v: isinstance(v, (_types.Marshaler, type(None)))) # noqa
|
26
|
+
marshaler_factory: ta.Optional['MarshalerFactory'] = None
|
27
|
+
|
28
|
+
unmarshaler: ta.Optional['Unmarshaler'] = dc.xfield(None, validate=lambda v: isinstance(v, (_types.Unmarshaler, type(None)))) # noqa
|
29
|
+
unmarshaler_factory: ta.Optional['UnmarshalerFactory'] = None
|
30
|
+
|
31
|
+
|
32
|
+
@dc.dataclass(frozen=True)
|
33
|
+
class ReflectOverride(RegistryItem, lang.Final):
|
34
|
+
rty: rfl.Type
|
@@ -1,13 +1,9 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- inheritance
|
4
|
-
"""
|
5
1
|
import dataclasses as dc
|
6
2
|
import threading
|
7
3
|
import typing as ta
|
8
4
|
|
9
|
-
from
|
10
|
-
from
|
5
|
+
from ... import collections as col
|
6
|
+
from ... import lang
|
11
7
|
|
12
8
|
|
13
9
|
##
|
@@ -33,10 +29,16 @@ class _KeyRegistryItems:
|
|
33
29
|
|
34
30
|
|
35
31
|
class Registry:
|
36
|
-
def __init__(
|
32
|
+
def __init__(
|
33
|
+
self,
|
34
|
+
*,
|
35
|
+
lock: ta.Optional[threading.RLock] = None, # noqa
|
36
|
+
) -> None:
|
37
37
|
super().__init__()
|
38
38
|
|
39
|
-
|
39
|
+
if lock is None:
|
40
|
+
lock = threading.RLock()
|
41
|
+
self._lock = lock
|
40
42
|
self._idct: ta.MutableMapping[ta.Any, _KeyRegistryItems] = col.IdentityKeyDict()
|
41
43
|
self._dct: dict[ta.Any, _KeyRegistryItems] = {}
|
42
44
|
|
@@ -46,7 +48,7 @@ class Registry:
|
|
46
48
|
*items: RegistryItem,
|
47
49
|
identity: bool = False,
|
48
50
|
) -> 'Registry':
|
49
|
-
with self.
|
51
|
+
with self._lock:
|
50
52
|
dct: ta.Any = self._idct if identity else self._dct
|
51
53
|
if (sr := dct.get(key)) is None:
|
52
54
|
sr = dct[key] = _KeyRegistryItems(key)
|