anydi 0.24.2__tar.gz → 0.24.3__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: anydi
3
- Version: 0.24.2
3
+ Version: 0.24.3
4
4
  Summary: Dependency Injection library
5
5
  Home-page: https://github.com/antonrh/anydi
6
6
  License: MIT
@@ -43,7 +43,12 @@ from ._logger import logger
43
43
  from ._module import Module, ModuleRegistry
44
44
  from ._scanner import Scanner
45
45
  from ._types import AnyInterface, Interface, Provider, Scope, is_marker
46
- from ._utils import get_full_qualname, get_signature, is_builtin_type
46
+ from ._utils import (
47
+ get_full_qualname,
48
+ get_typed_parameters,
49
+ get_typed_return_annotation,
50
+ is_builtin_type,
51
+ )
47
52
 
48
53
  T = TypeVar("T", bound=Any)
49
54
  P = ParamSpec("P")
@@ -327,7 +332,7 @@ class Container:
327
332
  """
328
333
  related_providers = []
329
334
 
330
- for parameter in provider.parameters.values():
335
+ for parameter in provider.parameters:
331
336
  if parameter.annotation is inspect._empty: # noqa
332
337
  raise TypeError(
333
338
  f"Missing provider `{provider}` "
@@ -366,7 +371,7 @@ class Container:
366
371
  The auto scope, or None if the auto scope cannot be detected.
367
372
  """
368
373
  has_transient, has_request, has_singleton = False, False, False
369
- for parameter in get_signature(obj).parameters.values():
374
+ for parameter in get_typed_parameters(obj):
370
375
  sub_provider = self._get_or_register_provider(parameter.annotation)
371
376
  if not has_transient and sub_provider.scope == "transient":
372
377
  has_transient = True
@@ -711,9 +716,9 @@ class Container:
711
716
  Raises:
712
717
  TypeError: If the provider return annotation is missing or invalid.
713
718
  """
714
- annotation = get_signature(obj).return_annotation
719
+ annotation = get_typed_return_annotation(obj)
715
720
 
716
- if annotation is inspect._empty: # noqa
721
+ if annotation is None:
717
722
  raise TypeError(
718
723
  f"Missing `{get_full_qualname(obj)}` provider return annotation."
719
724
  )
@@ -741,7 +746,7 @@ class Container:
741
746
  of the injected parameters.
742
747
  """
743
748
  injected_params = {}
744
- for parameter in get_signature(obj).parameters.values():
749
+ for parameter in get_typed_parameters(obj):
745
750
  if not is_marker(parameter.default):
746
751
  continue
747
752
  try:
@@ -97,7 +97,7 @@ class ScopedContext(abc.ABC):
97
97
  The arguments for the provider.
98
98
  """
99
99
  args, kwargs = [], {}
100
- for parameter in provider.parameters.values():
100
+ for parameter in provider.parameters:
101
101
  instance = self.container.resolve(parameter.annotation)
102
102
  if parameter.kind == parameter.POSITIONAL_ONLY:
103
103
  args.append(instance)
@@ -117,7 +117,7 @@ class ScopedContext(abc.ABC):
117
117
  The arguments for the provider.
118
118
  """
119
119
  args, kwargs = [], {}
120
- for parameter in provider.parameters.values():
120
+ for parameter in provider.parameters:
121
121
  instance = await self.container.aresolve(parameter.annotation)
122
122
  if parameter.kind == parameter.POSITIONAL_ONLY:
123
123
  args.append(instance)
@@ -20,7 +20,7 @@ from typing import (
20
20
  from typing_extensions import NamedTuple, ParamSpec
21
21
 
22
22
  from ._types import is_marker
23
- from ._utils import get_signature
23
+ from ._utils import get_typed_parameters
24
24
 
25
25
  if TYPE_CHECKING:
26
26
  from ._container import Container
@@ -157,10 +157,10 @@ class Scanner:
157
157
 
158
158
  # Get by Marker
159
159
  if inspect.isclass(member):
160
- signature = get_signature(member.__init__)
160
+ parameters = get_typed_parameters(member.__init__)
161
161
  else:
162
- signature = get_signature(member)
163
- for parameter in signature.parameters.values():
162
+ parameters = get_typed_parameters(member)
163
+ for parameter in parameters:
164
164
  if is_marker(parameter.default):
165
165
  dependencies.append(
166
166
  self._create_dependency(member=member, module=module)
@@ -1,11 +1,13 @@
1
+ from __future__ import annotations
2
+
1
3
  import inspect
2
4
  from dataclasses import dataclass
3
5
  from functools import cached_property
4
- from typing import Any, Callable, Mapping, Type, TypeVar, Union
6
+ from typing import Any, Callable, Type, TypeVar, Union
5
7
 
6
8
  from typing_extensions import Annotated, Literal, Self, TypeAlias
7
9
 
8
- from ._utils import get_full_qualname, get_signature
10
+ from ._utils import get_full_qualname, get_typed_parameters
9
11
 
10
12
  Scope = Literal["transient", "singleton", "request"]
11
13
 
@@ -58,13 +60,13 @@ class Provider:
58
60
  return get_full_qualname(self.obj)
59
61
 
60
62
  @cached_property
61
- def parameters(self) -> Mapping[str, inspect.Parameter]:
63
+ def parameters(self) -> list[inspect.Parameter]:
62
64
  """Returns the parameters of the provider as a mapping.
63
65
 
64
66
  Returns:
65
67
  The parameters of the provider.
66
68
  """
67
- return get_signature(self.obj).parameters
69
+ return get_typed_parameters(self.obj)
68
70
 
69
71
  @cached_property
70
72
  def is_class(self) -> bool:
@@ -0,0 +1,111 @@
1
+ """Shared AnyDI utils module."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import builtins
6
+ import functools
7
+ import inspect
8
+ import sys
9
+ from typing import Any, Callable, ForwardRef, TypeVar, cast
10
+
11
+ from typing_extensions import Annotated, ParamSpec, get_origin
12
+
13
+ try:
14
+ import anyio # noqa
15
+ except ImportError:
16
+ anyio = None # type: ignore[assignment]
17
+
18
+
19
+ if sys.version_info < (3, 9): # pragma: nocover
20
+
21
+ def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
22
+ return type_._evaluate(globalns, localns) # noqa
23
+
24
+ else:
25
+
26
+ def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
27
+ return cast(Any, type_)._evaluate(globalns, localns, set()) # noqa
28
+
29
+
30
+ T = TypeVar("T")
31
+ P = ParamSpec("P")
32
+
33
+
34
+ def get_full_qualname(obj: Any) -> str:
35
+ """Get the fully qualified name of an object."""
36
+ origin = get_origin(obj)
37
+ if origin is Annotated:
38
+ metadata = ", ".join(
39
+ [
40
+ f'"{arg}"' if isinstance(arg, str) else str(arg)
41
+ for arg in obj.__metadata__
42
+ ]
43
+ )
44
+ return f"Annotated[{get_full_qualname(obj.__args__[0])}, {metadata}]]"
45
+
46
+ qualname = getattr(obj, "__qualname__", None)
47
+ module_name = getattr(obj, "__module__", None)
48
+ if qualname is None:
49
+ qualname = type(obj).__qualname__
50
+
51
+ if module_name is None:
52
+ module_name = type(obj).__module__
53
+
54
+ if module_name == builtins.__name__:
55
+ return qualname
56
+ return f"{module_name}.{qualname}"
57
+
58
+
59
+ def is_builtin_type(tp: type[Any]) -> bool:
60
+ """Check if the given type is a built-in type."""
61
+ return tp.__module__ == builtins.__name__
62
+
63
+
64
+ def make_forwardref(annotation: str, globalns: dict[str, Any]) -> Any:
65
+ """Create a forward reference from a string annotation."""
66
+ forward_ref = ForwardRef(annotation)
67
+ return evaluate_forwardref(forward_ref, globalns, globalns)
68
+
69
+
70
+ def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any:
71
+ """Get the typed annotation of a parameter."""
72
+ if isinstance(annotation, str):
73
+ annotation = ForwardRef(annotation)
74
+ annotation = evaluate_forwardref(annotation, globalns, globalns)
75
+ return annotation
76
+
77
+
78
+ def get_typed_return_annotation(obj: Callable[..., Any]) -> Any:
79
+ """Get the typed return annotation of a callable object."""
80
+ signature = inspect.signature(obj)
81
+ annotation = signature.return_annotation
82
+ if annotation is inspect.Signature.empty:
83
+ return None
84
+ globalns = getattr(obj, "__globals__", {})
85
+ return get_typed_annotation(annotation, globalns)
86
+
87
+
88
+ def get_typed_parameters(obj: Callable[..., Any]) -> list[inspect.Parameter]:
89
+ """Get the typed parameters of a callable object."""
90
+ globalns = getattr(obj, "__globals__", {})
91
+ return [
92
+ parameter.replace(
93
+ annotation=get_typed_annotation(parameter.annotation, globalns)
94
+ )
95
+ for name, parameter in inspect.signature(obj).parameters.items()
96
+ ]
97
+
98
+
99
+ async def run_async(
100
+ func: Callable[P, T],
101
+ /,
102
+ *args: P.args,
103
+ **kwargs: P.kwargs,
104
+ ) -> T:
105
+ """Runs the given function asynchronously using the `anyio` library."""
106
+ if not anyio:
107
+ raise ImportError(
108
+ "`anyio` library is not currently installed. Please make sure to install "
109
+ "it first, or consider using `anydi[full]` instead."
110
+ )
111
+ return await anyio.to_thread.run_sync(functools.partial(func, *args, **kwargs))
@@ -13,7 +13,7 @@ from starlette.requests import Request
13
13
  from typing_extensions import Annotated, get_args, get_origin
14
14
 
15
15
  from anydi import Container
16
- from anydi._utils import get_full_qualname, get_signature
16
+ from anydi._utils import get_full_qualname, get_typed_parameters
17
17
 
18
18
  from .starlette.middleware import RequestScopedMiddleware
19
19
 
@@ -47,7 +47,7 @@ def install(app: FastAPI, container: Container) -> None:
47
47
  call, *params = dependant.cache_key
48
48
  if not call:
49
49
  continue # pragma: no cover
50
- for parameter in get_signature(call).parameters.values():
50
+ for parameter in get_typed_parameters(call):
51
51
  _patch_route_parameter(call, parameter, container)
52
52
 
53
53
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "anydi"
3
- version = "0.24.2"
3
+ version = "0.24.3"
4
4
  description = "Dependency Injection library"
5
5
  authors = ["Anton Ruhlov <antonruhlov@gmail.com>"]
6
6
  license = "MIT"
@@ -1,113 +0,0 @@
1
- """Shared AnyDI utils module."""
2
-
3
- from __future__ import annotations
4
-
5
- import builtins
6
- import functools
7
- import inspect
8
- import sys
9
- from typing import Any, Callable, TypeVar
10
-
11
- from typing_extensions import Annotated, ParamSpec, get_origin
12
-
13
- try:
14
- import anyio # noqa
15
- except ImportError:
16
- anyio = None # type: ignore[assignment]
17
-
18
-
19
- T = TypeVar("T")
20
- P = ParamSpec("P")
21
-
22
-
23
- def get_full_qualname(obj: Any) -> str:
24
- """Get the fully qualified name of an object.
25
-
26
- This function returns the fully qualified name of the given object,
27
- which includes both the module name and the object's qualname.
28
-
29
- Args:
30
- obj: The object for which to retrieve the fully qualified name.
31
-
32
- Returns:
33
- The fully qualified name of the object.
34
- """
35
- origin = get_origin(obj)
36
- if origin is Annotated:
37
- metadata = ", ".join(
38
- [
39
- f'"{arg}"' if isinstance(arg, str) else str(arg)
40
- for arg in obj.__metadata__
41
- ]
42
- )
43
- return f"Annotated[{get_full_qualname(obj.__args__[0])}, {metadata}]]"
44
-
45
- qualname = getattr(obj, "__qualname__", None)
46
- module_name = getattr(obj, "__module__", None)
47
- if qualname is None:
48
- qualname = type(obj).__qualname__
49
-
50
- if module_name is None:
51
- module_name = type(obj).__module__
52
-
53
- if module_name == builtins.__name__:
54
- return qualname
55
- return f"{module_name}.{qualname}"
56
-
57
-
58
- def is_builtin_type(tp: type[Any]) -> bool:
59
- """
60
- Check if the given type is a built-in type.
61
- Args:
62
- tp (type): The type to check.
63
- Returns:
64
- bool: True if the type is a built-in type, False otherwise.
65
- """
66
- return tp.__module__ == builtins.__name__
67
-
68
-
69
- @functools.lru_cache(maxsize=None)
70
- def get_signature(obj: Callable[..., Any]) -> inspect.Signature:
71
- """Get the signature of a callable object.
72
-
73
- This function uses the `inspect.signature` function to retrieve the signature
74
- of the given callable object. It applies an LRU cache decorator to improve
75
- performance by caching the signatures of previously inspected objects.
76
-
77
- Args:
78
- obj: The callable object to inspect.
79
-
80
- Returns:
81
- The signature of the callable object.
82
- """
83
- signature_kwargs: dict[str, Any] = {}
84
- if sys.version_info >= (3, 10):
85
- signature_kwargs["eval_str"] = True
86
- return inspect.signature(obj, **signature_kwargs)
87
-
88
-
89
- async def run_async(
90
- func: Callable[P, T],
91
- /,
92
- *args: P.args,
93
- **kwargs: P.kwargs,
94
- ) -> T:
95
- """Runs the given function asynchronously using the `anyio` library.
96
-
97
- Args:
98
- func: The function to run asynchronously.
99
- args: The positional arguments to pass to the function.
100
- kwargs: The keyword arguments to pass to the function.
101
-
102
- Returns:
103
- The result of the function.
104
-
105
- Raises:
106
- ImportError: If the `anyio` library is not installed.
107
- """
108
- if not anyio:
109
- raise ImportError(
110
- "`anyio` library is not currently installed. Please make sure to install "
111
- "it first, or consider using `anydi[full]` instead."
112
- )
113
- return await anyio.to_thread.run_sync(functools.partial(func, *args, **kwargs))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes