omlish 0.0.0.dev433__py3-none-any.whl → 0.0.0.dev435__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 -2
- omlish/asyncs/all.py +0 -13
- omlish/concurrent/__init__.py +0 -17
- omlish/concurrent/all.py +17 -0
- omlish/configs/types.py +1 -1
- omlish/daemons/__init__.py +70 -0
- omlish/dataclasses/errors.py +1 -1
- omlish/formats/json/stream/lexing.py +12 -6
- omlish/formats/json/stream/utils.py +28 -2
- omlish/formats/json5/stream.py +82 -0
- omlish/funcs/genmachine.py +1 -1
- omlish/http/coro/server/server.py +1 -1
- omlish/inject/__init__.py +152 -126
- omlish/inject/binder.py +7 -4
- omlish/inject/impl/elements.py +6 -8
- omlish/inject/impl/injector.py +58 -32
- omlish/inject/impl/inspect.py +1 -0
- omlish/inject/impl/maysync.py +44 -0
- omlish/inject/impl/multis.py +5 -5
- omlish/inject/impl/privates.py +8 -8
- omlish/inject/impl/providers.py +24 -31
- omlish/inject/impl/providers2.py +43 -0
- omlish/inject/impl/scopes.py +19 -25
- omlish/inject/impl/sync.py +42 -0
- omlish/inject/injector.py +9 -11
- omlish/inject/inspect.py +1 -3
- omlish/inject/listeners.py +4 -4
- omlish/inject/managed.py +52 -20
- omlish/inject/maysync.py +27 -0
- omlish/inject/providers.py +6 -0
- omlish/inject/scopes.py +38 -10
- omlish/inject/sync.py +46 -0
- omlish/lang/__init__.py +12 -3
- omlish/lang/asyncs.py +18 -0
- omlish/lang/contextmanagers.py +23 -0
- omlish/lite/asyncs.py +21 -0
- omlish/lite/attrops.py +1 -1
- omlish/lite/inject.py +4 -4
- omlish/lite/maysync.py +21 -0
- omlish/marshal/__init__.py +20 -8
- omlish/os/atomics.py +1 -1
- omlish/reflect/ops.py +9 -0
- omlish/reflect/types.py +19 -6
- omlish/sockets/addresses.py +1 -1
- omlish/sql/queries/params.py +1 -1
- {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev435.dist-info}/METADATA +1 -4
- {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev435.dist-info}/RECORD +51 -47
- omlish/asyncs/bridge.py +0 -359
- omlish/asyncs/utils.py +0 -18
- omlish/formats/json5/streams.py +0 -22
- {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev435.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev435.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev435.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev435.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from ... import lang
|
4
|
+
from ..elements import Elements
|
5
|
+
from ..injector import AsyncInjector
|
6
|
+
from ..inspect import KwargsTarget
|
7
|
+
from ..keys import Key
|
8
|
+
from ..sync import Injector
|
9
|
+
from .elements import ElementCollection
|
10
|
+
from .injector import AsyncInjectorImpl
|
11
|
+
|
12
|
+
|
13
|
+
##
|
14
|
+
|
15
|
+
|
16
|
+
class InjectorImpl(Injector, lang.Final):
|
17
|
+
_ai: AsyncInjector
|
18
|
+
|
19
|
+
def try_provide(self, key: ta.Any) -> lang.Maybe[ta.Any]:
|
20
|
+
return lang.sync_await(self._ai.try_provide(key))
|
21
|
+
|
22
|
+
def provide(self, key: ta.Any) -> ta.Any:
|
23
|
+
return lang.sync_await(self._ai.provide(key))
|
24
|
+
|
25
|
+
def provide_kwargs(self, kt: KwargsTarget) -> ta.Mapping[str, ta.Any]:
|
26
|
+
return lang.sync_await(self._ai.provide_kwargs(kt))
|
27
|
+
|
28
|
+
def inject(self, obj: ta.Any) -> ta.Any:
|
29
|
+
return lang.sync_await(self._ai.inject(obj))
|
30
|
+
|
31
|
+
|
32
|
+
def create_injector(es: Elements) -> Injector:
|
33
|
+
si = InjectorImpl()
|
34
|
+
ai = AsyncInjectorImpl(
|
35
|
+
ElementCollection(es),
|
36
|
+
internal_consts={
|
37
|
+
Key(Injector): si,
|
38
|
+
},
|
39
|
+
)
|
40
|
+
si._ai = ai # noqa
|
41
|
+
lang.sync_await(ai._init()) # noqa
|
42
|
+
return si
|
omlish/inject/injector.py
CHANGED
@@ -8,10 +8,8 @@ from .inspect import KwargsTarget
|
|
8
8
|
from .keys import Key
|
9
9
|
|
10
10
|
|
11
|
-
|
11
|
+
with lang.auto_proxy_import(globals()):
|
12
12
|
from .impl import injector as _injector
|
13
|
-
else:
|
14
|
-
_injector = lang.proxy_import('.impl.injector', __package__)
|
15
13
|
|
16
14
|
|
17
15
|
T = ta.TypeVar('T')
|
@@ -20,29 +18,29 @@ T = ta.TypeVar('T')
|
|
20
18
|
##
|
21
19
|
|
22
20
|
|
23
|
-
class
|
21
|
+
class AsyncInjector(lang.Abstract):
|
24
22
|
@abc.abstractmethod
|
25
|
-
def try_provide(self, key: ta.Any) -> lang.Maybe[ta.Any]:
|
23
|
+
def try_provide(self, key: ta.Any) -> ta.Awaitable[lang.Maybe[ta.Any]]:
|
26
24
|
raise NotImplementedError
|
27
25
|
|
28
26
|
@abc.abstractmethod
|
29
|
-
def provide(self, key: ta.Any) -> ta.Any:
|
27
|
+
def provide(self, key: ta.Any) -> ta.Awaitable[ta.Any]:
|
30
28
|
raise NotImplementedError
|
31
29
|
|
32
30
|
@abc.abstractmethod
|
33
|
-
def provide_kwargs(self, kt: KwargsTarget) -> ta.Mapping[str, ta.Any]:
|
31
|
+
def provide_kwargs(self, kt: KwargsTarget) -> ta.Awaitable[ta.Mapping[str, ta.Any]]:
|
34
32
|
raise NotImplementedError
|
35
33
|
|
36
34
|
@abc.abstractmethod
|
37
|
-
def inject(self, obj: ta.Any) -> ta.Any:
|
35
|
+
def inject(self, obj: ta.Any) -> ta.Awaitable[ta.Any]:
|
38
36
|
raise NotImplementedError
|
39
37
|
|
40
38
|
def __getitem__(
|
41
39
|
self,
|
42
40
|
target: Key[T] | type[T],
|
43
|
-
) -> T:
|
41
|
+
) -> ta.Awaitable[T]:
|
44
42
|
return self.provide(target)
|
45
43
|
|
46
44
|
|
47
|
-
def
|
48
|
-
return _injector.
|
45
|
+
def create_async_injector(*args: Elemental) -> ta.Awaitable[AsyncInjector]:
|
46
|
+
return _injector.create_async_injector(as_elements(*args))
|
omlish/inject/inspect.py
CHANGED
omlish/inject/listeners.py
CHANGED
@@ -4,7 +4,7 @@ from .. import dataclasses as dc
|
|
4
4
|
from .. import lang
|
5
5
|
from .bindings import Binding
|
6
6
|
from .elements import Element
|
7
|
-
from .injector import
|
7
|
+
from .injector import AsyncInjector
|
8
8
|
from .keys import Key
|
9
9
|
|
10
10
|
|
@@ -12,11 +12,11 @@ from .keys import Key
|
|
12
12
|
|
13
13
|
|
14
14
|
ProvisionListener: ta.TypeAlias = ta.Callable[[
|
15
|
-
|
15
|
+
AsyncInjector,
|
16
16
|
Key,
|
17
17
|
Binding | None,
|
18
|
-
ta.Callable[[], ta.Any],
|
19
|
-
], ta.
|
18
|
+
ta.Callable[[], ta.Awaitable[ta.Any]],
|
19
|
+
], ta.Awaitable[ta.Any]]
|
20
20
|
|
21
21
|
|
22
22
|
@dc.dataclass(frozen=True)
|
omlish/inject/managed.py
CHANGED
@@ -9,14 +9,12 @@ from .. import lang
|
|
9
9
|
from .binder import bind
|
10
10
|
from .elements import Elemental
|
11
11
|
from .impl.inspect import build_kwargs_target
|
12
|
-
from .injector import Injector
|
13
|
-
from .injector import create_injector
|
14
12
|
|
15
13
|
|
16
|
-
|
17
|
-
from
|
18
|
-
|
19
|
-
|
14
|
+
with lang.auto_proxy_import(globals()):
|
15
|
+
from . import injector as _injector
|
16
|
+
from . import maysync as _maysync
|
17
|
+
from . import sync as _sync
|
20
18
|
|
21
19
|
|
22
20
|
T = ta.TypeVar('T')
|
@@ -25,9 +23,43 @@ T = ta.TypeVar('T')
|
|
25
23
|
##
|
26
24
|
|
27
25
|
|
26
|
+
@contextlib.asynccontextmanager
|
27
|
+
async def create_async_managed_injector(*args: Elemental) -> ta.AsyncGenerator['_injector.AsyncInjector']:
|
28
|
+
ai = await _injector.create_async_injector(
|
29
|
+
bind(contextlib.AsyncExitStack, singleton=True, eager=True),
|
30
|
+
*args,
|
31
|
+
)
|
32
|
+
async with (await ai[contextlib.AsyncExitStack]):
|
33
|
+
yield ai
|
34
|
+
|
35
|
+
|
36
|
+
def make_async_managed_provider(
|
37
|
+
fac: ta.Callable[..., T],
|
38
|
+
*fns: ta.Callable[[T], ta.AsyncContextManager[T]],
|
39
|
+
) -> ta.Callable[..., ta.Awaitable[T]]:
|
40
|
+
kt = build_kwargs_target(fac)
|
41
|
+
|
42
|
+
async def _provide(
|
43
|
+
ai: _injector.AsyncInjector,
|
44
|
+
aes: contextlib.AsyncExitStack,
|
45
|
+
):
|
46
|
+
obj = await ai.inject(kt)
|
47
|
+
if not fns:
|
48
|
+
obj = await aes.enter_async_context(obj)
|
49
|
+
else:
|
50
|
+
for fn in fns:
|
51
|
+
await aes.enter_async_context(fn(obj))
|
52
|
+
return obj
|
53
|
+
|
54
|
+
return _provide
|
55
|
+
|
56
|
+
|
57
|
+
##
|
58
|
+
|
59
|
+
|
28
60
|
@contextlib.contextmanager
|
29
|
-
def create_managed_injector(*args: Elemental) -> ta.Generator[Injector]:
|
30
|
-
i = create_injector(
|
61
|
+
def create_managed_injector(*args: Elemental) -> ta.Generator['_sync.Injector']:
|
62
|
+
i = _sync.create_injector(
|
31
63
|
bind(contextlib.ExitStack, singleton=True, eager=True),
|
32
64
|
*args,
|
33
65
|
)
|
@@ -42,7 +74,7 @@ def make_managed_provider(
|
|
42
74
|
kt = build_kwargs_target(fac)
|
43
75
|
|
44
76
|
def _provide(
|
45
|
-
i: Injector,
|
77
|
+
i: _sync.Injector,
|
46
78
|
es: contextlib.ExitStack,
|
47
79
|
):
|
48
80
|
obj = i.inject(kt)
|
@@ -59,32 +91,32 @@ def make_managed_provider(
|
|
59
91
|
##
|
60
92
|
|
61
93
|
|
62
|
-
@contextlib.
|
63
|
-
|
64
|
-
i =
|
65
|
-
bind(contextlib.
|
94
|
+
@contextlib.contextmanager
|
95
|
+
def create_maysync_managed_injector(*args: Elemental) -> ta.Generator['_maysync.MaysyncInjector']:
|
96
|
+
i = _maysync.create_maysync_injector(
|
97
|
+
bind(contextlib.ExitStack, singleton=True, eager=True),
|
66
98
|
*args,
|
67
99
|
)
|
68
|
-
|
100
|
+
with i[contextlib.ExitStack]:
|
69
101
|
yield i
|
70
102
|
|
71
103
|
|
72
|
-
def
|
104
|
+
def make_maysync_managed_provider(
|
73
105
|
fac: ta.Callable[..., T],
|
74
|
-
*fns: ta.Callable[[T], ta.
|
106
|
+
*fns: ta.Callable[[T], ta.ContextManager[T]],
|
75
107
|
) -> ta.Callable[..., T]:
|
76
108
|
kt = build_kwargs_target(fac)
|
77
109
|
|
78
110
|
def _provide(
|
79
|
-
i:
|
80
|
-
|
111
|
+
i: _maysync.MaysyncInjector,
|
112
|
+
es: contextlib.ExitStack,
|
81
113
|
):
|
82
114
|
obj = i.inject(kt)
|
83
115
|
if not fns:
|
84
|
-
obj =
|
116
|
+
obj = es.enter_context(obj)
|
85
117
|
else:
|
86
118
|
for fn in fns:
|
87
|
-
|
119
|
+
es.enter_context(fn(obj))
|
88
120
|
return obj
|
89
121
|
|
90
122
|
return _provide
|
omlish/inject/maysync.py
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from .. import lang
|
4
|
+
from .elements import Elemental
|
5
|
+
from .elements import as_elements
|
6
|
+
from .sync import Injector
|
7
|
+
|
8
|
+
|
9
|
+
with lang.auto_proxy_import(globals()):
|
10
|
+
from .impl import maysync as _maysync
|
11
|
+
|
12
|
+
|
13
|
+
T = ta.TypeVar('T')
|
14
|
+
|
15
|
+
|
16
|
+
##
|
17
|
+
|
18
|
+
|
19
|
+
class MaysyncInjector(Injector, lang.Abstract):
|
20
|
+
pass
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
|
25
|
+
|
26
|
+
def create_maysync_injector(*args: Elemental) -> MaysyncInjector:
|
27
|
+
return _maysync.create_maysync_injector(as_elements(*args))
|
omlish/inject/providers.py
CHANGED
@@ -17,6 +17,12 @@ class Provider(lang.Abstract):
|
|
17
17
|
pass
|
18
18
|
|
19
19
|
|
20
|
+
@dc.dataclass(frozen=True)
|
21
|
+
@dc.extra_class_params(cache_hash=True)
|
22
|
+
class AsyncFnProvider(Provider):
|
23
|
+
fn: ta.Any = dc.xfield(validate=callable)
|
24
|
+
|
25
|
+
|
20
26
|
@dc.dataclass(frozen=True)
|
21
27
|
@dc.extra_class_params(cache_hash=True)
|
22
28
|
class FnProvider(Provider):
|
omlish/inject/scopes.py
CHANGED
@@ -7,16 +7,17 @@ from .. import dataclasses as dc
|
|
7
7
|
from .. import lang
|
8
8
|
from .bindings import Binding
|
9
9
|
from .elements import Element
|
10
|
+
from .injector import AsyncInjector
|
10
11
|
from .keys import Key
|
11
12
|
from .keys import as_key
|
12
13
|
from .providers import Provider
|
13
14
|
from .types import Scope
|
14
15
|
|
15
16
|
|
16
|
-
|
17
|
-
from . import injector as
|
18
|
-
|
19
|
-
|
17
|
+
with lang.auto_proxy_import(globals()):
|
18
|
+
from . import injector as _injector
|
19
|
+
from . import maysync as _maysync
|
20
|
+
from . import sync as _sync
|
20
21
|
|
21
22
|
|
22
23
|
##
|
@@ -65,7 +66,7 @@ class SeededScope(Scope, lang.Final):
|
|
65
66
|
|
66
67
|
class Manager(lang.Abstract):
|
67
68
|
@abc.abstractmethod
|
68
|
-
def __call__(self, seeds: ta.Mapping[Key, ta.Any]) -> ta.
|
69
|
+
def __call__(self, seeds: ta.Mapping[Key, ta.Any]) -> ta.AsyncContextManager[None]:
|
69
70
|
raise NotImplementedError
|
70
71
|
|
71
72
|
|
@@ -81,11 +82,38 @@ def bind_scope_seed(k: ta.Any, ss: SeededScope) -> Element:
|
|
81
82
|
return Binding(k, ScopeSeededProvider(ss, k))
|
82
83
|
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
##
|
86
|
+
|
87
|
+
|
88
|
+
@contextlib.asynccontextmanager
|
89
|
+
async def async_enter_seeded_scope(
|
90
|
+
i: '_injector.AsyncInjector',
|
87
91
|
ss: SeededScope,
|
88
92
|
keys: ta.Mapping[Key, ta.Any],
|
89
|
-
) -> ta.
|
90
|
-
with i.provide(Key(SeededScope.Manager, tag=ss))(keys):
|
93
|
+
) -> ta.AsyncGenerator[None]:
|
94
|
+
async with (await i.provide(Key(SeededScope.Manager, tag=ss)))(keys):
|
91
95
|
yield
|
96
|
+
|
97
|
+
|
98
|
+
def enter_seeded_scope(
|
99
|
+
i: '_sync.Injector',
|
100
|
+
ss: SeededScope,
|
101
|
+
keys: ta.Mapping[Key, ta.Any],
|
102
|
+
) -> ta.ContextManager[None]:
|
103
|
+
return lang.run_maysync_context_manager(async_enter_seeded_scope(
|
104
|
+
i[AsyncInjector],
|
105
|
+
ss,
|
106
|
+
keys,
|
107
|
+
))
|
108
|
+
|
109
|
+
|
110
|
+
def maysync_enter_seeded_scope(
|
111
|
+
i: '_maysync.MaysyncInjector',
|
112
|
+
ss: SeededScope,
|
113
|
+
keys: ta.Mapping[Key, ta.Any],
|
114
|
+
) -> ta.ContextManager[None]:
|
115
|
+
return lang.sync_async_context_manager(async_enter_seeded_scope(
|
116
|
+
i[AsyncInjector],
|
117
|
+
ss,
|
118
|
+
keys,
|
119
|
+
))
|
omlish/inject/sync.py
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
import abc
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from .. import lang
|
5
|
+
from .elements import Elemental
|
6
|
+
from .elements import as_elements
|
7
|
+
from .inspect import KwargsTarget
|
8
|
+
from .keys import Key
|
9
|
+
|
10
|
+
|
11
|
+
with lang.auto_proxy_import(globals()):
|
12
|
+
from .impl import sync as _sync
|
13
|
+
|
14
|
+
|
15
|
+
T = ta.TypeVar('T')
|
16
|
+
|
17
|
+
|
18
|
+
##
|
19
|
+
|
20
|
+
|
21
|
+
class Injector(lang.Abstract):
|
22
|
+
@abc.abstractmethod
|
23
|
+
def try_provide(self, key: ta.Any) -> lang.Maybe[ta.Any]:
|
24
|
+
raise NotImplementedError
|
25
|
+
|
26
|
+
@abc.abstractmethod
|
27
|
+
def provide(self, key: ta.Any) -> ta.Any:
|
28
|
+
raise NotImplementedError
|
29
|
+
|
30
|
+
@abc.abstractmethod
|
31
|
+
def provide_kwargs(self, kt: KwargsTarget) -> ta.Mapping[str, ta.Any]:
|
32
|
+
raise NotImplementedError
|
33
|
+
|
34
|
+
@abc.abstractmethod
|
35
|
+
def inject(self, obj: ta.Any) -> ta.Any:
|
36
|
+
raise NotImplementedError
|
37
|
+
|
38
|
+
def __getitem__(
|
39
|
+
self,
|
40
|
+
target: Key[T] | type[T],
|
41
|
+
) -> T:
|
42
|
+
return self.provide(target)
|
43
|
+
|
44
|
+
|
45
|
+
def create_injector(*args: Elemental) -> Injector:
|
46
|
+
return _sync.create_injector(as_elements(*args))
|
omlish/lang/__init__.py
CHANGED
@@ -15,6 +15,9 @@ with _auto_proxy_init(
|
|
15
15
|
|
16
16
|
sync_await,
|
17
17
|
sync_async_list,
|
18
|
+
|
19
|
+
SyncAsyncContextManager,
|
20
|
+
sync_async_context_manager,
|
18
21
|
)
|
19
22
|
|
20
23
|
from .attrstorage import ( # noqa
|
@@ -184,6 +187,9 @@ with _auto_proxy_init(
|
|
184
187
|
Timer,
|
185
188
|
|
186
189
|
double_check_setdefault,
|
190
|
+
|
191
|
+
call_with_exit_stack,
|
192
|
+
call_with_async_exit_stack,
|
187
193
|
)
|
188
194
|
|
189
195
|
from .datetimes import ( # noqa
|
@@ -487,9 +493,6 @@ with _auto_proxy_init(
|
|
487
493
|
)
|
488
494
|
|
489
495
|
from ..lite.maysync import ( # noqa
|
490
|
-
mark_maysync,
|
491
|
-
is_maysync,
|
492
|
-
|
493
496
|
AnyMaysyncFn,
|
494
497
|
|
495
498
|
MaywaitableAlreadyConsumedError,
|
@@ -504,6 +507,12 @@ with _auto_proxy_init(
|
|
504
507
|
is_running_maysync,
|
505
508
|
|
506
509
|
run_maysync,
|
510
|
+
|
511
|
+
RunMaysyncContextManager,
|
512
|
+
run_maysync_context_manager,
|
513
|
+
|
514
|
+
mark_maysync,
|
515
|
+
is_maysync,
|
507
516
|
)
|
508
517
|
|
509
518
|
from ..lite.objects import ( # noqa
|
omlish/lang/asyncs.py
CHANGED
@@ -79,3 +79,21 @@ def sync_async_list(
|
|
79
79
|
raise TypeError(lst)
|
80
80
|
|
81
81
|
return lst
|
82
|
+
|
83
|
+
|
84
|
+
@ta.final
|
85
|
+
class SyncAsyncContextManager(ta.Generic[T]):
|
86
|
+
def __init__(self, acm: ta.AsyncContextManager[T]) -> None:
|
87
|
+
self._acm = acm
|
88
|
+
|
89
|
+
def __repr__(self) -> str:
|
90
|
+
return f'{self.__class__.__name__}({self._acm!r})'
|
91
|
+
|
92
|
+
def __enter__(self) -> T:
|
93
|
+
return sync_await(self._acm.__aenter__())
|
94
|
+
|
95
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
96
|
+
return sync_await(self._acm.__aexit__(exc_type, exc_val, exc_tb))
|
97
|
+
|
98
|
+
|
99
|
+
sync_async_context_manager = SyncAsyncContextManager
|
omlish/lang/contextmanagers.py
CHANGED
@@ -20,6 +20,8 @@ T = ta.TypeVar('T')
|
|
20
20
|
K = ta.TypeVar('K')
|
21
21
|
V = ta.TypeVar('V')
|
22
22
|
|
23
|
+
P = ta.ParamSpec('P')
|
24
|
+
|
23
25
|
|
24
26
|
##
|
25
27
|
|
@@ -382,3 +384,24 @@ def double_check_setdefault(
|
|
382
384
|
v = fn()
|
383
385
|
dct[k] = v
|
384
386
|
return v
|
387
|
+
|
388
|
+
|
389
|
+
##
|
390
|
+
|
391
|
+
|
392
|
+
def call_with_exit_stack(
|
393
|
+
fn: ta.Callable[ta.Concatenate[contextlib.ExitStack, P], T],
|
394
|
+
*args: ta.Any,
|
395
|
+
**kwargs: ta.Any,
|
396
|
+
) -> T:
|
397
|
+
with contextlib.ExitStack() as es:
|
398
|
+
return fn(es, *args, **kwargs)
|
399
|
+
|
400
|
+
|
401
|
+
async def call_with_async_exit_stack(
|
402
|
+
fn: ta.Callable[ta.Concatenate[contextlib.AsyncExitStack, P], ta.Awaitable[T]],
|
403
|
+
*args: ta.Any,
|
404
|
+
**kwargs: ta.Any,
|
405
|
+
) -> T:
|
406
|
+
async with contextlib.AsyncExitStack() as aes:
|
407
|
+
return await fn(aes, *args, **kwargs)
|
omlish/lite/asyncs.py
CHANGED
@@ -18,3 +18,24 @@ def as_async(fn: ta.Callable[..., T], *, wrap: bool = False) -> ta.Callable[...,
|
|
18
18
|
return fn(*args, **kwargs)
|
19
19
|
|
20
20
|
return functools.wraps(fn)(inner) if wrap else inner
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
|
25
|
+
|
26
|
+
@ta.final
|
27
|
+
class SyncToAsyncContextManager(ta.Generic[T]):
|
28
|
+
def __init__(self, cm: ta.ContextManager[T]) -> None:
|
29
|
+
self._cm = cm
|
30
|
+
|
31
|
+
def __repr__(self) -> str:
|
32
|
+
return f'{self.__class__.__name__}({self._cm!r})'
|
33
|
+
|
34
|
+
async def __aenter__(self) -> T:
|
35
|
+
return self._cm.__enter__()
|
36
|
+
|
37
|
+
async def __aexit__(self, exc_type, exc_value, traceback, /):
|
38
|
+
return self._cm.__exit__(exc_type, exc_value, traceback)
|
39
|
+
|
40
|
+
|
41
|
+
as_async_context_manager = SyncToAsyncContextManager
|
omlish/lite/attrops.py
CHANGED
@@ -212,7 +212,7 @@ class AttrOps(ta.Generic[T]):
|
|
212
212
|
return (
|
213
213
|
f'{o.__class__.__module__ + "." if self._with_module else ""}'
|
214
214
|
f'{o.__class__.__qualname__ if self._use_qualname else o.__class__.__name__}'
|
215
|
-
f'{("@" + hex(id(o))[2:]) if self._with_id else ""}'
|
215
|
+
f'{("@" + hex(id(o))[2:]) if self._with_id else ""}' # noqa
|
216
216
|
f'({vs})'
|
217
217
|
)
|
218
218
|
|
omlish/lite/inject.py
CHANGED
@@ -21,12 +21,12 @@ T = ta.TypeVar('T')
|
|
21
21
|
U = ta.TypeVar('U')
|
22
22
|
|
23
23
|
|
24
|
-
InjectorKeyCls = ta.Union[type, ta.NewType]
|
24
|
+
InjectorKeyCls = ta.Union[type, ta.NewType] # ta.TypeAlias
|
25
25
|
|
26
|
-
InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
|
27
|
-
InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
|
26
|
+
InjectorProviderFn = ta.Callable[['Injector'], ta.Any] # ta.TypeAlias
|
27
|
+
InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn'] # ta.TypeAlias
|
28
28
|
|
29
|
-
InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
|
29
|
+
InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings'] # ta.TypeAlias
|
30
30
|
|
31
31
|
|
32
32
|
###
|
omlish/lite/maysync.py
CHANGED
@@ -523,6 +523,27 @@ def run_maysync(m):
|
|
523
523
|
##
|
524
524
|
|
525
525
|
|
526
|
+
@ta.final
|
527
|
+
class RunMaysyncContextManager(ta.Generic[T]):
|
528
|
+
def __init__(self, acm: ta.AsyncContextManager[T]) -> None:
|
529
|
+
self._acm = acm
|
530
|
+
|
531
|
+
def __repr__(self) -> str:
|
532
|
+
return f'{self.__class__.__name__}({self._acm!r})'
|
533
|
+
|
534
|
+
def __enter__(self) -> T:
|
535
|
+
return run_maysync(self._acm.__aenter__())
|
536
|
+
|
537
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
538
|
+
return run_maysync(self._acm.__aexit__(exc_type, exc_val, exc_tb))
|
539
|
+
|
540
|
+
|
541
|
+
run_maysync_context_manager = RunMaysyncContextManager
|
542
|
+
|
543
|
+
|
544
|
+
##
|
545
|
+
|
546
|
+
|
526
547
|
_MAYSYNC_MARK_ATTR = '__maysync__'
|
527
548
|
|
528
549
|
|
omlish/marshal/__init__.py
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
# ruff: noqa: I001
|
2
2
|
"""
|
3
3
|
TODO:
|
4
|
-
-
|
5
|
-
-
|
6
|
-
|
7
|
-
-
|
8
|
-
|
9
|
-
-
|
10
|
-
|
11
|
-
|
4
|
+
- streaming?
|
5
|
+
- datatypes
|
6
|
+
- redacted
|
7
|
+
- lang.Marker - class name, handle type[Foo]
|
8
|
+
- pathlib.Path
|
9
|
+
- decimal.Decimal
|
10
|
+
- datetime.date, datetime.time
|
11
|
+
- ipaddress
|
12
|
+
- numpy types
|
13
|
+
- jackson switches
|
14
|
+
- accept_case_insensitive_enums
|
15
|
+
- accept_case_insensitive_properties
|
16
|
+
- accept_case_insensitive_values
|
17
|
+
- allow_coercion_of_scalars
|
18
|
+
- use_base_type_as_default_impl
|
19
|
+
- codegen
|
20
|
+
- context-local switches
|
21
|
+
- mutable_collections
|
12
22
|
- simple lite interop like inj - alt ObjMarshalerManager impl for Context
|
13
23
|
|
14
24
|
See:
|
@@ -16,6 +26,8 @@ See:
|
|
16
26
|
- https://github.com/jcrist/msgspec
|
17
27
|
- https://github.com/Fatal1ty/mashumaro
|
18
28
|
- https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#custom-serializers
|
29
|
+
- https://github.com/yukinarit/pyserde
|
30
|
+
- https://github.com/FasterXML/jackson
|
19
31
|
"""
|
20
32
|
from .. import dataclasses as _dc # noqa
|
21
33
|
|
omlish/os/atomics.py
CHANGED
@@ -11,7 +11,7 @@ from ..lite.attrops import attr_repr
|
|
11
11
|
from ..lite.check import check
|
12
12
|
|
13
13
|
|
14
|
-
AtomicPathSwapKind = ta.Literal['dir', 'file']
|
14
|
+
AtomicPathSwapKind = ta.Literal['dir', 'file'] # ta.TypeAlias
|
15
15
|
AtomicPathSwapState = ta.Literal['open', 'committed', 'aborted'] # ta.TypeAlias
|
16
16
|
|
17
17
|
|
omlish/reflect/ops.py
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- visitor / transformer
|
4
|
+
- gson had an ObjectNavigator:
|
5
|
+
- https://github.com/google/gson/blob/f291c4d33ea5fcc52afcfa5713e519e663378bda/gson/src/main/java/com/google/gson/ObjectNavigator.java
|
6
|
+
- removed in 25c6ae177b1ca56db7f3c29eb574bdd032a06165
|
7
|
+
- uniform collection isinstance - items() for mappings, iter() for other
|
8
|
+
- also check instance type in isinstance not just items lol
|
9
|
+
""" # noqa
|
1
10
|
import dataclasses as dc
|
2
11
|
import typing as ta
|
3
12
|
|