anydi 0.70.0__py3-none-any.whl → 0.70.2__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 +38 -15
- anydi/_decorators.py +6 -12
- anydi/_provider.py +1 -0
- anydi/_scanner.py +3 -2
- anydi/_types.py +9 -0
- {anydi-0.70.0.dist-info → anydi-0.70.2.dist-info}/METADATA +1 -1
- {anydi-0.70.0.dist-info → anydi-0.70.2.dist-info}/RECORD +9 -9
- {anydi-0.70.0.dist-info → anydi-0.70.2.dist-info}/WHEEL +0 -0
- {anydi-0.70.0.dist-info → anydi-0.70.2.dist-info}/entry_points.txt +0 -0
anydi/_container.py
CHANGED
|
@@ -17,7 +17,7 @@ from typing import Any, Literal, TypeVar, get_args, get_origin, overload
|
|
|
17
17
|
from typing_extensions import ParamSpec, Self, type_repr
|
|
18
18
|
|
|
19
19
|
from ._context import InstanceContext
|
|
20
|
-
from ._decorators import
|
|
20
|
+
from ._decorators import is_provided
|
|
21
21
|
from ._graph import Graph
|
|
22
22
|
from ._injector import Injector
|
|
23
23
|
from ._marker import Marker
|
|
@@ -25,7 +25,15 @@ from ._module import ModuleDef, ModuleRegistrar
|
|
|
25
25
|
from ._provider import Provider, ProviderDef, ProviderKind, ProviderParameter
|
|
26
26
|
from ._resolver import Resolver
|
|
27
27
|
from ._scanner import PackageOrIterable, Scanner
|
|
28
|
-
from ._types import
|
|
28
|
+
from ._types import (
|
|
29
|
+
NOT_SET,
|
|
30
|
+
Event,
|
|
31
|
+
Scope,
|
|
32
|
+
is_event_type,
|
|
33
|
+
is_iterator_type,
|
|
34
|
+
is_none_type,
|
|
35
|
+
to_list,
|
|
36
|
+
)
|
|
29
37
|
|
|
30
38
|
T = TypeVar("T", bound=Any)
|
|
31
39
|
P = ParamSpec("P")
|
|
@@ -75,13 +83,13 @@ class Container:
|
|
|
75
83
|
# Register providers
|
|
76
84
|
providers = providers or []
|
|
77
85
|
for provider in providers:
|
|
78
|
-
self.
|
|
86
|
+
self.register(
|
|
79
87
|
provider.dependency_type,
|
|
80
88
|
provider.factory,
|
|
81
|
-
provider.scope,
|
|
82
|
-
provider.from_context,
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
scope=provider.scope,
|
|
90
|
+
from_context=provider.from_context,
|
|
91
|
+
alias=provider.alias,
|
|
92
|
+
override=False,
|
|
85
93
|
)
|
|
86
94
|
|
|
87
95
|
# Register modules
|
|
@@ -345,6 +353,7 @@ class Container:
|
|
|
345
353
|
scope: Scope = "singleton",
|
|
346
354
|
from_context: bool = False,
|
|
347
355
|
override: bool = False,
|
|
356
|
+
alias: Any = NOT_SET,
|
|
348
357
|
interface: Any = NOT_SET,
|
|
349
358
|
call: Callable[..., Any] = NOT_SET,
|
|
350
359
|
) -> Provider:
|
|
@@ -372,10 +381,16 @@ class Container:
|
|
|
372
381
|
dependency_type = interface
|
|
373
382
|
if factory is NOT_SET:
|
|
374
383
|
factory = call if call is not NOT_SET else dependency_type
|
|
375
|
-
|
|
384
|
+
provider = self._register_provider(
|
|
376
385
|
dependency_type, factory, scope, from_context, override, None
|
|
377
386
|
)
|
|
378
387
|
|
|
388
|
+
# Register aliases if specified
|
|
389
|
+
for alias_type in to_list(alias):
|
|
390
|
+
self.alias(alias_type, provider.dependency_type)
|
|
391
|
+
|
|
392
|
+
return provider
|
|
393
|
+
|
|
379
394
|
def alias(self, alias_type: Any, canonical_type: Any, /) -> None:
|
|
380
395
|
"""Register an alias for a dependency type."""
|
|
381
396
|
if self.ready:
|
|
@@ -427,12 +442,19 @@ class Container:
|
|
|
427
442
|
self._delete_provider(provider)
|
|
428
443
|
|
|
429
444
|
def provider(
|
|
430
|
-
self, *, scope: Scope, override: bool = False
|
|
445
|
+
self, *, scope: Scope, override: bool = False, alias: Any = NOT_SET
|
|
431
446
|
) -> Callable[[Callable[P, T]], Callable[P, T]]:
|
|
432
447
|
"""Decorator to register a provider function with the specified scope."""
|
|
433
448
|
|
|
434
449
|
def decorator(call: Callable[P, T]) -> Callable[P, T]:
|
|
435
|
-
self._register_provider(
|
|
450
|
+
provider = self._register_provider(
|
|
451
|
+
NOT_SET, call, scope, False, override, None
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
# Register aliases if specified
|
|
455
|
+
for alias_type in to_list(alias):
|
|
456
|
+
self.alias(alias_type, provider.dependency_type)
|
|
457
|
+
|
|
436
458
|
return call
|
|
437
459
|
|
|
438
460
|
return decorator
|
|
@@ -627,7 +649,8 @@ class Container:
|
|
|
627
649
|
)
|
|
628
650
|
# Register aliases if specified
|
|
629
651
|
if not self.ready:
|
|
630
|
-
|
|
652
|
+
aliases = to_list(dependency_type.__provided__.get("alias"))
|
|
653
|
+
for alias_type in aliases:
|
|
631
654
|
self.alias(alias_type, dependency_type)
|
|
632
655
|
registered = True
|
|
633
656
|
else:
|
|
@@ -710,7 +733,8 @@ class Container:
|
|
|
710
733
|
None,
|
|
711
734
|
)
|
|
712
735
|
# Register aliases if specified
|
|
713
|
-
|
|
736
|
+
aliases = to_list(dependency_type.__provided__.get("alias"))
|
|
737
|
+
for alias_type in aliases:
|
|
714
738
|
self._aliases[alias_type] = dependency_type
|
|
715
739
|
# Recursively ensure the @provided class is resolved
|
|
716
740
|
dep_provider = self._ensure_provider_resolved(
|
|
@@ -1013,9 +1037,8 @@ class Container:
|
|
|
1013
1037
|
None,
|
|
1014
1038
|
)
|
|
1015
1039
|
# Register aliases if specified
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
):
|
|
1040
|
+
provided_meta = param_dependency_type.__provided__
|
|
1041
|
+
for alias_type in to_list(provided_meta.get("alias")):
|
|
1019
1042
|
self._aliases[alias_type] = param_dependency_type
|
|
1020
1043
|
elif param.has_default:
|
|
1021
1044
|
# Has default, can be missing
|
anydi/_decorators.py
CHANGED
|
@@ -34,16 +34,6 @@ class ProvidedMetadata(TypedDict):
|
|
|
34
34
|
from_context: NotRequired[bool]
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
def get_alias_list(provided: ProvidedMetadata) -> list[Any]:
|
|
38
|
-
"""Get alias list from __provided__ metadata, normalizing single to list."""
|
|
39
|
-
alias = provided.get("alias")
|
|
40
|
-
if alias is None:
|
|
41
|
-
return []
|
|
42
|
-
if isinstance(alias, list | tuple):
|
|
43
|
-
return list(alias) # type: ignore
|
|
44
|
-
return [alias]
|
|
45
|
-
|
|
46
|
-
|
|
47
37
|
def provided(
|
|
48
38
|
*, scope: Scope, alias: Any = NOT_SET, from_context: bool = False
|
|
49
39
|
) -> Callable[[ClassT], ClassT]:
|
|
@@ -162,10 +152,11 @@ def is_provided(cls: Any) -> TypeGuard[type[Provided]]:
|
|
|
162
152
|
class ProviderMetadata(TypedDict):
|
|
163
153
|
scope: Scope
|
|
164
154
|
override: bool
|
|
155
|
+
alias: NotRequired[Any]
|
|
165
156
|
|
|
166
157
|
|
|
167
158
|
def provider(
|
|
168
|
-
*, scope: Scope, override: bool = False
|
|
159
|
+
*, scope: Scope, override: bool = False, alias: Any = NOT_SET
|
|
169
160
|
) -> Callable[
|
|
170
161
|
[Callable[Concatenate[ModuleT, P], T]], Callable[Concatenate[ModuleT, P], T]
|
|
171
162
|
]:
|
|
@@ -174,7 +165,10 @@ def provider(
|
|
|
174
165
|
def decorator(
|
|
175
166
|
target: Callable[Concatenate[ModuleT, P], T],
|
|
176
167
|
) -> Callable[Concatenate[ModuleT, P], T]:
|
|
177
|
-
|
|
168
|
+
metadata: ProviderMetadata = {"scope": scope, "override": override}
|
|
169
|
+
if alias is not NOT_SET:
|
|
170
|
+
metadata["alias"] = alias
|
|
171
|
+
target.__provider__ = metadata # type: ignore
|
|
178
172
|
return target
|
|
179
173
|
|
|
180
174
|
return decorator
|
anydi/_provider.py
CHANGED
anydi/_scanner.py
CHANGED
|
@@ -8,7 +8,8 @@ from dataclasses import dataclass
|
|
|
8
8
|
from types import ModuleType
|
|
9
9
|
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
|
-
from ._decorators import Provided,
|
|
11
|
+
from ._decorators import Provided, is_injectable, is_provided
|
|
12
|
+
from ._types import to_list
|
|
12
13
|
|
|
13
14
|
if TYPE_CHECKING:
|
|
14
15
|
from ._container import Container
|
|
@@ -65,7 +66,7 @@ class Scanner:
|
|
|
65
66
|
cls, cls, scope=scope, from_context=from_context
|
|
66
67
|
)
|
|
67
68
|
# Create aliases if specified (alias → cls)
|
|
68
|
-
for alias_type in
|
|
69
|
+
for alias_type in to_list(cls.__provided__.get("alias")):
|
|
69
70
|
self._container.alias(alias_type, cls)
|
|
70
71
|
|
|
71
72
|
# Second: inject @injectable functions
|
anydi/_types.py
CHANGED
|
@@ -43,3 +43,12 @@ def is_none_type(tp: Any) -> bool:
|
|
|
43
43
|
def is_iterator_type(tp: Any) -> bool:
|
|
44
44
|
"""Check if the given object is an iterator type."""
|
|
45
45
|
return tp in (Iterator, AsyncIterator)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def to_list(value: Any) -> list[Any]:
|
|
49
|
+
"""Convert a value to a list, handling None and sequences."""
|
|
50
|
+
if value is None or value is NOT_SET:
|
|
51
|
+
return []
|
|
52
|
+
if isinstance(value, list | tuple):
|
|
53
|
+
return list(value) # type: ignore[arg-type]
|
|
54
|
+
return [value]
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
anydi/__init__.py,sha256=KFX8OthKXwBuYDPCV61t-044DpJ88tAOzIxeUWRC5OA,633
|
|
2
2
|
anydi/_async_lock.py,sha256=3dwZr0KthXFYha0XKMyXf8jMmGb1lYoNC0O5w29V9ic,1104
|
|
3
3
|
anydi/_cli.py,sha256=0BhNvWPyuIGzUkDELIBm_nsEMWk7MtLi3oTvgXj5oko,2072
|
|
4
|
-
anydi/_container.py,sha256=
|
|
4
|
+
anydi/_container.py,sha256=0Mhper1g4O4cmAaGOeXAkcfMeJhoJqcYTowhNKPQhhs,49237
|
|
5
5
|
anydi/_context.py,sha256=ZQWxtBXWkrMsCk_L7K_A7-e09v5Mv9HApPH3LZ6ZF9k,3648
|
|
6
|
-
anydi/_decorators.py,sha256=
|
|
6
|
+
anydi/_decorators.py,sha256=27AQBzp_P_ajO_bRk1ybgwuxTy9PMWGMJmfBvjriJ-8,5435
|
|
7
7
|
anydi/_graph.py,sha256=WN_N1nNNPp74YU1mqxM-dJlf0rWF9ooGNTIv87DJpKI,8619
|
|
8
8
|
anydi/_injector.py,sha256=RvnPEYOgkg-WOIW1ItvVsoAZaSC9wmCnWQrfXad_86A,4507
|
|
9
9
|
anydi/_marker.py,sha256=yXSPbIVU-X-jMSawtCHWFMKke5VpWMiBRZlEH8PlUqE,3373
|
|
10
10
|
anydi/_module.py,sha256=2kN5uEXLd2Dsc58gz5IWK43wJewr_QgIVGSO3iWp798,2609
|
|
11
|
-
anydi/_provider.py,sha256=
|
|
11
|
+
anydi/_provider.py,sha256=1hUah9xmAVEVfE1AOFraodJiyfgRhO05egWq1aeRZCA,2923
|
|
12
12
|
anydi/_resolver.py,sha256=xpBgFhUTMdHeNjqmUfOZMU5J8PviVkc5q_ckgwrdAhs,33603
|
|
13
|
-
anydi/_scanner.py,sha256=
|
|
14
|
-
anydi/_types.py,sha256=
|
|
13
|
+
anydi/_scanner.py,sha256=gLs6Gdv12VVgT-J1vfCVOQ515drGtZQ4QNI8Bs0fqE0,5916
|
|
14
|
+
anydi/_types.py,sha256=QQY_WG6-e2VuqH2AqrStiM1bg2ACQMHaPtdOQVsDimU,1439
|
|
15
15
|
anydi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
anydi/ext/django/__init__.py,sha256=Ve8lncLU9dPY_Vjt4zihPgsSxwAtFHACn0XvBM5JG8k,367
|
|
17
17
|
anydi/ext/fastapi.py,sha256=NowHc-z_Sw069YDv9vP98Mehum5vHsIIcqvDkRmicmc,2964
|
|
@@ -23,7 +23,7 @@ anydi/ext/starlette/middleware.py,sha256=n_JJ7BcG2Mg2M5HwM_SBboxZ-mnnD6WWJn4khq7
|
|
|
23
23
|
anydi/ext/typer.py,sha256=c7HapXQfKhnLJQcHNncJAGd8jZ3crX5it6-MRCJjyPM,6268
|
|
24
24
|
anydi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
anydi/testing.py,sha256=cHg3mMScZbEep9smRqSNQ81BZMQOkyugHe8TvKdPnEg,1347
|
|
26
|
-
anydi-0.70.
|
|
27
|
-
anydi-0.70.
|
|
28
|
-
anydi-0.70.
|
|
29
|
-
anydi-0.70.
|
|
26
|
+
anydi-0.70.2.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
27
|
+
anydi-0.70.2.dist-info/entry_points.txt,sha256=oDl_yEX12KlWcDzsZBTg85GG1Jl1rpiYOG4C7EJvebs,87
|
|
28
|
+
anydi-0.70.2.dist-info/METADATA,sha256=kDJCV_O9IcrhLR-X4gWYTHM0h5AvO8H_q53p9VBe1Ew,8061
|
|
29
|
+
anydi-0.70.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|