omlish 0.0.0.dev433__py3-none-any.whl → 0.0.0.dev434__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.
Files changed (35) hide show
  1. omlish/__about__.py +2 -2
  2. omlish/asyncs/all.py +0 -13
  3. omlish/inject/__init__.py +152 -126
  4. omlish/inject/binder.py +7 -4
  5. omlish/inject/impl/elements.py +6 -8
  6. omlish/inject/impl/injector.py +58 -32
  7. omlish/inject/impl/inspect.py +1 -0
  8. omlish/inject/impl/maysync.py +44 -0
  9. omlish/inject/impl/multis.py +5 -5
  10. omlish/inject/impl/privates.py +8 -8
  11. omlish/inject/impl/providers.py +24 -31
  12. omlish/inject/impl/providers2.py +43 -0
  13. omlish/inject/impl/scopes.py +19 -25
  14. omlish/inject/impl/sync.py +42 -0
  15. omlish/inject/injector.py +9 -11
  16. omlish/inject/inspect.py +1 -3
  17. omlish/inject/listeners.py +4 -4
  18. omlish/inject/managed.py +52 -20
  19. omlish/inject/maysync.py +27 -0
  20. omlish/inject/providers.py +6 -0
  21. omlish/inject/scopes.py +38 -10
  22. omlish/inject/sync.py +46 -0
  23. omlish/lang/__init__.py +12 -3
  24. omlish/lang/asyncs.py +18 -0
  25. omlish/lang/contextmanagers.py +23 -0
  26. omlish/lite/asyncs.py +21 -0
  27. omlish/lite/maysync.py +21 -0
  28. {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev434.dist-info}/METADATA +1 -4
  29. {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev434.dist-info}/RECORD +33 -30
  30. omlish/asyncs/bridge.py +0 -359
  31. omlish/asyncs/utils.py +0 -18
  32. {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev434.dist-info}/WHEEL +0 -0
  33. {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev434.dist-info}/entry_points.txt +0 -0
  34. {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev434.dist-info}/licenses/LICENSE +0 -0
  35. {omlish-0.0.0.dev433.dist-info → omlish-0.0.0.dev434.dist-info}/top_level.txt +0 -0
@@ -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 Injector
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 InjectorImpl
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: Injector) -> ta.Any:
51
- return check.isinstance(injector, InjectorImpl).create_child(self.ec)
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: Injector) -> ta.Any:
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(InjectorImpl, tag=self.id)
85
+ return Key(AsyncInjectorImpl, tag=self.id)
86
86
 
87
87
  @cached.function
88
88
  def element_collection(self) -> ElementCollection:
@@ -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 Injector
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: Injector) -> ta.Any:
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 CallableProviderImpl(ProviderImpl, lang.Final):
47
- p: FnProvider | CtorProvider
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: Injector) -> ta.Any:
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 ConstProviderImpl(ProviderImpl, lang.Final):
63
- p: ConstProvider
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: Injector) -> ta.Any:
70
- return self.p.v
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 LinkProviderImpl(ProviderImpl, lang.Final):
78
- p: LinkProvider
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: Injector) -> ta.Any:
85
- return injector.provide(self.p.k)
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
- PROVIDER_IMPLS_BY_PROVIDER: dict[type[Provider], ta.Callable[..., ProviderImpl]] = {
92
- FnProvider: lambda p: CallableProviderImpl(p, build_kwargs_target(p.fn)),
93
- CtorProvider: lambda p: CallableProviderImpl(p, build_kwargs_target(p.ty)),
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
- def make_provider_impl(p: Provider) -> ProviderImpl:
101
- try:
102
- fac = PROVIDER_IMPLS_BY_PROVIDER[type(p)]
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
- raise TypeError(p)
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)
@@ -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 Injector
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
- if ta.TYPE_CHECKING:
36
- from . import injector as injector_
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: Injector) -> ta.Any:
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: Injector) -> ta.Any:
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: Injector) -> ta.Any:
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: Injector) -> ta.Any:
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: Injector) -> ta.Any:
124
- ii = check.isinstance(injector, injector_.InjectorImpl)
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: Injector) -> None:
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, injector_.InjectorImpl)
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.contextmanager
162
- def __call__(self, seeds: ta.Mapping[Key, ta.Any]) -> ta.Generator[None]:
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: Injector) -> ta.Any:
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
 
@@ -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
- if ta.TYPE_CHECKING:
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 Injector(lang.Abstract):
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 create_injector(*args: Elemental) -> Injector:
48
- return _injector.create_injector(as_elements(*args))
45
+ def create_async_injector(*args: Elemental) -> ta.Awaitable[AsyncInjector]:
46
+ return _injector.create_async_injector(as_elements(*args))
omlish/inject/inspect.py CHANGED
@@ -4,10 +4,8 @@ from .. import lang
4
4
  from .keys import Key
5
5
 
6
6
 
7
- if ta.TYPE_CHECKING:
7
+ with lang.auto_proxy_import(globals()):
8
8
  from .impl import inspect as _inspect
9
- else:
10
- _inspect = lang.proxy_import('.impl.inspect', __package__)
11
9
 
12
10
 
13
11
  T = ta.TypeVar('T')
@@ -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 Injector
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
- Injector,
15
+ AsyncInjector,
16
16
  Key,
17
17
  Binding | None,
18
- ta.Callable[[], ta.Any],
19
- ], ta.Callable[[], ta.Any]]
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
- if ta.TYPE_CHECKING:
17
- from ..asyncs import all as _asyncs
18
- else:
19
- _asyncs = lang.proxy_import('..asyncs.all', __package__)
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.asynccontextmanager
63
- async def create_async_managed_injector(*args: Elemental) -> ta.AsyncGenerator[Injector]:
64
- i = await _asyncs.s_to_a(create_injector)(
65
- bind(contextlib.AsyncExitStack, singleton=True, eager=True),
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
- async with i[contextlib.AsyncExitStack]:
100
+ with i[contextlib.ExitStack]:
69
101
  yield i
70
102
 
71
103
 
72
- def make_async_managed_provider(
104
+ def make_maysync_managed_provider(
73
105
  fac: ta.Callable[..., T],
74
- *fns: ta.Callable[[T], ta.AsyncContextManager[T]],
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: Injector,
80
- aes: contextlib.AsyncExitStack,
111
+ i: _maysync.MaysyncInjector,
112
+ es: contextlib.ExitStack,
81
113
  ):
82
114
  obj = i.inject(kt)
83
115
  if not fns:
84
- obj = _asyncs.a_to_s(aes.enter_async_context)(obj)
116
+ obj = es.enter_context(obj)
85
117
  else:
86
118
  for fn in fns:
87
- _asyncs.a_to_s(aes.enter_async_context)(fn(obj))
119
+ es.enter_context(fn(obj))
88
120
  return obj
89
121
 
90
122
  return _provide
@@ -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))
@@ -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):