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
omlish/inject/impl/elements.py
CHANGED
@@ -47,14 +47,12 @@ from .multis import make_multi_provider_impl
|
|
47
47
|
from .origins import Origins
|
48
48
|
from .origins import set_origins
|
49
49
|
from .providers import ProviderImpl
|
50
|
-
from .
|
50
|
+
from .providers2 import make_provider_impl
|
51
51
|
from .scopes import make_scope_impl
|
52
52
|
|
53
53
|
|
54
|
-
|
55
|
-
from . import privates as
|
56
|
-
else:
|
57
|
-
privates_ = lang.proxy_import('.privates', __package__)
|
54
|
+
with lang.auto_proxy_import(globals()):
|
55
|
+
from . import privates as _privates
|
58
56
|
|
59
57
|
|
60
58
|
ElementT = ta.TypeVar('ElementT', bound=Element)
|
@@ -69,17 +67,17 @@ class ElementCollection(lang.Final):
|
|
69
67
|
|
70
68
|
self._es = check.isinstance(es, Elements)
|
71
69
|
|
72
|
-
self._private_infos: ta.MutableMapping[Private,
|
70
|
+
self._private_infos: ta.MutableMapping[Private, _privates.PrivateInfo] | None = None
|
73
71
|
|
74
72
|
##
|
75
73
|
|
76
|
-
def _get_private_info(self, p: Private) -> '
|
74
|
+
def _get_private_info(self, p: Private) -> '_privates.PrivateInfo':
|
77
75
|
if (pis := self._private_infos) is None:
|
78
76
|
self._private_infos = pis = col.IdentityKeyDict()
|
79
77
|
try:
|
80
78
|
return pis[p]
|
81
79
|
except KeyError:
|
82
|
-
pis[p] = ec =
|
80
|
+
pis[p] = ec = _privates.PrivateInfo(self, p)
|
83
81
|
return ec
|
84
82
|
|
85
83
|
##
|
omlish/inject/impl/injector.py
CHANGED
@@ -25,7 +25,7 @@ from ...logs import all as logs
|
|
25
25
|
from ..elements import Elements
|
26
26
|
from ..errors import CyclicDependencyError
|
27
27
|
from ..errors import UnboundKeyError
|
28
|
-
from ..injector import
|
28
|
+
from ..injector import AsyncInjector
|
29
29
|
from ..inspect import KwargsTarget
|
30
30
|
from ..keys import Key
|
31
31
|
from ..keys import as_key
|
@@ -55,15 +55,22 @@ DEFAULT_SCOPES: list[Scope] = [
|
|
55
55
|
]
|
56
56
|
|
57
57
|
|
58
|
-
class
|
59
|
-
def __init__(
|
58
|
+
class AsyncInjectorImpl(AsyncInjector, lang.Final):
|
59
|
+
def __init__(
|
60
|
+
self,
|
61
|
+
ec: ElementCollection,
|
62
|
+
p: ta.Optional['AsyncInjectorImpl'] = None,
|
63
|
+
*,
|
64
|
+
internal_consts: dict[Key, ta.Any] | None = None,
|
65
|
+
) -> None:
|
60
66
|
super().__init__()
|
61
67
|
|
62
68
|
self._ec = check.isinstance(ec, ElementCollection)
|
63
|
-
self._p:
|
69
|
+
self._p: AsyncInjectorImpl | None = check.isinstance(p, (AsyncInjectorImpl, None))
|
64
70
|
|
65
71
|
self._internal_consts: dict[Key, ta.Any] = {
|
66
|
-
Key(
|
72
|
+
Key(AsyncInjector): self,
|
73
|
+
**(internal_consts or {}),
|
67
74
|
}
|
68
75
|
|
69
76
|
self._bim = ec.binding_impl_map()
|
@@ -76,10 +83,10 @@ class InjectorImpl(Injector, lang.Final):
|
|
76
83
|
)
|
77
84
|
)
|
78
85
|
|
79
|
-
self._cs: weakref.WeakSet[
|
80
|
-
self._root:
|
86
|
+
self._cs: weakref.WeakSet[AsyncInjectorImpl] | None = None
|
87
|
+
self._root: AsyncInjectorImpl = p._root if p is not None else self # noqa
|
81
88
|
|
82
|
-
self.__cur_req:
|
89
|
+
self.__cur_req: AsyncInjectorImpl._Request | None = None
|
83
90
|
|
84
91
|
ss = [
|
85
92
|
*DEFAULT_SCOPES,
|
@@ -89,27 +96,41 @@ class InjectorImpl(Injector, lang.Final):
|
|
89
96
|
s: make_scope_impl(s) for s in ss
|
90
97
|
}
|
91
98
|
|
92
|
-
|
93
|
-
|
99
|
+
#
|
100
|
+
|
101
|
+
_has_run_init: bool = False
|
102
|
+
|
103
|
+
async def _init(self) -> bool:
|
104
|
+
if self._has_run_init:
|
105
|
+
return False
|
106
|
+
|
107
|
+
self._has_run_init = True
|
108
|
+
|
109
|
+
await self._instantiate_eagers(Unscoped())
|
110
|
+
await self._instantiate_eagers(Singleton())
|
94
111
|
|
95
|
-
|
112
|
+
return True
|
96
113
|
|
97
|
-
|
114
|
+
#
|
115
|
+
|
116
|
+
_root: 'AsyncInjectorImpl'
|
117
|
+
|
118
|
+
async def _instantiate_eagers(self, sc: Scope) -> None:
|
98
119
|
for k in self._ekbs.get(sc, ()):
|
99
|
-
self.provide(k)
|
120
|
+
await self.provide(k)
|
100
121
|
|
101
122
|
def get_scope_impl(self, sc: Scope) -> ScopeImpl:
|
102
123
|
return self._scopes[sc]
|
103
124
|
|
104
|
-
def create_child(self, ec: ElementCollection) ->
|
105
|
-
c =
|
125
|
+
def create_child(self, ec: ElementCollection) -> AsyncInjector:
|
126
|
+
c = AsyncInjectorImpl(ec, self)
|
106
127
|
if self._cs is None:
|
107
128
|
self._cs = weakref.WeakSet()
|
108
129
|
self._cs.add(c)
|
109
130
|
return c
|
110
131
|
|
111
132
|
class _Request:
|
112
|
-
def __init__(self, injector: '
|
133
|
+
def __init__(self, injector: 'AsyncInjectorImpl') -> None:
|
113
134
|
super().__init__()
|
114
135
|
|
115
136
|
self._injector = injector
|
@@ -162,10 +183,13 @@ class InjectorImpl(Injector, lang.Final):
|
|
162
183
|
finally:
|
163
184
|
self.__cur_req = None
|
164
185
|
|
165
|
-
def _try_provide(self, key: ta.Any, *, source: ta.Any = None) -> lang.Maybe[ta.Any]:
|
186
|
+
async def _try_provide(self, key: ta.Any, *, source: ta.Any = None) -> lang.Maybe[ta.Any]:
|
187
|
+
if not self._has_run_init:
|
188
|
+
await self._init()
|
189
|
+
|
166
190
|
key = as_key(key)
|
167
191
|
|
168
|
-
cr:
|
192
|
+
cr: AsyncInjectorImpl._Request
|
169
193
|
with self._current_request() as cr:
|
170
194
|
with cr.push_source(source):
|
171
195
|
if (rv := cr.handle_key(key)).present:
|
@@ -182,55 +206,57 @@ class InjectorImpl(Injector, lang.Final):
|
|
182
206
|
fn = lambda: sc.provide(bi, self) # noqa
|
183
207
|
for pl in self._pls:
|
184
208
|
fn = functools.partial(pl, self, key, bi.binding, fn)
|
185
|
-
v = fn()
|
209
|
+
v = await fn()
|
186
210
|
|
187
211
|
return cr.handle_provision(key, lang.just(v))
|
188
212
|
|
189
213
|
if self._p is not None:
|
190
|
-
pv = self._p._try_provide(key, source=source) # noqa
|
214
|
+
pv = await self._p._try_provide(key, source=source) # noqa
|
191
215
|
if pv.present:
|
192
216
|
return cr.handle_provision(key, pv)
|
193
217
|
|
194
218
|
return cr.handle_provision(key, lang.empty())
|
195
219
|
|
196
|
-
def _provide(self, key: ta.Any, *, source: ta.Any = None) -> ta.Any:
|
197
|
-
v = self._try_provide(key, source=source)
|
220
|
+
async def _provide(self, key: ta.Any, *, source: ta.Any = None) -> ta.Any:
|
221
|
+
v = await self._try_provide(key, source=source)
|
198
222
|
if v.present:
|
199
223
|
return v.must()
|
200
224
|
raise UnboundKeyError(key)
|
201
225
|
|
202
226
|
#
|
203
227
|
|
204
|
-
def try_provide(self, key: ta.Any) -> lang.Maybe[ta.Any]:
|
228
|
+
def try_provide(self, key: ta.Any) -> ta.Awaitable[lang.Maybe[ta.Any]]:
|
205
229
|
return self._try_provide(key)
|
206
230
|
|
207
|
-
def provide(self, key: ta.Any) -> ta.Any:
|
208
|
-
v = self._try_provide(key)
|
231
|
+
async def provide(self, key: ta.Any) -> ta.Any:
|
232
|
+
v = await self._try_provide(key)
|
209
233
|
if v.present:
|
210
234
|
return v.must()
|
211
235
|
raise UnboundKeyError(key)
|
212
236
|
|
213
|
-
def provide_kwargs(self, kt: KwargsTarget) -> ta.Mapping[str, ta.Any]:
|
237
|
+
async def provide_kwargs(self, kt: KwargsTarget) -> ta.Mapping[str, ta.Any]:
|
214
238
|
ret: dict[str, ta.Any] = {}
|
215
239
|
for kw in kt.kwargs:
|
216
240
|
if kw.has_default:
|
217
|
-
if not (mv := self._try_provide(kw.key, source=kt)).present:
|
241
|
+
if not (mv := await self._try_provide(kw.key, source=kt)).present:
|
218
242
|
continue
|
219
243
|
v = mv.must()
|
220
244
|
else:
|
221
|
-
v = self._provide(kw.key, source=kt)
|
245
|
+
v = await self._provide(kw.key, source=kt)
|
222
246
|
ret[kw.name] = v
|
223
247
|
return ret
|
224
248
|
|
225
|
-
def inject(self, obj: ta.Any) -> ta.Any:
|
249
|
+
async def inject(self, obj: ta.Any) -> ta.Any:
|
226
250
|
if isinstance(obj, KwargsTarget):
|
227
251
|
obj, kt = obj.obj, obj
|
228
252
|
else:
|
229
253
|
kt = build_kwargs_target(obj)
|
230
|
-
kws = self.provide_kwargs(kt)
|
254
|
+
kws = await self.provide_kwargs(kt)
|
231
255
|
# FIXME: still 'injecting' (as in has a req) if ctor needs and uses Injector
|
232
256
|
return obj(**kws)
|
233
257
|
|
234
258
|
|
235
|
-
def
|
236
|
-
|
259
|
+
async def create_async_injector(es: Elements) -> AsyncInjector:
|
260
|
+
i = AsyncInjectorImpl(ElementCollection(es))
|
261
|
+
await i._init() # noqa
|
262
|
+
return i
|
omlish/inject/impl/inspect.py
CHANGED
@@ -0,0 +1,44 @@
|
|
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 ..maysync import MaysyncInjector
|
9
|
+
from ..sync import Injector
|
10
|
+
from .elements import ElementCollection
|
11
|
+
from .injector import AsyncInjectorImpl
|
12
|
+
|
13
|
+
|
14
|
+
##
|
15
|
+
|
16
|
+
|
17
|
+
class MaysyncInjectorImpl(MaysyncInjector, lang.Final):
|
18
|
+
_ai: AsyncInjector
|
19
|
+
|
20
|
+
def try_provide(self, key: ta.Any) -> lang.Maybe[ta.Any]:
|
21
|
+
return lang.run_maysync(self._ai.try_provide(key))
|
22
|
+
|
23
|
+
def provide(self, key: ta.Any) -> ta.Any:
|
24
|
+
return lang.run_maysync(self._ai.provide(key))
|
25
|
+
|
26
|
+
def provide_kwargs(self, kt: KwargsTarget) -> ta.Mapping[str, ta.Any]:
|
27
|
+
return lang.run_maysync(self._ai.provide_kwargs(kt))
|
28
|
+
|
29
|
+
def inject(self, obj: ta.Any) -> ta.Any:
|
30
|
+
return lang.run_maysync(self._ai.inject(obj))
|
31
|
+
|
32
|
+
|
33
|
+
def create_maysync_injector(es: Elements) -> MaysyncInjector:
|
34
|
+
si = MaysyncInjectorImpl()
|
35
|
+
ai = AsyncInjectorImpl(
|
36
|
+
ElementCollection(es),
|
37
|
+
internal_consts={
|
38
|
+
Key(MaysyncInjector): si,
|
39
|
+
Key(Injector): si,
|
40
|
+
},
|
41
|
+
)
|
42
|
+
si._ai = ai # noqa
|
43
|
+
lang.run_maysync(ai._init()) # noqa
|
44
|
+
return si
|
omlish/inject/impl/multis.py
CHANGED
@@ -3,7 +3,7 @@ import typing as ta
|
|
3
3
|
from ... import dataclasses as dc
|
4
4
|
from ... import lang
|
5
5
|
from ..elements import Element
|
6
|
-
from ..injector import
|
6
|
+
from ..injector import AsyncInjector
|
7
7
|
from ..multis import MapBinding
|
8
8
|
from ..multis import MapProvider
|
9
9
|
from ..multis import SetBinding
|
@@ -26,10 +26,10 @@ class SetProviderImpl(ProviderImpl, lang.Final):
|
|
26
26
|
for p in self.ps:
|
27
27
|
yield from p.providers
|
28
28
|
|
29
|
-
def provide(self, injector:
|
29
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
30
30
|
rv = set()
|
31
31
|
for ep in self.ps:
|
32
|
-
o = ep.provide(injector)
|
32
|
+
o = await ep.provide(injector)
|
33
33
|
rv.add(o)
|
34
34
|
return rv
|
35
35
|
|
@@ -47,10 +47,10 @@ class MapProviderImpl(ProviderImpl, lang.Final):
|
|
47
47
|
for e in self.es:
|
48
48
|
yield from e.v.providers
|
49
49
|
|
50
|
-
def provide(self, injector:
|
50
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
51
51
|
rv = {}
|
52
52
|
for e in self.es:
|
53
|
-
o = e.v.provide(injector)
|
53
|
+
o = await e.v.provide(injector)
|
54
54
|
rv[e.k] = o
|
55
55
|
return rv
|
56
56
|
|
omlish/inject/impl/privates.py
CHANGED
@@ -12,14 +12,14 @@ from ... import lang
|
|
12
12
|
from ..bindings import Binding
|
13
13
|
from ..eagers import Eager
|
14
14
|
from ..elements import Element
|
15
|
-
from ..injector import
|
15
|
+
from ..injector import AsyncInjector
|
16
16
|
from ..keys import Key
|
17
17
|
from ..privates import Expose
|
18
18
|
from ..privates import Private
|
19
19
|
from ..providers import Provider
|
20
20
|
from ..scopes import Singleton
|
21
21
|
from .elements import ElementCollection
|
22
|
-
from .injector import
|
22
|
+
from .injector import AsyncInjectorImpl
|
23
23
|
from .providers import InternalProvider
|
24
24
|
from .providers import ProviderImpl
|
25
25
|
|
@@ -47,8 +47,8 @@ class PrivateInjectorProviderImpl(ProviderImpl, lang.Final):
|
|
47
47
|
def providers(self) -> ta.Iterable[Provider]:
|
48
48
|
return ()
|
49
49
|
|
50
|
-
def provide(self, injector:
|
51
|
-
return check.isinstance(injector,
|
50
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
51
|
+
return check.isinstance(injector, AsyncInjectorImpl).create_child(self.ec)
|
52
52
|
|
53
53
|
|
54
54
|
##
|
@@ -63,9 +63,9 @@ class ExposedPrivateProviderImpl(ProviderImpl, lang.Final):
|
|
63
63
|
def providers(self) -> ta.Iterable[Provider]:
|
64
64
|
return ()
|
65
65
|
|
66
|
-
def provide(self, injector:
|
67
|
-
pi = injector.provide(self.pik)
|
68
|
-
return pi.provide(self.k)
|
66
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
67
|
+
pi = await injector.provide(self.pik)
|
68
|
+
return await pi.provide(self.k)
|
69
69
|
|
70
70
|
|
71
71
|
##
|
@@ -82,7 +82,7 @@ class PrivateInfo(lang.Final):
|
|
82
82
|
|
83
83
|
@cached.property
|
84
84
|
def pik(self) -> Key:
|
85
|
-
return Key(
|
85
|
+
return Key(AsyncInjectorImpl, tag=self.id)
|
86
86
|
|
87
87
|
@cached.function
|
88
88
|
def element_collection(self) -> ElementCollection:
|
omlish/inject/impl/providers.py
CHANGED
@@ -7,14 +7,14 @@ import typing as ta
|
|
7
7
|
|
8
8
|
from ... import dataclasses as dc
|
9
9
|
from ... import lang
|
10
|
-
from ..injector import
|
10
|
+
from ..injector import AsyncInjector
|
11
11
|
from ..inspect import KwargsTarget
|
12
|
+
from ..providers import AsyncFnProvider
|
12
13
|
from ..providers import ConstProvider
|
13
14
|
from ..providers import CtorProvider
|
14
15
|
from ..providers import FnProvider
|
15
16
|
from ..providers import LinkProvider
|
16
17
|
from ..providers import Provider
|
17
|
-
from .inspect import build_kwargs_target
|
18
18
|
|
19
19
|
|
20
20
|
##
|
@@ -27,7 +27,7 @@ class ProviderImpl(lang.Abstract):
|
|
27
27
|
raise NotImplementedError
|
28
28
|
|
29
29
|
@abc.abstractmethod
|
30
|
-
def provide(self, injector:
|
30
|
+
def provide(self, injector: AsyncInjector) -> ta.Awaitable[ta.Any]:
|
31
31
|
raise NotImplementedError
|
32
32
|
|
33
33
|
|
@@ -43,66 +43,59 @@ class InternalProvider(Provider):
|
|
43
43
|
|
44
44
|
|
45
45
|
@dc.dataclass(frozen=True, eq=False)
|
46
|
-
class
|
47
|
-
p:
|
46
|
+
class AsyncCallableProviderImpl(ProviderImpl, lang.Final):
|
47
|
+
p: AsyncFnProvider
|
48
48
|
kt: KwargsTarget
|
49
49
|
|
50
50
|
@property
|
51
51
|
def providers(self) -> ta.Iterable[Provider]:
|
52
52
|
return (self.p,)
|
53
53
|
|
54
|
-
def provide(self, injector:
|
55
|
-
return injector.inject(self.kt)
|
54
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
55
|
+
return await (await injector.inject(self.kt))
|
56
56
|
|
57
57
|
|
58
58
|
##
|
59
59
|
|
60
60
|
|
61
61
|
@dc.dataclass(frozen=True, eq=False)
|
62
|
-
class
|
63
|
-
p:
|
62
|
+
class CallableProviderImpl(ProviderImpl, lang.Final):
|
63
|
+
p: FnProvider | CtorProvider
|
64
|
+
kt: KwargsTarget
|
64
65
|
|
65
66
|
@property
|
66
67
|
def providers(self) -> ta.Iterable[Provider]:
|
67
68
|
return (self.p,)
|
68
69
|
|
69
|
-
def provide(self, injector:
|
70
|
-
return self.
|
70
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
71
|
+
return await injector.inject(self.kt)
|
71
72
|
|
72
73
|
|
73
74
|
##
|
74
75
|
|
75
76
|
|
76
77
|
@dc.dataclass(frozen=True, eq=False)
|
77
|
-
class
|
78
|
-
p:
|
78
|
+
class ConstProviderImpl(ProviderImpl, lang.Final):
|
79
|
+
p: ConstProvider
|
79
80
|
|
80
81
|
@property
|
81
82
|
def providers(self) -> ta.Iterable[Provider]:
|
82
83
|
return (self.p,)
|
83
84
|
|
84
|
-
def provide(self, injector:
|
85
|
-
return
|
85
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
86
|
+
return self.p.v
|
86
87
|
|
87
88
|
|
88
89
|
##
|
89
90
|
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
ConstProvider: ConstProviderImpl,
|
95
|
-
LinkProvider: LinkProviderImpl,
|
96
|
-
InternalProvider: lambda p: p.impl,
|
97
|
-
}
|
98
|
-
|
92
|
+
@dc.dataclass(frozen=True, eq=False)
|
93
|
+
class LinkProviderImpl(ProviderImpl, lang.Final):
|
94
|
+
p: LinkProvider
|
99
95
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
except KeyError:
|
104
|
-
pass
|
105
|
-
else:
|
106
|
-
return fac(p)
|
96
|
+
@property
|
97
|
+
def providers(self) -> ta.Iterable[Provider]:
|
98
|
+
return (self.p,)
|
107
99
|
|
108
|
-
|
100
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
101
|
+
return await injector.provide(self.p.k)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from ..providers import AsyncFnProvider
|
4
|
+
from ..providers import ConstProvider
|
5
|
+
from ..providers import CtorProvider
|
6
|
+
from ..providers import FnProvider
|
7
|
+
from ..providers import LinkProvider
|
8
|
+
from ..providers import Provider
|
9
|
+
from ..scopes import ScopeSeededProvider
|
10
|
+
from .inspect import build_kwargs_target
|
11
|
+
from .providers import AsyncCallableProviderImpl
|
12
|
+
from .providers import CallableProviderImpl
|
13
|
+
from .providers import ConstProviderImpl
|
14
|
+
from .providers import InternalProvider
|
15
|
+
from .providers import LinkProviderImpl
|
16
|
+
from .providers import ProviderImpl
|
17
|
+
from .scopes import ScopeSeededProviderImpl
|
18
|
+
|
19
|
+
|
20
|
+
##
|
21
|
+
|
22
|
+
|
23
|
+
PROVIDER_IMPLS_BY_PROVIDER: dict[type[Provider], ta.Callable[..., ProviderImpl]] = {
|
24
|
+
AsyncFnProvider: lambda p: AsyncCallableProviderImpl(p, build_kwargs_target(p.fn)),
|
25
|
+
FnProvider: lambda p: CallableProviderImpl(p, build_kwargs_target(p.fn)),
|
26
|
+
CtorProvider: lambda p: CallableProviderImpl(p, build_kwargs_target(p.ty)),
|
27
|
+
ConstProvider: ConstProviderImpl,
|
28
|
+
LinkProvider: LinkProviderImpl,
|
29
|
+
InternalProvider: lambda p: p.impl,
|
30
|
+
|
31
|
+
ScopeSeededProvider: ScopeSeededProviderImpl,
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
def make_provider_impl(p: Provider) -> ProviderImpl:
|
36
|
+
try:
|
37
|
+
fac = PROVIDER_IMPLS_BY_PROVIDER[type(p)]
|
38
|
+
except KeyError:
|
39
|
+
pass
|
40
|
+
else:
|
41
|
+
return fac(p)
|
42
|
+
|
43
|
+
raise TypeError(p)
|
omlish/inject/impl/scopes.py
CHANGED
@@ -17,7 +17,7 @@ from ..elements import Elements
|
|
17
17
|
from ..elements import as_elements
|
18
18
|
from ..errors import ScopeAlreadyOpenError
|
19
19
|
from ..errors import ScopeNotOpenError
|
20
|
-
from ..injector import
|
20
|
+
from ..injector import AsyncInjector
|
21
21
|
from ..keys import Key
|
22
22
|
from ..providers import FnProvider
|
23
23
|
from ..providers import Provider
|
@@ -28,14 +28,11 @@ from ..scopes import ThreadScope
|
|
28
28
|
from ..types import Scope
|
29
29
|
from ..types import Unscoped
|
30
30
|
from .bindings import BindingImpl
|
31
|
-
from .providers import PROVIDER_IMPLS_BY_PROVIDER
|
32
31
|
from .providers import ProviderImpl
|
33
32
|
|
34
33
|
|
35
|
-
|
36
|
-
from . import injector as
|
37
|
-
else:
|
38
|
-
injector_ = lang.proxy_import('.injector', __package__)
|
34
|
+
with lang.auto_proxy_import(globals()):
|
35
|
+
from . import injector as _injector
|
39
36
|
|
40
37
|
|
41
38
|
##
|
@@ -51,7 +48,7 @@ class ScopeImpl(lang.Abstract):
|
|
51
48
|
return None
|
52
49
|
|
53
50
|
@abc.abstractmethod
|
54
|
-
def provide(self, binding: BindingImpl, injector:
|
51
|
+
def provide(self, binding: BindingImpl, injector: AsyncInjector) -> ta.Awaitable[ta.Any]:
|
55
52
|
raise NotImplementedError
|
56
53
|
|
57
54
|
|
@@ -60,8 +57,8 @@ class UnscopedScopeImpl(ScopeImpl, lang.Final):
|
|
60
57
|
def scope(self) -> Unscoped:
|
61
58
|
return Unscoped()
|
62
59
|
|
63
|
-
def provide(self, binding: BindingImpl, injector:
|
64
|
-
return binding.provider.provide(injector)
|
60
|
+
async def provide(self, binding: BindingImpl, injector: AsyncInjector) -> ta.Any:
|
61
|
+
return await binding.provider.provide(injector)
|
65
62
|
|
66
63
|
|
67
64
|
class SingletonScopeImpl(ScopeImpl, lang.Final):
|
@@ -74,12 +71,12 @@ class SingletonScopeImpl(ScopeImpl, lang.Final):
|
|
74
71
|
def scope(self) -> Singleton:
|
75
72
|
return Singleton()
|
76
73
|
|
77
|
-
def provide(self, binding: BindingImpl, injector:
|
74
|
+
async def provide(self, binding: BindingImpl, injector: AsyncInjector) -> ta.Any:
|
78
75
|
try:
|
79
76
|
return self._dct[binding]
|
80
77
|
except KeyError:
|
81
78
|
pass
|
82
|
-
v = binding.provider.provide(injector)
|
79
|
+
v = await binding.provider.provide(injector)
|
83
80
|
self._dct[binding] = v
|
84
81
|
return v
|
85
82
|
|
@@ -94,7 +91,7 @@ class ThreadScopeImpl(ScopeImpl, lang.Final):
|
|
94
91
|
def scope(self) -> ThreadScope:
|
95
92
|
return ThreadScope()
|
96
93
|
|
97
|
-
def provide(self, binding: BindingImpl, injector:
|
94
|
+
async def provide(self, binding: BindingImpl, injector: AsyncInjector) -> ta.Any:
|
98
95
|
dct: dict[BindingImpl, ta.Any]
|
99
96
|
try:
|
100
97
|
dct = self._local.dct
|
@@ -104,7 +101,7 @@ class ThreadScopeImpl(ScopeImpl, lang.Final):
|
|
104
101
|
return dct[binding]
|
105
102
|
except KeyError:
|
106
103
|
pass
|
107
|
-
v = binding.provider.provide(injector)
|
104
|
+
v = await binding.provider.provide(injector)
|
108
105
|
dct[binding] = v
|
109
106
|
return v
|
110
107
|
|
@@ -120,15 +117,12 @@ class ScopeSeededProviderImpl(ProviderImpl):
|
|
120
117
|
def providers(self) -> ta.Iterable[Provider]:
|
121
118
|
return (self.p,)
|
122
119
|
|
123
|
-
def provide(self, injector:
|
124
|
-
ii = check.isinstance(injector,
|
120
|
+
async def provide(self, injector: AsyncInjector) -> ta.Any:
|
121
|
+
ii = check.isinstance(injector, _injector.AsyncInjectorImpl)
|
125
122
|
ssi = check.isinstance(ii.get_scope_impl(self.p.ss), SeededScopeImpl)
|
126
123
|
return ssi.must_state().seeds[self.p.key]
|
127
124
|
|
128
125
|
|
129
|
-
PROVIDER_IMPLS_BY_PROVIDER[ScopeSeededProvider] = ScopeSeededProviderImpl
|
130
|
-
|
131
|
-
|
132
126
|
class SeededScopeImpl(ScopeImpl):
|
133
127
|
@dc.dataclass(frozen=True)
|
134
128
|
class State:
|
@@ -151,20 +145,20 @@ class SeededScopeImpl(ScopeImpl):
|
|
151
145
|
return st
|
152
146
|
|
153
147
|
class Manager(SeededScope.Manager, lang.Final):
|
154
|
-
def __init__(self, ss: SeededScope, i:
|
148
|
+
def __init__(self, ss: SeededScope, i: AsyncInjector) -> None:
|
155
149
|
super().__init__()
|
156
150
|
|
157
151
|
self._ss = check.isinstance(ss, SeededScope)
|
158
|
-
self._ii = check.isinstance(i,
|
152
|
+
self._ii = check.isinstance(i, _injector.AsyncInjectorImpl)
|
159
153
|
self._ssi = check.isinstance(self._ii.get_scope_impl(self._ss), SeededScopeImpl)
|
160
154
|
|
161
|
-
@contextlib.
|
162
|
-
def __call__(self, seeds: ta.Mapping[Key, ta.Any]) -> ta.
|
155
|
+
@contextlib.asynccontextmanager
|
156
|
+
async def __call__(self, seeds: ta.Mapping[Key, ta.Any]) -> ta.AsyncGenerator[None]:
|
163
157
|
try:
|
164
158
|
if self._ssi._st is not None: # noqa
|
165
159
|
raise ScopeAlreadyOpenError(self._ss)
|
166
160
|
self._ssi._st = SeededScopeImpl.State(dict(seeds)) # noqa
|
167
|
-
self._ii._instantiate_eagers(self._ss) # noqa
|
161
|
+
await self._ii._instantiate_eagers(self._ss) # noqa
|
168
162
|
yield
|
169
163
|
finally:
|
170
164
|
if self._ssi._st is None: # noqa
|
@@ -180,13 +174,13 @@ class SeededScopeImpl(ScopeImpl):
|
|
180
174
|
),
|
181
175
|
)
|
182
176
|
|
183
|
-
def provide(self, binding: BindingImpl, injector:
|
177
|
+
async def provide(self, binding: BindingImpl, injector: AsyncInjector) -> ta.Any:
|
184
178
|
st = self.must_state()
|
185
179
|
try:
|
186
180
|
return st.prvs[binding]
|
187
181
|
except KeyError:
|
188
182
|
pass
|
189
|
-
v = binding.provider.provide(injector)
|
183
|
+
v = await binding.provider.provide(injector)
|
190
184
|
st.prvs[binding] = v
|
191
185
|
return v
|
192
186
|
|