anydi 0.70.0__py3-none-any.whl → 0.70.1__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 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 get_alias_list, is_provided
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 NOT_SET, Event, Scope, is_event_type, is_iterator_type, is_none_type
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")
@@ -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
- return self._register_provider(
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(NOT_SET, call, scope, False, override, None)
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
- for alias_type in get_alias_list(dependency_type.__provided__):
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
- for alias_type in get_alias_list(dependency_type.__provided__):
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
- for alias_type in get_alias_list(
1017
- param_dependency_type.__provided__
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
- target.__provider__ = ProviderMetadata(scope=scope, override=override) # type: ignore
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/_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, get_alias_list, is_injectable, is_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 get_alias_list(cls.__provided__):
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anydi
3
- Version: 0.70.0
3
+ Version: 0.70.1
4
4
  Summary: Dependency Injection library
5
5
  Keywords: dependency injection,dependencies,di,async,asyncio,application
6
6
  Author: Anton Ruhlov
@@ -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=6dqMUlqvBEI0bghytOSqHK74EN9tfiEoQbJdNPbjLeE,48660
4
+ anydi/_container.py,sha256=7c96X4hrN9-OZglUedvdKjoKcYJKFMy7IeTAHF9dOUs,49203
5
5
  anydi/_context.py,sha256=ZQWxtBXWkrMsCk_L7K_A7-e09v5Mv9HApPH3LZ6ZF9k,3648
6
- anydi/_decorators.py,sha256=04M1xN7oHVskAnoEJdvJr3hXrrzruUp4mzlLOCuuZv0,5598
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
11
  anydi/_provider.py,sha256=5pMXyiGwBo2j6OHaoOktLQfiX2rkCf5aYXFlFi65JlQ,2898
12
12
  anydi/_resolver.py,sha256=xpBgFhUTMdHeNjqmUfOZMU5J8PviVkc5q_ckgwrdAhs,33603
13
- anydi/_scanner.py,sha256=bCd1mBYXYBANBVoVEf2gHyw3Mr1DbTX5kV1b80-RljM,5898
14
- anydi/_types.py,sha256=lsShY_-_CM2EFajeknAYXvLl-rHfopBT8udnK5_BtS4,1161
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.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
27
- anydi-0.70.0.dist-info/entry_points.txt,sha256=oDl_yEX12KlWcDzsZBTg85GG1Jl1rpiYOG4C7EJvebs,87
28
- anydi-0.70.0.dist-info/METADATA,sha256=w2CzRSLiozxgqMa3gaGhpR1LdcAyGA7yVsJrCruZeEI,8061
29
- anydi-0.70.0.dist-info/RECORD,,
26
+ anydi-0.70.1.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
27
+ anydi-0.70.1.dist-info/entry_points.txt,sha256=oDl_yEX12KlWcDzsZBTg85GG1Jl1rpiYOG4C7EJvebs,87
28
+ anydi-0.70.1.dist-info/METADATA,sha256=fSe7AsDMguaUHD6hCEELMRKVFx7Ge5B7gQjs3t5jbUA,8061
29
+ anydi-0.70.1.dist-info/RECORD,,
File without changes