omlish 0.0.0.dev1__py3-none-any.whl → 0.0.0.dev2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/__about__.py +2 -2
- omlish/argparse.py +4 -4
- omlish/asyncs/anyio.py +62 -1
- omlish/asyncs/futures.py +6 -6
- omlish/c3.py +4 -4
- omlish/check.py +6 -6
- omlish/collections/__init__.py +98 -63
- omlish/collections/cache/descriptor.py +5 -5
- omlish/collections/cache/impl.py +4 -4
- omlish/collections/coerce.py +43 -43
- omlish/collections/frozen.py +3 -3
- omlish/collections/identity.py +1 -1
- omlish/collections/mappings.py +3 -3
- omlish/collections/ordered.py +1 -1
- omlish/collections/skiplist.py +6 -6
- omlish/collections/sorted.py +3 -3
- omlish/collections/treap.py +17 -17
- omlish/collections/treapmap.py +2 -2
- omlish/collections/unmodifiable.py +28 -27
- omlish/configs/flattening.py +1 -1
- omlish/configs/props.py +1 -1
- omlish/dataclasses/impl/__init__.py +2 -0
- omlish/dataclasses/impl/api.py +5 -13
- omlish/dataclasses/impl/fields.py +1 -1
- omlish/dataclasses/impl/init.py +1 -1
- omlish/dataclasses/impl/internals.py +15 -0
- omlish/dataclasses/impl/main.py +4 -4
- omlish/dataclasses/impl/metaclass.py +1 -1
- omlish/dataclasses/impl/metadata.py +1 -1
- omlish/dataclasses/impl/order.py +1 -1
- omlish/dataclasses/impl/params.py +4 -38
- omlish/dataclasses/impl/reflect.py +1 -7
- omlish/dataclasses/impl/repr.py +23 -5
- omlish/dataclasses/impl/simple.py +2 -2
- omlish/dataclasses/impl/slots.py +2 -2
- omlish/dataclasses/impl/utils.py +4 -4
- omlish/dispatch/dispatch.py +9 -8
- omlish/dispatch/methods.py +2 -2
- omlish/docker.py +8 -6
- omlish/dynamic.py +5 -5
- omlish/graphs/dot/items.py +1 -1
- omlish/graphs/trees.py +15 -21
- omlish/inject/elements.py +1 -1
- omlish/inject/exceptions.py +1 -1
- omlish/inject/impl/injector.py +1 -1
- omlish/inject/impl/inspect.py +1 -1
- omlish/inject/injector.py +1 -1
- omlish/inject/providers.py +2 -2
- omlish/iterators.py +43 -2
- omlish/lang/__init__.py +167 -112
- omlish/lang/cached.py +13 -5
- omlish/lang/classes/__init__.py +35 -24
- omlish/lang/classes/abstract.py +1 -1
- omlish/lang/classes/simple.py +1 -1
- omlish/lang/clsdct.py +1 -1
- omlish/lang/contextmanagers.py +23 -15
- omlish/lang/datetimes.py +1 -1
- omlish/lang/descriptors.py +35 -2
- omlish/lang/exceptions.py +2 -0
- omlish/lang/functions.py +43 -13
- omlish/lang/imports.py +8 -8
- omlish/lang/iterables.py +1 -1
- omlish/lang/maybes.py +1 -1
- omlish/lang/objects.py +2 -2
- omlish/lang/timeouts.py +53 -0
- omlish/lang/typing.py +2 -2
- omlish/libc.py +6 -6
- omlish/marshal/base.py +6 -6
- omlish/marshal/dataclasses.py +2 -2
- omlish/marshal/enums.py +2 -2
- omlish/marshal/factories.py +10 -10
- omlish/marshal/iterables.py +2 -2
- omlish/marshal/mappings.py +2 -2
- omlish/marshal/optionals.py +4 -4
- omlish/marshal/polymorphism.py +4 -4
- omlish/marshal/standard.py +6 -6
- omlish/marshal/utils.py +1 -1
- omlish/os.py +13 -4
- omlish/procfs.py +336 -0
- omlish/reflect.py +2 -12
- omlish/replserver/console.py +9 -9
- omlish/replserver/server.py +4 -4
- omlish/sql/__init__.py +0 -0
- omlish/sql/_abcs.py +65 -0
- omlish/sql/dbs.py +90 -0
- omlish/stats.py +3 -3
- omlish/testing/pydevd.py +4 -6
- omlish/testing/pytest/inject/__init__.py +7 -0
- omlish/testing/pytest/inject/harness.py +23 -1
- omlish/testing/pytest/plugins/__init__.py +1 -1
- omlish/testing/pytest/plugins/pydevd.py +12 -0
- omlish/testing/pytest/plugins/switches.py +2 -2
- omlish/testing/testing.py +5 -5
- omlish/text/parts.py +3 -3
- omlish-0.0.0.dev2.dist-info/METADATA +31 -0
- omlish-0.0.0.dev2.dist-info/RECORD +193 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/WHEEL +1 -1
- omlish/testing/pytest/plugins/pycharm.py +0 -54
- omlish-0.0.0.dev1.dist-info/METADATA +0 -17
- omlish-0.0.0.dev1.dist-info/RECORD +0 -187
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/top_level.txt +0 -0
omlish/dataclasses/impl/api.py
CHANGED
|
@@ -12,14 +12,11 @@ from .main import process_class
|
|
|
12
12
|
from .metadata import METADATA_ATTR
|
|
13
13
|
from .metadata import Metadata
|
|
14
14
|
from .params import FieldExtras
|
|
15
|
-
from .params import Params12
|
|
16
15
|
from .params import ParamsExtras
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
MISSING = dc.MISSING
|
|
20
19
|
|
|
21
|
-
IS_12 = sys.version_info[1] >= 12
|
|
22
|
-
|
|
23
20
|
|
|
24
21
|
def field(
|
|
25
22
|
default=MISSING,
|
|
@@ -32,10 +29,11 @@ def field(
|
|
|
32
29
|
metadata=None,
|
|
33
30
|
kw_only=MISSING,
|
|
34
31
|
|
|
35
|
-
coerce: ta.
|
|
36
|
-
check: ta.
|
|
37
|
-
check_type:
|
|
32
|
+
coerce: ta.Callable[[ta.Any], ta.Any] | None = None,
|
|
33
|
+
check: ta.Callable[[ta.Any], bool] | None = None,
|
|
34
|
+
check_type: bool | None = None,
|
|
38
35
|
override: bool = False,
|
|
36
|
+
repr_fn: ta.Callable[[ta.Any], str | None] | None = None
|
|
39
37
|
): # -> dc.Field
|
|
40
38
|
if default is not MISSING and default_factory is not MISSING:
|
|
41
39
|
raise ValueError('cannot specify both default and default_factory')
|
|
@@ -45,6 +43,7 @@ def field(
|
|
|
45
43
|
check=check,
|
|
46
44
|
check_type=check_type,
|
|
47
45
|
override=override,
|
|
46
|
+
repr_fn=repr_fn,
|
|
48
47
|
)
|
|
49
48
|
|
|
50
49
|
md: ta.Mapping = {FieldExtras: fx}
|
|
@@ -96,8 +95,6 @@ def dataclass(
|
|
|
96
95
|
order=order,
|
|
97
96
|
unsafe_hash=unsafe_hash,
|
|
98
97
|
frozen=frozen,
|
|
99
|
-
)
|
|
100
|
-
p12kw = dict(
|
|
101
98
|
match_args=match_args,
|
|
102
99
|
kw_only=kw_only,
|
|
103
100
|
slots=slots,
|
|
@@ -118,11 +115,6 @@ def dataclass(
|
|
|
118
115
|
ParamsExtras: pex,
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
if IS_12:
|
|
122
|
-
pkw.update(p12kw)
|
|
123
|
-
else:
|
|
124
|
-
mmd[Params12] = Params12(**p12kw)
|
|
125
|
-
|
|
126
118
|
md: Metadata = mmd
|
|
127
119
|
cmds = []
|
|
128
120
|
if metadata is not None:
|
|
@@ -112,7 +112,7 @@ def field_init(
|
|
|
112
112
|
locals[cn] = f.type
|
|
113
113
|
lines.append(
|
|
114
114
|
f'if not __dataclass_builtins_isinstance__({f.name}, {cn}): '
|
|
115
|
-
f'raise __dataclass_builtins_TypeError__({f.name}, {cn})'
|
|
115
|
+
f'raise __dataclass_builtins_TypeError__({f.name}, {cn})',
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
value: str | None = None
|
omlish/dataclasses/impl/init.py
CHANGED
|
@@ -17,6 +17,21 @@ POST_INIT_NAME = dc._POST_INIT_NAME # type: ignore # noqa
|
|
|
17
17
|
|
|
18
18
|
Params = dc._DataclassParams # type: ignore # noqa
|
|
19
19
|
|
|
20
|
+
"""
|
|
21
|
+
@dc.dataclass(frozen=True)
|
|
22
|
+
class Params:
|
|
23
|
+
init = True
|
|
24
|
+
repr = True
|
|
25
|
+
eq = True
|
|
26
|
+
order = False
|
|
27
|
+
unsafe_hash = False
|
|
28
|
+
frozen = False
|
|
29
|
+
match_args = True
|
|
30
|
+
kw_only = False
|
|
31
|
+
slots = False
|
|
32
|
+
weakref_slot = False
|
|
33
|
+
"""
|
|
34
|
+
|
|
20
35
|
|
|
21
36
|
##
|
|
22
37
|
|
omlish/dataclasses/impl/main.py
CHANGED
|
@@ -84,7 +84,7 @@ class MainProcessor:
|
|
|
84
84
|
|
|
85
85
|
cls_fields: list[dc.Field] = []
|
|
86
86
|
|
|
87
|
-
kw_only = self._info.
|
|
87
|
+
kw_only = self._info.params.kw_only
|
|
88
88
|
kw_only_seen = False
|
|
89
89
|
for name, ann in self._info.cls_annotations.items():
|
|
90
90
|
if is_kw_only(self._cls, ann):
|
|
@@ -111,11 +111,11 @@ class MainProcessor:
|
|
|
111
111
|
|
|
112
112
|
@lang.cached_function
|
|
113
113
|
def _transform_slots(self) -> None:
|
|
114
|
-
if self._info.
|
|
114
|
+
if self._info.params.weakref_slot and not self._info.params.slots:
|
|
115
115
|
raise TypeError('weakref_slot is True but slots is False')
|
|
116
|
-
if not self._info.
|
|
116
|
+
if not self._info.params.slots:
|
|
117
117
|
return
|
|
118
|
-
self._cls = add_slots(self._cls, self._info.params.frozen, self._info.
|
|
118
|
+
self._cls = add_slots(self._cls, self._info.params.frozen, self._info.params.weakref_slot)
|
|
119
119
|
|
|
120
120
|
@lang.cached_function
|
|
121
121
|
def process(self) -> type:
|
omlish/dataclasses/impl/order.py
CHANGED
|
@@ -43,5 +43,5 @@ class OrderProcessor(Processor):
|
|
|
43
43
|
if set_new_attribute(self._cls, name, cmp_fn(name, op, self_tuple, other_tuple, globals=self._info.globals)): # noqa
|
|
44
44
|
raise TypeError(
|
|
45
45
|
f'Cannot overwrite attribute {name} in class {self._cls.__name__}. '
|
|
46
|
-
f'Consider using functools.total_ordering'
|
|
46
|
+
f'Consider using functools.total_ordering',
|
|
47
47
|
)
|
|
@@ -28,7 +28,6 @@ Params:
|
|
|
28
28
|
weakref_slot: bool = False
|
|
29
29
|
"""
|
|
30
30
|
import dataclasses as dc
|
|
31
|
-
import sys
|
|
32
31
|
import typing as ta
|
|
33
32
|
|
|
34
33
|
from ... import lang
|
|
@@ -38,18 +37,16 @@ from .metadata import EMPTY_METADATA
|
|
|
38
37
|
from .metadata import METADATA_ATTR
|
|
39
38
|
|
|
40
39
|
|
|
41
|
-
IS_12 = sys.version_info[1] >= 12
|
|
42
|
-
|
|
43
|
-
|
|
44
40
|
##
|
|
45
41
|
|
|
46
42
|
|
|
47
43
|
@dc.dataclass(frozen=True)
|
|
48
44
|
class FieldExtras(lang.Final):
|
|
49
|
-
coerce:
|
|
50
|
-
check: ta.
|
|
51
|
-
check_type:
|
|
45
|
+
coerce: bool | ta.Callable[[ta.Any], ta.Any] | None = None
|
|
46
|
+
check: ta.Callable[[ta.Any], bool] | None = None
|
|
47
|
+
check_type: bool | None = None
|
|
52
48
|
override: bool = False
|
|
49
|
+
repr_fn: ta.Callable[[ta.Any], str | None] | None = None
|
|
53
50
|
|
|
54
51
|
|
|
55
52
|
DEFAULT_FIELD_EXTRAS = FieldExtras()
|
|
@@ -82,37 +79,6 @@ def get_params(obj: ta.Any) -> Params:
|
|
|
82
79
|
##
|
|
83
80
|
|
|
84
81
|
|
|
85
|
-
@dc.dataclass(frozen=True)
|
|
86
|
-
class Params12(lang.Final):
|
|
87
|
-
match_args: bool = True
|
|
88
|
-
kw_only: bool = False
|
|
89
|
-
slots: bool = False
|
|
90
|
-
weakref_slot: bool = False
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
DEFAULT_PARAMS12 = Params12()
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def get_params12(obj: ta.Any) -> Params12:
|
|
97
|
-
if IS_12:
|
|
98
|
-
p = get_params(obj)
|
|
99
|
-
return Params12(
|
|
100
|
-
match_args=p.match_args,
|
|
101
|
-
kw_only=p.kw_only,
|
|
102
|
-
slots=p.slots,
|
|
103
|
-
weakref_slot=p.weakref_slot,
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
if (pcls := get_params_cls(obj)) is None:
|
|
107
|
-
raise TypeError(pcls)
|
|
108
|
-
|
|
109
|
-
md = pcls.__dict__.get(METADATA_ATTR, EMPTY_METADATA)
|
|
110
|
-
return md.get(Params12, DEFAULT_PARAMS12)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
##
|
|
114
|
-
|
|
115
|
-
|
|
116
82
|
@dc.dataclass(frozen=True)
|
|
117
83
|
class ParamsExtras(lang.Final):
|
|
118
84
|
reorder: bool = False
|
|
@@ -22,10 +22,8 @@ from .metadata import METADATA_ATTR
|
|
|
22
22
|
from .metadata import Metadata
|
|
23
23
|
from .metadata import get_merged_metadata
|
|
24
24
|
from .params import PARAMS_ATTR
|
|
25
|
-
from .params import Params12
|
|
26
25
|
from .params import ParamsExtras
|
|
27
26
|
from .params import get_params
|
|
28
|
-
from .params import get_params12
|
|
29
27
|
from .params import get_params_extras
|
|
30
28
|
from .utils import Namespace
|
|
31
29
|
|
|
@@ -55,7 +53,7 @@ class ClassInfo:
|
|
|
55
53
|
return {}
|
|
56
54
|
|
|
57
55
|
@cached.property
|
|
58
|
-
def cls_annotations(self) ->
|
|
56
|
+
def cls_annotations(self) -> ta.Mapping[str, ta.Any]:
|
|
59
57
|
return inspect.get_annotations(self._cls)
|
|
60
58
|
|
|
61
59
|
##
|
|
@@ -68,10 +66,6 @@ class ClassInfo:
|
|
|
68
66
|
def cls_params(self) -> Params | None:
|
|
69
67
|
return self._cls.__dict__.get(PARAMS_ATTR)
|
|
70
68
|
|
|
71
|
-
@cached.property
|
|
72
|
-
def params12(self) -> Params12:
|
|
73
|
-
return get_params12(self._cls)
|
|
74
|
-
|
|
75
69
|
@cached.property
|
|
76
70
|
def params_extras(self) -> ParamsExtras:
|
|
77
71
|
return get_params_extras(self._cls)
|
omlish/dataclasses/impl/repr.py
CHANGED
|
@@ -2,6 +2,7 @@ import dataclasses as dc
|
|
|
2
2
|
import reprlib
|
|
3
3
|
import typing as ta
|
|
4
4
|
|
|
5
|
+
from .params import get_field_extras
|
|
5
6
|
from .processing import Processor
|
|
6
7
|
from .utils import Namespace
|
|
7
8
|
from .utils import create_fn
|
|
@@ -12,15 +13,32 @@ def repr_fn(
|
|
|
12
13
|
fields: ta.Sequence[dc.Field],
|
|
13
14
|
globals: Namespace,
|
|
14
15
|
) -> ta.Callable:
|
|
16
|
+
locals: dict[str, ta.Any] = {}
|
|
17
|
+
if any(get_field_extras(f).repr_fn is not None for f in fields):
|
|
18
|
+
lst: list[str] = []
|
|
19
|
+
for f in fields:
|
|
20
|
+
if (fex := get_field_extras(f)).repr_fn is not None:
|
|
21
|
+
locals[fn_name := f'__repr_fn__{f.name}'] = fex.repr_fn
|
|
22
|
+
lst.append(f"if (r := {fn_name}(self.{f.name})) is not None: l.append(f'{f.name}={{r}}')")
|
|
23
|
+
else:
|
|
24
|
+
lst.append(f"l.append(f'{f.name}={{self.{f.name}!r}}')")
|
|
25
|
+
src = [
|
|
26
|
+
'l = []',
|
|
27
|
+
*lst,
|
|
28
|
+
'return f"{self.__class__.__qualname__}({\", \".join(l)})"',
|
|
29
|
+
]
|
|
30
|
+
else:
|
|
31
|
+
src = [
|
|
32
|
+
'return f"{self.__class__.__qualname__}(' +
|
|
33
|
+
', '.join([f"{f.name}={{self.{f.name}!r}}" for f in fields]) +
|
|
34
|
+
')"',
|
|
35
|
+
]
|
|
15
36
|
fn = create_fn(
|
|
16
37
|
'__repr__',
|
|
17
38
|
('self',),
|
|
18
|
-
|
|
19
|
-
'return f"{self.__class__.__qualname__}(' +
|
|
20
|
-
', '.join([f"{f.name}={{self.{f.name}!r}}" for f in fields]) +
|
|
21
|
-
')"'
|
|
22
|
-
],
|
|
39
|
+
src,
|
|
23
40
|
globals=globals,
|
|
41
|
+
locals=locals,
|
|
24
42
|
)
|
|
25
43
|
return reprlib.recursive_repr()(fn)
|
|
26
44
|
|
|
@@ -16,7 +16,7 @@ class OverridesProcessor(Processor):
|
|
|
16
16
|
if not fx.override:
|
|
17
17
|
continue
|
|
18
18
|
|
|
19
|
-
if self._info.
|
|
19
|
+
if self._info.params.slots:
|
|
20
20
|
raise TypeError
|
|
21
21
|
|
|
22
22
|
self_name = '__dataclass_self__' if 'self' in self._info.fields else 'self'
|
|
@@ -85,7 +85,7 @@ class DocProcessor(Processor):
|
|
|
85
85
|
|
|
86
86
|
class MatchArgsProcessor(Processor):
|
|
87
87
|
def _process(self) -> None:
|
|
88
|
-
if not self._info.
|
|
88
|
+
if not self._info.params.match_args:
|
|
89
89
|
return
|
|
90
90
|
|
|
91
91
|
ifs = get_init_fields(self._info.fields.values())
|
omlish/dataclasses/impl/slots.py
CHANGED
omlish/dataclasses/impl/utils.py
CHANGED
|
@@ -16,8 +16,8 @@ def create_fn(
|
|
|
16
16
|
args: ta.Sequence[str],
|
|
17
17
|
body: ta.Sequence[str],
|
|
18
18
|
*,
|
|
19
|
-
globals:
|
|
20
|
-
locals:
|
|
19
|
+
globals: Namespace | None = None,
|
|
20
|
+
locals: Namespace | None = None,
|
|
21
21
|
return_type: lang.Maybe[ta.Any] = lang.empty(),
|
|
22
22
|
) -> ta.Callable:
|
|
23
23
|
check.not_isinstance(args, str)
|
|
@@ -59,11 +59,11 @@ class FuncBuilder:
|
|
|
59
59
|
args: ta.Sequence[str],
|
|
60
60
|
body: ta.Sequence[str],
|
|
61
61
|
*,
|
|
62
|
-
locals:
|
|
62
|
+
locals: Namespace | None = None,
|
|
63
63
|
return_type: lang.Maybe[ta.Any] = lang.empty(),
|
|
64
64
|
overwrite_error: bool = False,
|
|
65
65
|
unconditional_add: bool = False,
|
|
66
|
-
decorator:
|
|
66
|
+
decorator: str | None = None,
|
|
67
67
|
) -> None:
|
|
68
68
|
if locals is not None:
|
|
69
69
|
self.locals.update(locals)
|
omlish/dispatch/dispatch.py
CHANGED
|
@@ -27,19 +27,20 @@ def get_impl_func_cls_set(func: ta.Callable) -> ta.FrozenSet[type]:
|
|
|
27
27
|
raise TypeError(f'Invalid impl func: {func!r}')
|
|
28
28
|
|
|
29
29
|
_, cls = next(iter(ta.get_type_hints(func).items()))
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
rty = rfl.type_(cls)
|
|
31
|
+
if isinstance(rty, rfl.Union):
|
|
32
|
+
ret = frozenset(check.isinstance(arg, type) for arg in rty.args)
|
|
32
33
|
else:
|
|
33
|
-
ret = frozenset([check.isinstance(
|
|
34
|
+
ret = frozenset([check.isinstance(rty, type)])
|
|
34
35
|
|
|
35
36
|
_IMPL_FUNC_CLS_SET_CACHE[func] = ret
|
|
36
37
|
return ret
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
def find_impl(cls: type, registry: ta.Mapping[type, T]) ->
|
|
40
|
+
def find_impl(cls: type, registry: ta.Mapping[type, T]) -> T | None:
|
|
40
41
|
mro = c3.compose_mro(cls, registry.keys())
|
|
41
42
|
|
|
42
|
-
match:
|
|
43
|
+
match: type | None = None
|
|
43
44
|
for t in mro:
|
|
44
45
|
if match is not None:
|
|
45
46
|
# If *match* is an implicit ABC but there is another unrelated, equally matching implicit ABC, refuse the
|
|
@@ -71,7 +72,7 @@ class Dispatcher(ta.Generic[T]):
|
|
|
71
72
|
impls_by_arg_cls: dict[type, T] = {}
|
|
72
73
|
self._impls_by_arg_cls = impls_by_arg_cls
|
|
73
74
|
|
|
74
|
-
dispatch_cache: dict[ta.Any,
|
|
75
|
+
dispatch_cache: dict[ta.Any, T | None] = {}
|
|
75
76
|
self._get_dispatch_cache = lambda: dispatch_cache
|
|
76
77
|
|
|
77
78
|
def cache_remove(k, self_ref=weakref.ref(self)):
|
|
@@ -87,7 +88,7 @@ class Dispatcher(ta.Generic[T]):
|
|
|
87
88
|
|
|
88
89
|
weakref_ref_ = weakref.ref
|
|
89
90
|
|
|
90
|
-
def dispatch(cls: type) ->
|
|
91
|
+
def dispatch(cls: type) -> T | None:
|
|
91
92
|
nonlocal cache_token
|
|
92
93
|
|
|
93
94
|
if cache_token is not None and (current_token := abc.get_cache_token()) != cache_token:
|
|
@@ -132,6 +133,6 @@ class Dispatcher(ta.Generic[T]):
|
|
|
132
133
|
def cache_size(self) -> int:
|
|
133
134
|
return len(self._get_dispatch_cache())
|
|
134
135
|
|
|
135
|
-
dispatch: ta.Callable[[type],
|
|
136
|
+
dispatch: ta.Callable[[type], T | None]
|
|
136
137
|
|
|
137
138
|
register: ta.Callable[[T, ta.Iterable[type]], T]
|
omlish/dispatch/methods.py
CHANGED
|
@@ -16,7 +16,7 @@ from .dispatch import get_impl_func_cls_set
|
|
|
16
16
|
T = ta.TypeVar('T')
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def build_mro_dct(instance_cls: type, owner_cls:
|
|
19
|
+
def build_mro_dct(instance_cls: type, owner_cls: type | None = None) -> ta.Mapping[str, ta.Any]:
|
|
20
20
|
if owner_cls is None:
|
|
21
21
|
owner_cls = instance_cls
|
|
22
22
|
mro = instance_cls.__mro__[-2::-1]
|
|
@@ -89,7 +89,7 @@ class Method:
|
|
|
89
89
|
|
|
90
90
|
return impl
|
|
91
91
|
|
|
92
|
-
def build_attr_dispatcher(self, instance_cls: type, owner_cls:
|
|
92
|
+
def build_attr_dispatcher(self, instance_cls: type, owner_cls: type | None = None) -> Dispatcher[str]:
|
|
93
93
|
disp: Dispatcher[str] = Dispatcher()
|
|
94
94
|
|
|
95
95
|
mro_dct = build_mro_dct(instance_cls, owner_cls)
|
omlish/docker.py
CHANGED
|
@@ -118,28 +118,30 @@ class ComposeConfig:
|
|
|
118
118
|
self,
|
|
119
119
|
prefix: str,
|
|
120
120
|
*,
|
|
121
|
-
|
|
121
|
+
file_path: str | None = None,
|
|
122
122
|
) -> None:
|
|
123
123
|
super().__init__()
|
|
124
124
|
|
|
125
125
|
self._prefix = prefix
|
|
126
|
-
self.
|
|
126
|
+
self._file_path = file_path
|
|
127
127
|
|
|
128
128
|
@lang.cached_function
|
|
129
129
|
def get_config(self) -> ta.Mapping[str, ta.Any]:
|
|
130
|
-
with open(check.not_none(self.
|
|
130
|
+
with open(check.not_none(self._file_path), 'r') as f:
|
|
131
131
|
buf = f.read()
|
|
132
|
-
|
|
132
|
+
return yaml.safe_load(buf)
|
|
133
133
|
|
|
134
|
+
@lang.cached_function
|
|
135
|
+
def get_services(self) -> ta.Mapping[str, ta.Any]:
|
|
134
136
|
ret = {}
|
|
135
|
-
for n, c in
|
|
137
|
+
for n, c in self.get_config()['services'].items():
|
|
136
138
|
check.state(n.startswith(self._prefix))
|
|
137
139
|
ret[n[len(self._prefix):]] = c
|
|
138
140
|
|
|
139
141
|
return ret
|
|
140
142
|
|
|
141
143
|
|
|
142
|
-
def timebomb_payload(delay_s:
|
|
144
|
+
def timebomb_payload(delay_s: float, name: str = 'omlish-docker-timebomb') -> str:
|
|
143
145
|
return (
|
|
144
146
|
'('
|
|
145
147
|
f'echo {shlex.quote(name)} && '
|
omlish/dynamic.py
CHANGED
|
@@ -49,10 +49,10 @@ class Var(ta.Generic[T]):
|
|
|
49
49
|
|
|
50
50
|
def __init__(
|
|
51
51
|
self,
|
|
52
|
-
default:
|
|
52
|
+
default: type[MISSING] | T = MISSING, # type: ignore
|
|
53
53
|
*,
|
|
54
|
-
new: ta.
|
|
55
|
-
validate: ta.
|
|
54
|
+
new: ta.Callable[[], T] | type[MISSING] = MISSING,
|
|
55
|
+
validate: ta.Callable[[T], None] | None = None,
|
|
56
56
|
) -> None:
|
|
57
57
|
super().__init__()
|
|
58
58
|
|
|
@@ -60,7 +60,7 @@ class Var(ta.Generic[T]):
|
|
|
60
60
|
raise TypeError('Cannot set both default and new')
|
|
61
61
|
elif default is not MISSING:
|
|
62
62
|
new = lambda: default # type: ignore
|
|
63
|
-
self._new:
|
|
63
|
+
self._new: type[MISSING] | ta.Callable[[], T] = new
|
|
64
64
|
self._validate = validate
|
|
65
65
|
self._bindings_by_frame: ta.MutableMapping[types.FrameType, ta.MutableMapping[int, Binding]] = weakref.WeakValueDictionary() # noqa
|
|
66
66
|
|
|
@@ -166,7 +166,7 @@ class Binding(ta.Generic[T]):
|
|
|
166
166
|
|
|
167
167
|
def __enter__(self) -> T:
|
|
168
168
|
frame = sys._getframe(self._offset).f_back # noqa
|
|
169
|
-
lag_frame:
|
|
169
|
+
lag_frame: types.FrameType | None = frame
|
|
170
170
|
while lag_frame is not None:
|
|
171
171
|
for cur_depth in range(_MAX_HOIST_DEPTH + 1):
|
|
172
172
|
if lag_frame is None:
|
omlish/graphs/dot/items.py
CHANGED
omlish/graphs/trees.py
CHANGED
|
@@ -57,7 +57,7 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
|
57
57
|
self._dict_fac: ta.Callable[..., ta.MutableMapping[NodeT, ta.Any]] = col.IdentityKeyDict if identity else dict
|
|
58
58
|
self._idx_seq_fac: ta.Callable[..., col.IndexedSeq[NodeT]] = functools.partial(col.IndexedSeq, identity=identity) # noqa
|
|
59
59
|
|
|
60
|
-
def walk(cur: NodeT, parent:
|
|
60
|
+
def walk(cur: NodeT, parent: NodeT | None) -> None:
|
|
61
61
|
check.not_none(cur)
|
|
62
62
|
if cur in node_set:
|
|
63
63
|
raise DuplicateNodeException(cur)
|
|
@@ -78,9 +78,9 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
|
78
78
|
|
|
79
79
|
nodes: list[NodeT] = []
|
|
80
80
|
node_set: ta.MutableSet[NodeT] = self._set_fac() # type: ignore
|
|
81
|
-
children_by_node: ta.MutableMapping[
|
|
81
|
+
children_by_node: ta.MutableMapping[NodeT | None, ta.Sequence[NodeT]] = self._dict_fac() # type: ignore
|
|
82
82
|
child_sets_by_node: ta.MutableMapping[ta.Optional[NodeT], ta.AbstractSet[NodeT]] = self._dict_fac() # type: ignore # noqa
|
|
83
|
-
parents_by_node: ta.MutableMapping[NodeT,
|
|
83
|
+
parents_by_node: ta.MutableMapping[NodeT, NodeT | None] = self._dict_fac() # type: ignore
|
|
84
84
|
|
|
85
85
|
children_by_node[None] = [root]
|
|
86
86
|
child_sets_by_node[None] = self._set_fac([root]) # type: ignore
|
|
@@ -89,10 +89,10 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
|
89
89
|
|
|
90
90
|
self._nodes = self._idx_seq_fac(nodes) # type: ignore
|
|
91
91
|
self._node_set: ta.AbstractSet[NodeT] = node_set
|
|
92
|
-
self._children_by_node: ta.Mapping[
|
|
92
|
+
self._children_by_node: ta.Mapping[NodeT | None, col.IndexedSeq[NodeT]] = self._dict_fac( # type: ignore
|
|
93
93
|
[(n, self._idx_seq_fac(cs)) for n, cs in children_by_node.items()])
|
|
94
|
-
self._child_sets_by_node: ta.Mapping[
|
|
95
|
-
self._parents_by_node: ta.Mapping[NodeT,
|
|
94
|
+
self._child_sets_by_node: ta.Mapping[NodeT | None, ta.AbstractSet[NodeT]] = child_sets_by_node
|
|
95
|
+
self._parents_by_node: ta.Mapping[NodeT, NodeT | None] = parents_by_node
|
|
96
96
|
|
|
97
97
|
@property
|
|
98
98
|
def root(self) -> NodeT:
|
|
@@ -115,27 +115,24 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
|
115
115
|
return self._node_set
|
|
116
116
|
|
|
117
117
|
@property
|
|
118
|
-
def children_by_node(self) -> ta.Mapping[
|
|
118
|
+
def children_by_node(self) -> ta.Mapping[NodeT | None, col.IndexedSeq[NodeT]]:
|
|
119
119
|
return self._children_by_node
|
|
120
120
|
|
|
121
121
|
@property
|
|
122
|
-
def child_sets_by_node(self) -> ta.Mapping[
|
|
122
|
+
def child_sets_by_node(self) -> ta.Mapping[NodeT | None, ta.AbstractSet[NodeT]]:
|
|
123
123
|
return self._child_sets_by_node
|
|
124
124
|
|
|
125
125
|
@property
|
|
126
|
-
def parents_by_node(self) -> ta.Mapping[NodeT,
|
|
126
|
+
def parents_by_node(self) -> ta.Mapping[NodeT, NodeT | None]:
|
|
127
127
|
return self._parents_by_node
|
|
128
128
|
|
|
129
129
|
@classmethod
|
|
130
130
|
def from_parents(
|
|
131
131
|
cls,
|
|
132
|
-
src: ta.
|
|
133
|
-
ta.Mapping[NodeT, ta.Optional[NodeT]],
|
|
134
|
-
ta.Iterable[tuple[NodeT, ta.Optional[NodeT]]],
|
|
135
|
-
],
|
|
132
|
+
src: ta.Mapping[NodeT, NodeT | None] | ta.Iterable[tuple[NodeT, NodeT | None]],
|
|
136
133
|
*,
|
|
137
134
|
identity: bool = False,
|
|
138
|
-
**kwargs
|
|
135
|
+
**kwargs,
|
|
139
136
|
) -> 'BasicTreeAnalysis[NodeT]':
|
|
140
137
|
pairs: ta.Sequence[tuple[NodeT, NodeT]]
|
|
141
138
|
if isinstance(src, ta.Mapping):
|
|
@@ -166,13 +163,10 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
|
166
163
|
@classmethod
|
|
167
164
|
def from_children(
|
|
168
165
|
cls,
|
|
169
|
-
src: ta.
|
|
170
|
-
ta.Mapping[NodeT, ta.Iterable[NodeT]],
|
|
171
|
-
ta.Iterable[tuple[NodeT, ta.Iterable[NodeT]]],
|
|
172
|
-
],
|
|
166
|
+
src: ta.Mapping[NodeT, ta.Iterable[NodeT]] | ta.Iterable[tuple[NodeT, ta.Iterable[NodeT]]],
|
|
173
167
|
*,
|
|
174
168
|
identity: bool = False,
|
|
175
|
-
**kwargs
|
|
169
|
+
**kwargs,
|
|
176
170
|
) -> 'BasicTreeAnalysis[NodeT]':
|
|
177
171
|
pairs: ta.Sequence[tuple[NodeT, ta.Sequence[NodeT]]]
|
|
178
172
|
if isinstance(src, ta.Mapping):
|
|
@@ -222,7 +216,7 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
|
222
216
|
return ret # type: ignore
|
|
223
217
|
|
|
224
218
|
def iter_ancestors(self, node: NodeT) -> NodeGenerator[NodeT]:
|
|
225
|
-
cur:
|
|
219
|
+
cur: NodeT | None = node
|
|
226
220
|
while True:
|
|
227
221
|
cur = self.parents_by_node.get(cur) # type: ignore
|
|
228
222
|
if cur is None:
|
|
@@ -232,7 +226,7 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
|
232
226
|
def get_lineage(self, node: NodeT) -> col.IndexedSeq[NodeT]:
|
|
233
227
|
return self._idx_seq_fac(reversed([node, *self.iter_ancestors(node)]))
|
|
234
228
|
|
|
235
|
-
def get_first_parent_of_type(self, node: NodeT, ty: type[T]) ->
|
|
229
|
+
def get_first_parent_of_type(self, node: NodeT, ty: type[T]) -> T | None:
|
|
236
230
|
for cur in self.iter_ancestors(node):
|
|
237
231
|
if isinstance(cur, ty):
|
|
238
232
|
return cur
|
omlish/inject/elements.py
CHANGED
omlish/inject/exceptions.py
CHANGED
omlish/inject/impl/injector.py
CHANGED
|
@@ -45,7 +45,7 @@ class InjectorImpl(Injector, lang.Final):
|
|
|
45
45
|
super().__init__()
|
|
46
46
|
|
|
47
47
|
self._ec = check.isinstance(ec, ElementCollection)
|
|
48
|
-
self._p:
|
|
48
|
+
self._p: InjectorImpl | None = check.isinstance(p, (InjectorImpl, None))
|
|
49
49
|
|
|
50
50
|
self._internal_consts: dict[Key, ta.Any] = {
|
|
51
51
|
Key(Injector): self,
|
omlish/inject/impl/inspect.py
CHANGED