anydi 0.54.0__py3-none-any.whl → 0.55.0__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/_context.py CHANGED
@@ -5,10 +5,11 @@ import threading
5
5
  from types import TracebackType
6
6
  from typing import Any
7
7
 
8
+ import anyio.to_thread
8
9
  from typing_extensions import Self
9
10
 
10
- from ._async import AsyncRLock, run_sync
11
- from ._typing import NOT_SET
11
+ from ._async_lock import AsyncRLock
12
+ from ._types import NOT_SET
12
13
 
13
14
 
14
15
  class InstanceContext:
@@ -18,10 +19,10 @@ class InstanceContext:
18
19
 
19
20
  def __init__(self) -> None:
20
21
  self._instances: dict[Any, Any] = {}
21
- self._stack = contextlib.ExitStack()
22
- self._async_stack = contextlib.AsyncExitStack()
23
- self._lock = threading.RLock()
24
- self._async_lock = AsyncRLock()
22
+ self._stack: contextlib.ExitStack | None = None
23
+ self._async_stack: contextlib.AsyncExitStack | None = None
24
+ self._lock: threading.RLock | None = None
25
+ self._async_lock: AsyncRLock | None = None
25
26
 
26
27
  def get(self, interface: Any, default: Any = NOT_SET) -> Any:
27
28
  """Get an instance from the context."""
@@ -33,10 +34,14 @@ class InstanceContext:
33
34
 
34
35
  def enter(self, cm: contextlib.AbstractContextManager[Any]) -> Any:
35
36
  """Enter the context."""
37
+ if self._stack is None:
38
+ self._stack = contextlib.ExitStack()
36
39
  return self._stack.enter_context(cm)
37
40
 
38
41
  async def aenter(self, cm: contextlib.AbstractAsyncContextManager[Any]) -> Any:
39
42
  """Enter the context asynchronously."""
43
+ if self._async_stack is None:
44
+ self._async_stack = contextlib.AsyncExitStack()
40
45
  return await self._async_stack.enter_async_context(cm)
41
46
 
42
47
  def __setitem__(self, interface: Any, value: Any) -> None:
@@ -62,11 +67,14 @@ class InstanceContext:
62
67
  exc_tb: TracebackType | None,
63
68
  ) -> Any:
64
69
  """Exit the context."""
70
+ if self._stack is None:
71
+ return False
65
72
  return self._stack.__exit__(exc_type, exc_val, exc_tb)
66
73
 
67
74
  def close(self) -> None:
68
75
  """Close the scoped context."""
69
- self._stack.__exit__(None, None, None)
76
+ if self._stack is not None:
77
+ self._stack.__exit__(None, None, None)
70
78
 
71
79
  async def __aenter__(self) -> Self:
72
80
  """Enter the context asynchronously."""
@@ -79,8 +87,14 @@ class InstanceContext:
79
87
  exc_tb: TracebackType | None,
80
88
  ) -> bool:
81
89
  """Exit the context asynchronously."""
82
- sync_exit = await run_sync(self.__exit__, exc_type, exc_val, exc_tb)
83
- async_exit = await self._async_stack.__aexit__(exc_type, exc_val, exc_tb)
90
+ sync_exit = False
91
+ async_exit = False
92
+ if self._stack is not None:
93
+ sync_exit = await anyio.to_thread.run_sync(
94
+ self.__exit__, exc_type, exc_val, exc_tb
95
+ )
96
+ if self._async_stack is not None:
97
+ async_exit = await self._async_stack.__aexit__(exc_type, exc_val, exc_tb)
84
98
  return bool(sync_exit) or bool(async_exit)
85
99
 
86
100
  async def aclose(self) -> None:
@@ -89,8 +103,12 @@ class InstanceContext:
89
103
 
90
104
  def lock(self) -> threading.RLock:
91
105
  """Acquire the context lock."""
106
+ if self._lock is None:
107
+ self._lock = threading.RLock()
92
108
  return self._lock
93
109
 
94
110
  def alock(self) -> AsyncRLock:
95
111
  """Acquire the context lock asynchronously."""
112
+ if self._async_lock is None:
113
+ self._async_lock = AsyncRLock()
96
114
  return self._async_lock
anydi/_decorators.py CHANGED
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
15
15
  from ._module import Module
16
16
 
17
17
 
18
- from ._scope import Scope
18
+ from ._types import Scope
19
19
 
20
20
  T = TypeVar("T")
21
21
  P = ParamSpec("P")
anydi/_provider.py CHANGED
@@ -4,11 +4,9 @@ import enum
4
4
  import inspect
5
5
  from collections.abc import Callable
6
6
  from dataclasses import dataclass
7
- from functools import cached_property
8
7
  from typing import Any
9
8
 
10
- from ._scope import Scope
11
- from ._typing import NOT_SET
9
+ from ._types import NOT_SET, Scope
12
10
 
13
11
 
14
12
  class ProviderKind(enum.IntEnum):
@@ -34,59 +32,32 @@ class ProviderKind(enum.IntEnum):
34
32
  f"The provider `{call}` is invalid because it is not a callable object."
35
33
  )
36
34
 
37
- @classmethod
38
- def is_resource(cls, kind: ProviderKind) -> bool:
39
- return kind in (cls.GENERATOR, cls.ASYNC_GENERATOR)
40
-
41
35
 
42
- @dataclass(kw_only=True, frozen=True, slots=True)
36
+ @dataclass(frozen=True, slots=True)
43
37
  class ProviderParameter:
44
38
  name: str
45
39
  annotation: Any
46
40
  default: Any
47
41
  has_default: bool
48
42
  provider: Provider | None = None
49
- shared_scope: bool = False
50
43
 
51
44
 
52
- @dataclass(kw_only=True, frozen=True)
45
+ @dataclass(frozen=True, slots=True)
53
46
  class Provider:
54
47
  call: Callable[..., Any]
55
48
  scope: Scope
56
49
  interface: Any
57
50
  name: str
58
51
  parameters: tuple[ProviderParameter, ...]
59
- kind: ProviderKind
60
-
61
- def __str__(self) -> str:
62
- return self.name
63
-
64
- @cached_property
65
- def is_class(self) -> bool:
66
- return self.kind == ProviderKind.CLASS
67
-
68
- @cached_property
69
- def is_coroutine(self) -> bool:
70
- return self.kind == ProviderKind.COROUTINE
71
-
72
- @cached_property
73
- def is_generator(self) -> bool:
74
- return self.kind == ProviderKind.GENERATOR
75
-
76
- @cached_property
77
- def is_async_generator(self) -> bool:
78
- return self.kind == ProviderKind.ASYNC_GENERATOR
79
-
80
- @cached_property
81
- def is_async(self) -> bool:
82
- return self.is_coroutine or self.is_async_generator
83
-
84
- @cached_property
85
- def is_resource(self) -> bool:
86
- return ProviderKind.is_resource(self.kind)
52
+ is_class: bool
53
+ is_coroutine: bool
54
+ is_generator: bool
55
+ is_async_generator: bool
56
+ is_async: bool
57
+ is_resource: bool
87
58
 
88
59
 
89
- @dataclass(kw_only=True, frozen=True, slots=True)
60
+ @dataclass(frozen=True, slots=True)
90
61
  class ProviderDef:
91
62
  call: Callable[..., Any]
92
63
  scope: Scope