anydi 0.27.0a5__py3-none-any.whl → 0.27.0a6__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.
- anydi/_container.py +10 -28
- anydi/_context.py +28 -4
- anydi/_types.py +11 -0
- {anydi-0.27.0a5.dist-info → anydi-0.27.0a6.dist-info}/METADATA +1 -1
- {anydi-0.27.0a5.dist-info → anydi-0.27.0a6.dist-info}/RECORD +8 -8
- {anydi-0.27.0a5.dist-info → anydi-0.27.0a6.dist-info}/WHEEL +1 -1
- {anydi-0.27.0a5.dist-info → anydi-0.27.0a6.dist-info}/LICENSE +0 -0
- {anydi-0.27.0a5.dist-info → anydi-0.27.0a6.dist-info}/entry_points.txt +0 -0
anydi/_container.py
CHANGED
|
@@ -11,11 +11,9 @@ from contextvars import ContextVar
|
|
|
11
11
|
from functools import wraps
|
|
12
12
|
from typing import (
|
|
13
13
|
Any,
|
|
14
|
-
AsyncContextManager,
|
|
15
14
|
AsyncIterator,
|
|
16
15
|
Awaitable,
|
|
17
16
|
Callable,
|
|
18
|
-
ContextManager,
|
|
19
17
|
Iterable,
|
|
20
18
|
Iterator,
|
|
21
19
|
Mapping,
|
|
@@ -43,7 +41,7 @@ from ._context import (
|
|
|
43
41
|
from ._logger import logger
|
|
44
42
|
from ._module import Module, ModuleRegistry
|
|
45
43
|
from ._scanner import Scanner
|
|
46
|
-
from ._types import AnyInterface, Interface, Provider, Scope, is_marker
|
|
44
|
+
from ._types import AnyInterface, Event, Interface, Provider, Scope, is_marker
|
|
47
45
|
from ._utils import (
|
|
48
46
|
get_full_qualname,
|
|
49
47
|
get_typed_parameters,
|
|
@@ -86,7 +84,7 @@ class Container:
|
|
|
86
84
|
strict: Whether to enable strict mode. Defaults to False.
|
|
87
85
|
"""
|
|
88
86
|
self._providers: dict[type[Any], Provider] = {}
|
|
89
|
-
self.
|
|
87
|
+
self._resource_cache: dict[Scope, list[type[Any]]] = defaultdict(list)
|
|
90
88
|
self._singleton_context = SingletonContext(self)
|
|
91
89
|
self._transient_context = TransientContext(self)
|
|
92
90
|
self._request_context_var: ContextVar[RequestContext | None] = ContextVar(
|
|
@@ -172,7 +170,7 @@ class Container:
|
|
|
172
170
|
|
|
173
171
|
# Create Event type
|
|
174
172
|
if provider.is_resource and (interface is NoneType or interface is None):
|
|
175
|
-
interface = type(f"Event_{uuid.uuid4().hex}", (), {})
|
|
173
|
+
interface = type(f"Event_{uuid.uuid4().hex}", (Event,), {})
|
|
176
174
|
|
|
177
175
|
if interface in self._providers:
|
|
178
176
|
if override:
|
|
@@ -286,7 +284,7 @@ class Container:
|
|
|
286
284
|
"""
|
|
287
285
|
self._providers[interface] = provider
|
|
288
286
|
if provider.is_resource:
|
|
289
|
-
self.
|
|
287
|
+
self._resource_cache[provider.scope].append(interface)
|
|
290
288
|
|
|
291
289
|
def _delete_provider(self, interface: AnyInterface) -> None:
|
|
292
290
|
"""Delete a provider by interface.
|
|
@@ -296,7 +294,7 @@ class Container:
|
|
|
296
294
|
"""
|
|
297
295
|
provider = self._providers.pop(interface, None)
|
|
298
296
|
if provider is not None and provider.is_resource:
|
|
299
|
-
self.
|
|
297
|
+
self._resource_cache[provider.scope].remove(interface)
|
|
300
298
|
|
|
301
299
|
def _validate_provider_scope(self, provider: Provider) -> None:
|
|
302
300
|
"""Validate the scope of a provider.
|
|
@@ -443,20 +441,13 @@ class Container:
|
|
|
443
441
|
"""Close the singleton context."""
|
|
444
442
|
self._singleton_context.close()
|
|
445
443
|
|
|
446
|
-
|
|
444
|
+
@contextlib.contextmanager
|
|
445
|
+
def request_context(self) -> Iterator[None]:
|
|
447
446
|
"""Obtain a context manager for the request-scoped context.
|
|
448
447
|
|
|
449
448
|
Returns:
|
|
450
449
|
A context manager for the request-scoped context.
|
|
451
450
|
"""
|
|
452
|
-
return contextlib.contextmanager(self._request_context)()
|
|
453
|
-
|
|
454
|
-
def _request_context(self) -> Iterator[None]:
|
|
455
|
-
"""Internal method that manages the request-scoped context.
|
|
456
|
-
|
|
457
|
-
Yields:
|
|
458
|
-
Yield control to the code block within the request context.
|
|
459
|
-
"""
|
|
460
451
|
context = RequestContext(self)
|
|
461
452
|
token = self._request_context_var.set(context)
|
|
462
453
|
with context:
|
|
@@ -479,28 +470,19 @@ class Container:
|
|
|
479
470
|
|
|
480
471
|
async def astart(self) -> None:
|
|
481
472
|
"""Start the singleton context asynchronously."""
|
|
482
|
-
|
|
483
|
-
if provider.scope == "singleton":
|
|
484
|
-
await self.aresolve(interface) # noqa
|
|
473
|
+
await self._singleton_context.astart()
|
|
485
474
|
|
|
486
475
|
async def aclose(self) -> None:
|
|
487
476
|
"""Close the singleton context asynchronously."""
|
|
488
477
|
await self._singleton_context.aclose()
|
|
489
478
|
|
|
490
|
-
|
|
479
|
+
@contextlib.asynccontextmanager
|
|
480
|
+
async def arequest_context(self) -> AsyncIterator[None]:
|
|
491
481
|
"""Obtain an async context manager for the request-scoped context.
|
|
492
482
|
|
|
493
483
|
Returns:
|
|
494
484
|
An async context manager for the request-scoped context.
|
|
495
485
|
"""
|
|
496
|
-
return contextlib.asynccontextmanager(self._arequest_context)()
|
|
497
|
-
|
|
498
|
-
async def _arequest_context(self) -> AsyncIterator[None]:
|
|
499
|
-
"""Internal method that manages the async request-scoped context.
|
|
500
|
-
|
|
501
|
-
Yields:
|
|
502
|
-
Yield control to the code block within the request context.
|
|
503
|
-
"""
|
|
504
486
|
context = RequestContext(self)
|
|
505
487
|
token = self._request_context_var.set(context)
|
|
506
488
|
async with context:
|
anydi/_context.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, TypeVar, cast
|
|
|
7
7
|
|
|
8
8
|
from typing_extensions import Self, final
|
|
9
9
|
|
|
10
|
-
from ._types import AnyInterface, Interface, Provider, Scope
|
|
10
|
+
from ._types import AnyInterface, Interface, Provider, Scope, is_event_type
|
|
11
11
|
from ._utils import run_async
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
@@ -254,9 +254,10 @@ class ResourceScopedContext(ScopedContext):
|
|
|
254
254
|
self.close()
|
|
255
255
|
return
|
|
256
256
|
|
|
257
|
+
@abc.abstractmethod
|
|
257
258
|
def start(self) -> None:
|
|
258
259
|
"""Start the scoped context."""
|
|
259
|
-
for interface in self.container.
|
|
260
|
+
for interface in self.container._resource_cache.get(self.scope, []): # noqa
|
|
260
261
|
self.container.resolve(interface)
|
|
261
262
|
|
|
262
263
|
def close(self) -> None:
|
|
@@ -288,10 +289,9 @@ class ResourceScopedContext(ScopedContext):
|
|
|
288
289
|
await self.aclose()
|
|
289
290
|
return
|
|
290
291
|
|
|
292
|
+
@abc.abstractmethod
|
|
291
293
|
async def astart(self) -> None:
|
|
292
294
|
"""Start the scoped context asynchronously."""
|
|
293
|
-
for interface in self.container._providers_cache.get(self.scope, []): # noqa
|
|
294
|
-
await self.container.aresolve(interface)
|
|
295
295
|
|
|
296
296
|
async def aclose(self) -> None:
|
|
297
297
|
"""Close the scoped context asynchronously."""
|
|
@@ -305,6 +305,16 @@ class SingletonContext(ResourceScopedContext):
|
|
|
305
305
|
|
|
306
306
|
scope = "singleton"
|
|
307
307
|
|
|
308
|
+
def start(self) -> None:
|
|
309
|
+
"""Start the scoped context."""
|
|
310
|
+
for interface in self.container._resource_cache.get(self.scope, []): # noqa
|
|
311
|
+
self.container.resolve(interface)
|
|
312
|
+
|
|
313
|
+
async def astart(self) -> None:
|
|
314
|
+
"""Start the scoped context asynchronously."""
|
|
315
|
+
for interface in self.container._resource_cache.get(self.scope, []): # noqa
|
|
316
|
+
await self.container.aresolve(interface)
|
|
317
|
+
|
|
308
318
|
|
|
309
319
|
@final
|
|
310
320
|
class RequestContext(ResourceScopedContext):
|
|
@@ -312,6 +322,20 @@ class RequestContext(ResourceScopedContext):
|
|
|
312
322
|
|
|
313
323
|
scope = "request"
|
|
314
324
|
|
|
325
|
+
def start(self) -> None:
|
|
326
|
+
"""Start the scoped context."""
|
|
327
|
+
for interface in self.container._resource_cache.get(self.scope, []): # noqa
|
|
328
|
+
if not is_event_type(interface):
|
|
329
|
+
continue
|
|
330
|
+
self.container.resolve(interface)
|
|
331
|
+
|
|
332
|
+
async def astart(self) -> None:
|
|
333
|
+
"""Start the scoped context asynchronously."""
|
|
334
|
+
for interface in self.container._resource_cache.get(self.scope, []): # noqa
|
|
335
|
+
if not is_event_type(interface):
|
|
336
|
+
continue
|
|
337
|
+
await self.container.aresolve(interface)
|
|
338
|
+
|
|
315
339
|
|
|
316
340
|
@final
|
|
317
341
|
class TransientContext(ScopedContext):
|
anydi/_types.py
CHANGED
|
@@ -30,6 +30,17 @@ def is_marker(obj: Any) -> bool:
|
|
|
30
30
|
return isinstance(obj, Marker)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
class Event:
|
|
34
|
+
"""Represents an event object."""
|
|
35
|
+
|
|
36
|
+
__slots__ = ()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def is_event_type(cls: Any) -> bool:
|
|
40
|
+
"""Checks if an object is an event type."""
|
|
41
|
+
return issubclass(cls, Event)
|
|
42
|
+
|
|
43
|
+
|
|
33
44
|
@dataclass(frozen=True)
|
|
34
45
|
class Provider:
|
|
35
46
|
"""Represents a provider object.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
anydi/__init__.py,sha256=aeaBp5vq09sG-e9sqqs9qpUtUIDNfOdFPrlAfE5Ku9E,584
|
|
2
|
-
anydi/_container.py,sha256=
|
|
3
|
-
anydi/_context.py,sha256=
|
|
2
|
+
anydi/_container.py,sha256=OjzwZPiQuf9ouyhmIqlNht99pHa77hjZ0sM_n_GovW0,28947
|
|
3
|
+
anydi/_context.py,sha256=AVml53KyrQL4yyoJZkU2pbNzQwtg-1Jyt7m6R_0l6_8,11740
|
|
4
4
|
anydi/_logger.py,sha256=UpubJUnW83kffFxkhUlObm2DmZX1Pjqoz9YFKS-JOPg,52
|
|
5
5
|
anydi/_module.py,sha256=E1TfLud_Af-MPB83PxIzHVA1jlDW2FGaRP_il1a6y3Y,3675
|
|
6
6
|
anydi/_scanner.py,sha256=cyEk-K2Q8ssZStq8GrxMeEcCuAZMw-RXrjlgWEevKCs,6667
|
|
7
|
-
anydi/_types.py,sha256=
|
|
7
|
+
anydi/_types.py,sha256=YGfHVyysu2qNSXaZnvl_1BwPzKub84o3e3F4rK0tGQw,3628
|
|
8
8
|
anydi/_utils.py,sha256=zP4UvO1aVQJTB8pFNUWAcncvSiuhcg4xNdRU7CoLrqw,3871
|
|
9
9
|
anydi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
anydi/ext/_utils.py,sha256=2kxLPTMM9Ro3s6-knbqYzONlqRB3hMcwZFFRQGHcFUg,2691
|
|
@@ -23,8 +23,8 @@ anydi/ext/pytest_plugin.py,sha256=pFLcfxGtJfGSqtk7sPrrHFSKOaZoKZTWt5X8CT0ydmA,42
|
|
|
23
23
|
anydi/ext/starlette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
anydi/ext/starlette/middleware.py,sha256=Ni0BQaPjs_Ha6zcLZYYJ3-XkslTCnL9aCSa06rnRDMI,1139
|
|
25
25
|
anydi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
-
anydi-0.27.
|
|
27
|
-
anydi-0.27.
|
|
28
|
-
anydi-0.27.
|
|
29
|
-
anydi-0.27.
|
|
30
|
-
anydi-0.27.
|
|
26
|
+
anydi-0.27.0a6.dist-info/LICENSE,sha256=V6rU8a8fv6o2jQ-7ODHs0XfDFimot8Q6Km6CylRIDTo,1069
|
|
27
|
+
anydi-0.27.0a6.dist-info/METADATA,sha256=G95uZ9BoMP2BLlYVARh_BWIoArTZEeuEz-eJUBi9d5g,5163
|
|
28
|
+
anydi-0.27.0a6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
29
|
+
anydi-0.27.0a6.dist-info/entry_points.txt,sha256=GmQblwzxFg42zva1HyBYJJ7TvrTIcSAGBHmyi3bvsi4,42
|
|
30
|
+
anydi-0.27.0a6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|