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
@@ -8,9 +8,9 @@ import copy
|
|
8
8
|
import dataclasses as dc
|
9
9
|
import typing as ta
|
10
10
|
|
11
|
-
from
|
12
|
-
from
|
13
|
-
from .
|
11
|
+
from ... import lang
|
12
|
+
from ...lite.dataclasses import is_immediate_dataclass
|
13
|
+
from ..api.classes.decorator import dataclass
|
14
14
|
|
15
15
|
|
16
16
|
##
|
@@ -122,6 +122,27 @@ class Static(lang.Abstract):
|
|
122
122
|
# Use a default_factory to allow unsafe (mutable) values.
|
123
123
|
new_fld.default_factory = (lambda v2: lambda: v2)(v) # noqa
|
124
124
|
|
125
|
+
# FIXME
|
126
|
+
from ..api.fields.metadata import _ExtraFieldParamsMetadata # noqa
|
127
|
+
from ..specs import FieldSpec
|
128
|
+
try:
|
129
|
+
x_fs = fld.metadata[FieldSpec]
|
130
|
+
except KeyError:
|
131
|
+
pass
|
132
|
+
else:
|
133
|
+
n_md = {
|
134
|
+
k: v
|
135
|
+
for k, v in fld.metadata.items()
|
136
|
+
if k not in (FieldSpec, _ExtraFieldParamsMetadata)
|
137
|
+
}
|
138
|
+
n_md[_ExtraFieldParamsMetadata] = {
|
139
|
+
fs_f.name: getattr(x_fs, fs_f.name)
|
140
|
+
for fs_f in dc.fields(FieldSpec) # noqa
|
141
|
+
if fs_f not in dc.Field.__slots__ # type: ignore[attr-defined]
|
142
|
+
and fs_f.name not in ('default', 'default_factory')
|
143
|
+
}
|
144
|
+
new_fld.metadata = n_md # type: ignore[assignment]
|
145
|
+
|
125
146
|
setattr(cls, fld.name, new_fld)
|
126
147
|
new_anns[fld.name] = fld.type
|
127
148
|
|
@@ -144,7 +165,7 @@ class Static(lang.Abstract):
|
|
144
165
|
)
|
145
166
|
|
146
167
|
# Explicitly forbid dc transforms that rebuild the class, such as slots.
|
147
|
-
if (dc_cls := dataclass(
|
168
|
+
if (dc_cls := dataclass(frozen=True)(cls)) is not cls:
|
148
169
|
raise TypeError(dc_cls)
|
149
170
|
|
150
171
|
dc_flds = dc.fields(cls) # type: ignore[arg-type] # noqa
|
omlish/dataclasses/utils.py
CHANGED
@@ -1,153 +1,98 @@
|
|
1
|
+
import ast
|
1
2
|
import collections
|
2
|
-
import
|
3
|
+
import functools
|
3
4
|
import types
|
4
5
|
import typing as ta
|
5
6
|
|
6
7
|
from .. import check
|
7
|
-
from .impl.metadata import METADATA_ATTR
|
8
|
-
from .impl.metadata import UserMetadata
|
9
|
-
from .impl.params import DEFAULT_FIELD_EXTRAS
|
10
|
-
from .impl.params import FieldExtras
|
11
|
-
from .impl.params import get_field_extras
|
12
8
|
|
13
9
|
|
14
10
|
T = ta.TypeVar('T')
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
def opt_repr(o: ta.Any) -> str | None:
|
21
|
-
return repr(o) if o is not None else None
|
22
|
-
|
23
|
-
|
24
|
-
def truthy_repr(o: ta.Any) -> str | None:
|
25
|
-
return repr(o) if o else None
|
12
|
+
K = ta.TypeVar('K')
|
13
|
+
V = ta.TypeVar('V')
|
26
14
|
|
27
15
|
|
28
16
|
##
|
29
17
|
|
30
18
|
|
31
|
-
def
|
32
|
-
|
19
|
+
def repr_round_trip_value(v: T) -> T:
|
20
|
+
r = repr(v)
|
21
|
+
v2 = ast.literal_eval(r)
|
22
|
+
if v != v2:
|
23
|
+
raise ValueError(v)
|
24
|
+
return v2
|
33
25
|
|
34
26
|
|
35
27
|
##
|
36
28
|
|
37
29
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
30
|
+
def set_qualname(cls: type, value: T) -> T:
|
31
|
+
if isinstance(value, types.FunctionType):
|
32
|
+
value.__qualname__ = f'{cls.__qualname__}.{value.__name__}'
|
33
|
+
return value
|
42
34
|
|
43
|
-
def __ror__(self, other: T) -> T:
|
44
|
-
return self(other)
|
45
35
|
|
46
|
-
|
47
|
-
|
36
|
+
def set_new_attribute(cls: type, name: str, value: ta.Any) -> bool:
|
37
|
+
if name in cls.__dict__:
|
38
|
+
return True
|
39
|
+
set_qualname(cls, value)
|
40
|
+
setattr(cls, name, value)
|
41
|
+
return False
|
48
42
|
|
49
43
|
|
50
|
-
|
51
|
-
return types.MappingProxyType(collections.ChainMap(*mds)) # type: ignore # noqa
|
44
|
+
##
|
52
45
|
|
53
46
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
md.setdefault(UserMetadata, []).extend(args)
|
58
|
-
return cls
|
47
|
+
class SealableRegistry(ta.Generic[K, V]):
|
48
|
+
def __init__(self) -> None:
|
49
|
+
super().__init__()
|
59
50
|
|
51
|
+
self._dct: dict[K, V] = {}
|
52
|
+
self._sealed = False
|
60
53
|
|
61
|
-
def
|
62
|
-
|
63
|
-
f.metadata = chain_metadata(nmd, f.metadata)
|
64
|
-
return f
|
54
|
+
def seal(self) -> None:
|
55
|
+
self._sealed = True
|
65
56
|
|
57
|
+
def __setitem__(self, k: K, v: V) -> None:
|
58
|
+
check.state(not self._sealed)
|
59
|
+
check.not_in(k, self._dct)
|
60
|
+
self._dct[k] = v
|
66
61
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
FieldExtras: dc.replace(fe, **{
|
71
|
-
k: v
|
72
|
-
for k, v in kwargs.items()
|
73
|
-
if not unless_non_default or v != getattr(DEFAULT_FIELD_EXTRAS, k)
|
74
|
-
}),
|
75
|
-
})
|
62
|
+
def __getitem__(self, k: K) -> V:
|
63
|
+
self.seal()
|
64
|
+
return self._dct[k]
|
76
65
|
|
66
|
+
def items(self) -> ta.Iterator[tuple[K, V]]:
|
67
|
+
self.seal()
|
68
|
+
return iter(self._dct.items())
|
77
69
|
|
78
|
-
def update_fields(
|
79
|
-
fn: ta.Callable[[str, dc.Field], dc.Field],
|
80
|
-
fields: ta.Iterable[str] | None = None,
|
81
|
-
) -> ta.Callable[[type[T]], type[T]]:
|
82
|
-
def inner(cls):
|
83
|
-
if fields is None:
|
84
|
-
for a, v in list(cls.__dict__.items()):
|
85
|
-
if isinstance(v, dc.Field):
|
86
|
-
setattr(cls, a, fn(a, v))
|
87
70
|
|
88
|
-
|
89
|
-
for a in fields:
|
90
|
-
try:
|
91
|
-
v = cls.__dict__[a]
|
92
|
-
except KeyError:
|
93
|
-
v = dc.field()
|
94
|
-
else:
|
95
|
-
if not isinstance(v, dc.Field):
|
96
|
-
v = dc.field(default=v)
|
97
|
-
setattr(cls, a, fn(a, v))
|
71
|
+
##
|
98
72
|
|
99
|
-
return cls
|
100
73
|
|
101
|
-
|
74
|
+
def class_decorator(fn):
|
75
|
+
@functools.wraps(fn)
|
76
|
+
def inner(cls=None, *args, **kwargs):
|
77
|
+
if cls is None:
|
78
|
+
return lambda cls: fn(cls, *args, **kwargs) # noqa
|
79
|
+
return fn(cls, *args, **kwargs)
|
102
80
|
return inner
|
103
81
|
|
104
82
|
|
105
|
-
def update_fields_metadata(
|
106
|
-
nmd: ta.Mapping,
|
107
|
-
fields: ta.Iterable[str] | None = None,
|
108
|
-
) -> ta.Callable[[type[T]], type[T]]:
|
109
|
-
def inner(a: str, f: dc.Field) -> dc.Field:
|
110
|
-
return update_field_metadata(f, nmd)
|
111
|
-
|
112
|
-
return update_fields(inner, fields)
|
113
|
-
|
114
|
-
|
115
83
|
##
|
116
84
|
|
117
85
|
|
118
|
-
|
119
|
-
return tuple(getattr(o, f.name) for f in dc.fields(o))
|
86
|
+
_EMPTY_MAPPING_PROXY: ta.Mapping = types.MappingProxyType({})
|
120
87
|
|
121
88
|
|
122
|
-
def
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
def deep_replace(o: T, *args: str | ta.Callable[[ta.Any], ta.Mapping[str, ta.Any]]) -> T:
|
130
|
-
if not args:
|
131
|
-
return o
|
132
|
-
elif len(args) == 1:
|
133
|
-
return dc.replace(o, **args[0](o)) # type: ignore
|
89
|
+
def chain_mapping_proxy(*ms: ta.Mapping) -> types.MappingProxyType:
|
90
|
+
m: ta.Any
|
91
|
+
if len(ms) > 1:
|
92
|
+
m = collections.ChainMap(*ms) # type: ignore[arg-type]
|
93
|
+
elif ms:
|
94
|
+
[m] = ms
|
134
95
|
else:
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
##
|
139
|
-
|
140
|
-
|
141
|
-
def iter_items(obj: ta.Any) -> ta.Iterator[tuple[str, ta.Any]]:
|
142
|
-
for f in dc.fields(obj):
|
143
|
-
yield (f.name, getattr(obj, f.name))
|
144
|
-
|
145
|
-
|
146
|
-
def iter_keys(obj: ta.Any) -> ta.Iterator[str]:
|
147
|
-
for f in dc.fields(obj):
|
148
|
-
yield f.name
|
149
|
-
|
96
|
+
m = _EMPTY_MAPPING_PROXY
|
150
97
|
|
151
|
-
|
152
|
-
for f in dc.fields(obj):
|
153
|
-
yield getattr(obj, f.name)
|
98
|
+
return types.MappingProxyType(m)
|
omlish/diag/__init__.py
CHANGED
@@ -17,10 +17,10 @@ Debuggers
|
|
17
17
|
|
18
18
|
CPU Profilers
|
19
19
|
- cProfile - https://docs.python.org/3/library/profile.html
|
20
|
-
-
|
21
|
-
-
|
22
|
-
-
|
23
|
-
-
|
20
|
+
- yappi - https://github.com/sumerc/yappi - tracing
|
21
|
+
- pyinstrument - https://github.com/joerick/pyinstrument - pretty
|
22
|
+
- py-spy - https://github.com/benfred/py-spy - busted on mac
|
23
|
+
- austin-dist - https://github.com/P403n1x87/austin - old
|
24
24
|
|
25
25
|
Memory Profilers
|
26
26
|
- tracemalloc - https://docs.python.org/3/library/tracemalloc.html
|
omlish/inject/bindings.py
CHANGED
@@ -12,7 +12,7 @@ from .types import Unscoped
|
|
12
12
|
|
13
13
|
|
14
14
|
@dc.dataclass(frozen=True)
|
15
|
-
@dc.
|
15
|
+
@dc.extra_class_params(cache_hash=True)
|
16
16
|
class Binding(Element, lang.Final):
|
17
17
|
key: Key = dc.xfield(coerce=check.of_isinstance(Key))
|
18
18
|
provider: Provider = dc.xfield(coerce=check.of_isinstance(Provider))
|
omlish/inject/eagers.py
CHANGED
omlish/inject/impl/bindings.py
CHANGED
omlish/inject/impl/origins.py
CHANGED
omlish/inject/keys.py
CHANGED
omlish/inject/listeners.py
CHANGED
omlish/inject/multis.py
CHANGED
@@ -30,14 +30,14 @@ def _check_set_multi_key(mk: Key) -> bool:
|
|
30
30
|
|
31
31
|
|
32
32
|
@dc.dataclass(frozen=True)
|
33
|
-
@dc.
|
33
|
+
@dc.extra_class_params(cache_hash=True)
|
34
34
|
class SetBinding(Element, lang.Final):
|
35
35
|
multi_key: Key = dc.xfield(validate=_check_set_multi_key)
|
36
36
|
dst: Key = dc.xfield(coerce=check.of_isinstance(Key))
|
37
37
|
|
38
38
|
|
39
39
|
@dc.dataclass(frozen=True)
|
40
|
-
@dc.
|
40
|
+
@dc.extra_class_params(cache_hash=True)
|
41
41
|
class SetProvider(Provider):
|
42
42
|
multi_key: Key = dc.xfield(validate=_check_set_multi_key)
|
43
43
|
|
@@ -50,7 +50,7 @@ def _check_map_multi_key(mk: Key) -> bool:
|
|
50
50
|
|
51
51
|
|
52
52
|
@dc.dataclass(frozen=True)
|
53
|
-
@dc.
|
53
|
+
@dc.extra_class_params(cache_hash=True)
|
54
54
|
class MapBinding(Element, lang.Final):
|
55
55
|
multi_key: Key = dc.xfield(validate=_check_map_multi_key)
|
56
56
|
map_key: ta.Any = dc.xfield()
|
@@ -58,7 +58,7 @@ class MapBinding(Element, lang.Final):
|
|
58
58
|
|
59
59
|
|
60
60
|
@dc.dataclass(frozen=True)
|
61
|
-
@dc.
|
61
|
+
@dc.extra_class_params(cache_hash=True)
|
62
62
|
class MapProvider(Provider):
|
63
63
|
multi_key: Key = dc.xfield(validate=_check_map_multi_key)
|
64
64
|
|
omlish/inject/origins.py
CHANGED
@@ -12,13 +12,13 @@ T = ta.TypeVar('T')
|
|
12
12
|
|
13
13
|
|
14
14
|
@dc.dataclass(frozen=True)
|
15
|
-
@dc.
|
15
|
+
@dc.extra_class_params(cache_hash=True)
|
16
16
|
class Origin:
|
17
17
|
lst: ta.Sequence[str]
|
18
18
|
|
19
19
|
|
20
20
|
@dc.dataclass(frozen=True)
|
21
|
-
@dc.
|
21
|
+
@dc.extra_class_params(cache_hash=True)
|
22
22
|
class Origins:
|
23
23
|
lst: ta.Sequence[Origin]
|
24
24
|
|
omlish/inject/overrides.py
CHANGED
@@ -12,7 +12,7 @@ from .elements import as_elements
|
|
12
12
|
|
13
13
|
|
14
14
|
@dc.dataclass(frozen=True)
|
15
|
-
@dc.
|
15
|
+
@dc.extra_class_params(cache_hash=True)
|
16
16
|
class Overrides(Element, lang.Final):
|
17
17
|
ovr: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
|
18
18
|
src: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
|
omlish/inject/privates.py
CHANGED
@@ -13,13 +13,13 @@ from .keys import as_key
|
|
13
13
|
|
14
14
|
|
15
15
|
@dc.dataclass(frozen=True)
|
16
|
-
@dc.
|
16
|
+
@dc.extra_class_params(cache_hash=True)
|
17
17
|
class Expose(Element, lang.Final):
|
18
18
|
key: Key = dc.xfield(coerce=as_key)
|
19
19
|
|
20
20
|
|
21
21
|
@dc.dataclass(frozen=True)
|
22
|
-
@dc.
|
22
|
+
@dc.extra_class_params(cache_hash=True)
|
23
23
|
class Private(Element, lang.Final):
|
24
24
|
elements: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
|
25
25
|
|
omlish/inject/providers.py
CHANGED
@@ -18,24 +18,24 @@ class Provider(lang.Abstract):
|
|
18
18
|
|
19
19
|
|
20
20
|
@dc.dataclass(frozen=True)
|
21
|
-
@dc.
|
21
|
+
@dc.extra_class_params(cache_hash=True)
|
22
22
|
class FnProvider(Provider):
|
23
23
|
fn: ta.Any = dc.xfield(validate=callable)
|
24
24
|
|
25
25
|
|
26
26
|
@dc.dataclass(frozen=True)
|
27
|
-
@dc.
|
27
|
+
@dc.extra_class_params(cache_hash=True)
|
28
28
|
class CtorProvider(Provider):
|
29
29
|
ty: type = dc.xfield(coerce=check.of_isinstance(type))
|
30
30
|
|
31
31
|
|
32
32
|
@dc.dataclass(frozen=True)
|
33
|
-
@dc.
|
33
|
+
@dc.extra_class_params(cache_hash=True)
|
34
34
|
class ConstProvider(Provider):
|
35
35
|
v: ta.Any
|
36
36
|
|
37
37
|
|
38
38
|
@dc.dataclass(frozen=True)
|
39
|
-
@dc.
|
39
|
+
@dc.extra_class_params(cache_hash=True)
|
40
40
|
class LinkProvider(Provider):
|
41
41
|
k: Key = dc.xfield(coerce=check.of_isinstance(Key))
|
omlish/inject/scopes.py
CHANGED
@@ -27,7 +27,7 @@ SCOPE_ALIASES: dict[str, Scope] = {}
|
|
27
27
|
|
28
28
|
|
29
29
|
@dc.dataclass(frozen=True)
|
30
|
-
@dc.
|
30
|
+
@dc.extra_class_params(cache_hash=True)
|
31
31
|
class ScopeBinding(Element, lang.Final):
|
32
32
|
scope: Scope = dc.xfield(coerce=check.of_isinstance(Scope))
|
33
33
|
|
@@ -60,7 +60,7 @@ SCOPE_ALIASES['thread'] = ThreadScope()
|
|
60
60
|
|
61
61
|
|
62
62
|
@dc.dataclass(frozen=True)
|
63
|
-
@dc.
|
63
|
+
@dc.extra_class_params(cache_hash=True)
|
64
64
|
class SeededScope(Scope, lang.Final):
|
65
65
|
tag: ta.Any = dc.xfield(coerce=check.not_none)
|
66
66
|
|
@@ -71,7 +71,7 @@ class SeededScope(Scope, lang.Final):
|
|
71
71
|
|
72
72
|
|
73
73
|
@dc.dataclass(frozen=True)
|
74
|
-
@dc.
|
74
|
+
@dc.extra_class_params(cache_hash=True)
|
75
75
|
class ScopeSeededProvider(Provider):
|
76
76
|
ss: SeededScope = dc.xfield(coerce=check.of_isinstance(SeededScope))
|
77
77
|
key: Key = dc.xfield(coerce=check.of_isinstance(Key))
|
omlish/lang/__init__.py
CHANGED
@@ -166,6 +166,7 @@ from .generators import ( # noqa
|
|
166
166
|
)
|
167
167
|
|
168
168
|
from .imports import ( # noqa
|
169
|
+
LazyGlobals,
|
169
170
|
can_import,
|
170
171
|
get_real_module_name,
|
171
172
|
import_all,
|
@@ -201,11 +202,9 @@ from .maybes import ( # noqa
|
|
201
202
|
)
|
202
203
|
|
203
204
|
from .objects import ( # noqa
|
204
|
-
AttrRepr,
|
205
205
|
SimpleProxy,
|
206
206
|
anon_object,
|
207
207
|
arg_repr,
|
208
|
-
attr_repr,
|
209
208
|
can_weakref,
|
210
209
|
deep_subclasses,
|
211
210
|
dir_dict,
|
@@ -304,6 +303,11 @@ from ..lite.imports import ( # noqa
|
|
304
303
|
import_module_attr,
|
305
304
|
)
|
306
305
|
|
306
|
+
from ..lite.reprs import ( # noqa
|
307
|
+
AttrRepr,
|
308
|
+
attr_repr,
|
309
|
+
)
|
310
|
+
|
307
311
|
from ..lite.timeouts import ( # noqa
|
308
312
|
DeadlineTimeout,
|
309
313
|
InfiniteTimeout,
|
omlish/lang/cached/function.py
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
"""
|
2
2
|
TODO:
|
3
|
+
- !!! lighter weight bound methods
|
4
|
+
- keymaker overhead less important than not rebuilding a whole dc every __get__ on a new instance
|
3
5
|
- !! specialize nullary, explicit kwarg
|
6
|
+
- !! use c-backed functools.cache if possible
|
7
|
+
- also just riic
|
4
8
|
- !! reconcile A().f() with A.f(A())
|
5
9
|
- unbound descriptor *should* still hit instance cache
|
6
10
|
- integrate / expose with collections.cache
|
@@ -10,6 +14,7 @@ TODO:
|
|
10
14
|
- 'staticmethod' or effective equiv - which must resolve to the shared instance
|
11
15
|
- and must be transient?
|
12
16
|
- use __transient_dict__ to support common state nuking
|
17
|
+
- use __set_name__ ?
|
13
18
|
"""
|
14
19
|
import dataclasses as dc
|
15
20
|
import functools
|
@@ -146,11 +151,12 @@ def _make_cache_key_maker(
|
|
146
151
|
|
147
152
|
|
148
153
|
class _CachedFunction(ta.Generic[T], Abstract):
|
149
|
-
@dc.dataclass(frozen=True)
|
154
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
150
155
|
class Opts:
|
151
156
|
map_maker: ta.Callable[[], ta.MutableMapping] = dict
|
152
157
|
lock: DefaultLockable = None
|
153
158
|
transient: bool = False
|
159
|
+
no_wrapper_update: bool = False
|
154
160
|
|
155
161
|
def __init__(
|
156
162
|
self,
|
@@ -170,7 +176,8 @@ class _CachedFunction(ta.Generic[T], Abstract):
|
|
170
176
|
self._lock = default_lock(opts.lock, False)() if opts.lock is not None else None
|
171
177
|
self._values = values if values is not None else opts.map_maker()
|
172
178
|
self._value_fn = value_fn if value_fn is not None else fn
|
173
|
-
|
179
|
+
if not self._opts.no_wrapper_update:
|
180
|
+
functools.update_wrapper(self, fn)
|
174
181
|
|
175
182
|
@property
|
176
183
|
def _fn(self):
|
@@ -353,10 +360,14 @@ class _DescriptorCachedFunction(_CachedFunction[T]):
|
|
353
360
|
def cached_function(fn=None, **kwargs): # noqa
|
354
361
|
if fn is None:
|
355
362
|
return functools.partial(cached_function, **kwargs)
|
363
|
+
|
356
364
|
opts = _CachedFunction.Opts(**kwargs)
|
365
|
+
|
357
366
|
if isinstance(fn, staticmethod):
|
358
367
|
return _FreeCachedFunction(fn, opts=opts, value_fn=unwrap_func(fn))
|
368
|
+
|
359
369
|
scope = classmethod if isinstance(fn, classmethod) else None
|
370
|
+
|
360
371
|
return _DescriptorCachedFunction(fn, scope, opts=opts)
|
361
372
|
|
362
373
|
|
omlish/lang/cached/property.py
CHANGED
@@ -112,7 +112,9 @@ class _TransientCachedProperty(_CachedProperty):
|
|
112
112
|
def cached_property(fn=None, *, transient=False, **kwargs): # noqa
|
113
113
|
if fn is None:
|
114
114
|
return functools.partial(cached_property, transient=transient, **kwargs)
|
115
|
-
|
115
|
+
|
116
|
+
elif transient:
|
116
117
|
return _TransientCachedProperty(fn, **kwargs)
|
118
|
+
|
117
119
|
else:
|
118
120
|
return _DictCachedProperty(fn, **kwargs)
|