dependency-injection-pattern 0.0.7__tar.gz → 0.0.8__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.
Files changed (43) hide show
  1. {dependency_injection_pattern-0.0.7/src/dependency_injection_pattern.egg-info → dependency_injection_pattern-0.0.8}/PKG-INFO +5 -5
  2. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/pyproject.toml +4 -4
  3. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8/src/dependency_injection_pattern.egg-info}/PKG-INFO +5 -5
  4. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/SOURCES.txt +1 -0
  5. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/requires.txt +2 -2
  6. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/__init__.py +5 -5
  7. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/container.py +21 -31
  8. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/default_scope.py +13 -11
  9. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/factory_provide_exception.py +4 -1
  10. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/implementation_exception.py +1 -0
  11. dependency_injection_pattern-0.0.8/src/di/core/exceptions/internal_exception.py +4 -0
  12. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/provide_exception.py +1 -0
  13. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/dependency.py +4 -2
  14. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/factory.py +16 -10
  15. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/scoped_factory.py +3 -2
  16. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/singleton_factory.py +6 -4
  17. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/transient_factory.py +3 -2
  18. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factory.py +3 -2
  19. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/helpers.py +8 -13
  20. dependency_injection_pattern-0.0.8/src/di/core/log.py +4 -0
  21. dependency_injection_pattern-0.0.8/src/di/core/named_service.py +6 -0
  22. dependency_injection_pattern-0.0.8/src/di/core/protocols/factory.py +7 -0
  23. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/protocols/provider.py +1 -1
  24. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/provider.py +7 -8
  25. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/scope.py +3 -1
  26. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/service_request.py +2 -2
  27. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/exceptions.py +7 -7
  28. dependency_injection_pattern-0.0.7/src/di/core/log.py +0 -4
  29. dependency_injection_pattern-0.0.7/src/di/core/named_service.py +0 -3
  30. dependency_injection_pattern-0.0.7/src/di/core/protocols/factory.py +0 -7
  31. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/LICENSE +0 -0
  32. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/README.md +0 -0
  33. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/setup.cfg +0 -0
  34. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/dependency_links.txt +0 -0
  35. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/top_level.txt +0 -0
  36. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/add_exception.py +0 -0
  37. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/container_sealed_error.py +0 -0
  38. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/seal_exception.py +0 -0
  39. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/protocols/container.py +0 -0
  40. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_container.py +0 -0
  41. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_examples.py +0 -0
  42. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_factory.py +0 -0
  43. {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_provider.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dependency-injection-pattern
3
- Version: 0.0.7
3
+ Version: 0.0.8
4
4
  Summary: Python implementation of the Dependency Injection pattern.
5
5
  Author-email: Anders Madsen <anders.madsen@alphavue.com>
6
6
  License-Expression: MIT
@@ -14,23 +14,23 @@ Classifier: Intended Audience :: Developers
14
14
  Classifier: Natural Language :: English
15
15
  Classifier: Programming Language :: Python :: 3 :: Only
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
19
18
  Classifier: Programming Language :: Python :: 3.12
20
19
  Classifier: Programming Language :: Python :: 3.13
21
20
  Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Python :: 3.15
22
22
  Classifier: Programming Language :: Python
23
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
24
  Classifier: Topic :: Software Development :: Libraries
25
25
  Classifier: Typing :: Typed
26
- Requires-Python: <3.15,>=3.10
26
+ Requires-Python: <3.16,>=3.11
27
27
  Description-Content-Type: text/markdown
28
28
  License-File: LICENSE
29
29
  Requires-Dist: typing-utilities<0.2,>=0.1.0
30
30
  Requires-Dist: runtime-reflection-lite<0.3,>=0.2.0
31
31
  Provides-Extra: test
32
- Requires-Dist: pytest>=8.3; extra == "test"
33
- Requires-Dist: pytest-cov>=6.1; extra == "test"
32
+ Requires-Dist: pytest>=9.0; extra == "test"
33
+ Requires-Dist: pytest-cov>=7.0; extra == "test"
34
34
  Dynamic: license-file
35
35
 
36
36
  [![Test](https://github.com/apmadsen/dependency-injection-pattern/actions/workflows/python-test.yml/badge.svg)](https://github.com/apmadsen/dependency-injection-pattern/actions/workflows/python-test.yml)
@@ -18,11 +18,11 @@ classifiers = [
18
18
  "Natural Language :: English",
19
19
  "Programming Language :: Python :: 3 :: Only",
20
20
  "Programming Language :: Python :: 3",
21
- "Programming Language :: Python :: 3.10",
22
21
  "Programming Language :: Python :: 3.11",
23
22
  "Programming Language :: Python :: 3.12",
24
23
  "Programming Language :: Python :: 3.13",
25
24
  "Programming Language :: Python :: 3.14",
25
+ "Programming Language :: Python :: 3.15",
26
26
  "Programming Language :: Python",
27
27
  "Topic :: Software Development :: Libraries :: Python Modules",
28
28
  "Topic :: Software Development :: Libraries",
@@ -32,15 +32,15 @@ dependencies = [
32
32
  "typing-utilities >= 0.1.0, < 0.2",
33
33
  "runtime-reflection-lite >= 0.2.0, < 0.3"
34
34
  ]
35
- requires-python = ">= 3.10, < 3.15"
35
+ requires-python = ">= 3.11, < 3.16"
36
36
 
37
37
  [project.urls]
38
38
  repository = "https://github.com/apmadsen/dependency-injection-pattern"
39
39
 
40
40
  [project.optional-dependencies]
41
41
  test = [
42
- "pytest>=8.3",
43
- "pytest-cov>=6.1",
42
+ "pytest>=9.0",
43
+ "pytest-cov>=7.0",
44
44
  ]
45
45
 
46
46
  [tool.setuptools-git-versioning]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dependency-injection-pattern
3
- Version: 0.0.7
3
+ Version: 0.0.8
4
4
  Summary: Python implementation of the Dependency Injection pattern.
5
5
  Author-email: Anders Madsen <anders.madsen@alphavue.com>
6
6
  License-Expression: MIT
@@ -14,23 +14,23 @@ Classifier: Intended Audience :: Developers
14
14
  Classifier: Natural Language :: English
15
15
  Classifier: Programming Language :: Python :: 3 :: Only
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
19
18
  Classifier: Programming Language :: Python :: 3.12
20
19
  Classifier: Programming Language :: Python :: 3.13
21
20
  Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Python :: 3.15
22
22
  Classifier: Programming Language :: Python
23
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
24
  Classifier: Topic :: Software Development :: Libraries
25
25
  Classifier: Typing :: Typed
26
- Requires-Python: <3.15,>=3.10
26
+ Requires-Python: <3.16,>=3.11
27
27
  Description-Content-Type: text/markdown
28
28
  License-File: LICENSE
29
29
  Requires-Dist: typing-utilities<0.2,>=0.1.0
30
30
  Requires-Dist: runtime-reflection-lite<0.3,>=0.2.0
31
31
  Provides-Extra: test
32
- Requires-Dist: pytest>=8.3; extra == "test"
33
- Requires-Dist: pytest-cov>=6.1; extra == "test"
32
+ Requires-Dist: pytest>=9.0; extra == "test"
33
+ Requires-Dist: pytest-cov>=7.0; extra == "test"
34
34
  Dynamic: license-file
35
35
 
36
36
  [![Test](https://github.com/apmadsen/dependency-injection-pattern/actions/workflows/python-test.yml/badge.svg)](https://github.com/apmadsen/dependency-injection-pattern/actions/workflows/python-test.yml)
@@ -21,6 +21,7 @@ src/di/core/exceptions/add_exception.py
21
21
  src/di/core/exceptions/container_sealed_error.py
22
22
  src/di/core/exceptions/factory_provide_exception.py
23
23
  src/di/core/exceptions/implementation_exception.py
24
+ src/di/core/exceptions/internal_exception.py
24
25
  src/di/core/exceptions/provide_exception.py
25
26
  src/di/core/exceptions/seal_exception.py
26
27
  src/di/core/factories/dependency.py
@@ -2,5 +2,5 @@ typing-utilities<0.2,>=0.1.0
2
2
  runtime-reflection-lite<0.3,>=0.2.0
3
3
 
4
4
  [test]
5
- pytest>=8.3
6
- pytest-cov>=6.1
5
+ pytest>=9.0
6
+ pytest-cov>=7.0
@@ -1,13 +1,13 @@
1
1
  from di.core.container import Container
2
- from di.core.provider import Provider
3
- from di.core.scope import Scope
4
2
  from di.core.default_scope import DefaultScope
5
3
  from di.core.factory import Factory
4
+ from di.core.provider import Provider
5
+ from di.core.scope import Scope
6
6
 
7
7
  __all__ = [
8
8
  'Container',
9
- 'Provider',
10
- 'Scope',
11
9
  'DefaultScope',
12
- 'Factory'
10
+ 'Factory',
11
+ 'Provider',
12
+ 'Scope'
13
13
  ]
@@ -1,27 +1,30 @@
1
1
  from __future__ import annotations
2
- from typing import TypeVar, Callable, Any, cast, overload, TYPE_CHECKING
3
- from typingutils import is_type, isinstance_typing, issubclass_typing, get_optional_type
2
+
3
+ from collections.abc import Callable
4
4
  from types import FunctionType
5
+ from typing import TYPE_CHECKING, Any, TypeVar, cast, overload
5
6
  from weakref import ref
7
+
6
8
  from runtime.reflection.lite import get_signature
9
+ from typingutils import get_optional_type, is_type, isinstance_typing, issubclass_typing
7
10
 
8
- from di.core.log import LOG
9
- from di.core.scope import Scope
10
- from di.core.service_request import ServiceRequest
11
- from di.core.factories.singleton_factory import SingletonFactory
12
- from di.core.factories.transient_factory import TransientFactory
13
- from di.core.factories.scoped_factory import ScopedFactory
14
11
  from di.core.default_scope import DefaultScope
15
- from di.core.named_service import NamedService
16
- from di.core.helpers import clean_service_name, get_service_name, is_context
17
- from di.core.exceptions.provide_exception import ProvideException
18
12
  from di.core.exceptions.add_exception import AddException
19
- from di.core.exceptions.seal_exception import SealException
20
13
  from di.core.exceptions.container_sealed_error import ContainerSealedError
14
+ from di.core.exceptions.provide_exception import ProvideException
15
+ from di.core.exceptions.seal_exception import SealException
16
+ from di.core.factories.scoped_factory import ScopedFactory
17
+ from di.core.factories.singleton_factory import SingletonFactory
18
+ from di.core.factories.transient_factory import TransientFactory
19
+ from di.core.helpers import clean_service_name, get_service_name, is_context
20
+ from di.core.log import LOG
21
+ from di.core.named_service import NamedService
22
+ from di.core.scope import Scope
23
+ from di.core.service_request import ServiceRequest
21
24
 
22
25
  if TYPE_CHECKING:
23
- from di.core.provider import Provider
24
26
  from di.core.factories.factory import Factory
27
+ from di.core.provider import Provider
25
28
 
26
29
  T = TypeVar('T')
27
30
 
@@ -35,7 +38,7 @@ class Container:
35
38
  provider = container.provider() # container is sealed, and no more services can be added beyound this point
36
39
  provider.provide(Service) # => Service
37
40
  """
38
- __slots__ = ["__factories", "__named_factories", "__list_factories", "__default_scope", "__provider", "__weakref__"]
41
+ __slots__ = ["__default_scope", "__factories", "__list_factories", "__named_factories", "__provider", "__weakref__"]
39
42
 
40
43
  def __init__(self):
41
44
  self.__factories: dict[type[Any], Factory[Any]] = {}
@@ -54,7 +57,6 @@ class Container:
54
57
  Args:
55
58
  service (type[Any]): The service interface
56
59
  """
57
- ...
58
60
  @overload
59
61
  def add_singleton(self, implementation: Callable[..., T], /) -> None:
60
62
  """Adds a singleton service to provider, which will result in same instance every time it's provided.
@@ -62,7 +64,6 @@ class Container:
62
64
  Args:
63
65
  implementation (Callable[..., T]) The service implementation
64
66
  """
65
- ...
66
67
  @overload
67
68
  def add_singleton(self, service: type[T], implementation: type[T] | Callable[..., T] | T, /) -> None:
68
69
  """Adds a singleton service to provider, which will result in same instance every time it's provided.
@@ -72,7 +73,6 @@ class Container:
72
73
  service (type[T]) The service interface
73
74
  implementation (type[T] | Callable[..., T] | T) The service implementation
74
75
  """
75
- ...
76
76
  @overload
77
77
  def add_singleton(self, service: str, implementation: type[T] | Callable[..., T] | T, /) -> None:
78
78
  """Adds a singleton service to provider, which will result in same instance every time it's provided.
@@ -82,7 +82,6 @@ class Container:
82
82
  service (str) The service name
83
83
  implementation (type[T] | Callable[..., T] | T) The service implementation
84
84
  """
85
- ...
86
85
  def add_singleton(self, *args: Any) -> None:
87
86
  self.__add_factory_pre(SingletonFactory, *args)
88
87
 
@@ -94,7 +93,6 @@ class Container:
94
93
  service (type[Any]) The service interface
95
94
 
96
95
  """
97
- ...
98
96
  @overload
99
97
  def add_transient(self, implementation: Callable[..., T], /) -> None:
100
98
  """Adds a transient service to provider, which will result in a new instance every time it's provided.
@@ -102,7 +100,6 @@ class Container:
102
100
  Args:
103
101
  implementation (Callable[..., T]) The service implementation
104
102
  """
105
- ...
106
103
  @overload
107
104
  def add_transient(self, service: type[T], implementation: type[T] | Callable[..., T], /) -> None:
108
105
  """Adds a transient service to provider, which will result in a new instance every time it's provided.
@@ -112,7 +109,6 @@ class Container:
112
109
  service (str | type[T]) The service interface
113
110
  implementation (type[T] | Callable[..., T]) The service implementation
114
111
  """
115
- ...
116
112
  @overload
117
113
  def add_transient(self, service: str, implementation: type[T] | Callable[..., T] | T, /) -> None:
118
114
  """Adds a transient service to provider, which will result in a new instance every time it's provided.
@@ -122,7 +118,6 @@ class Container:
122
118
  service (str) The service name
123
119
  implementation (type[T] | Callable[..., T] | T) The service implementation
124
120
  """
125
- ...
126
121
  def add_transient(self, *args: Any) -> None:
127
122
  self.__add_factory_pre(TransientFactory, *args)
128
123
 
@@ -136,7 +131,6 @@ class Container:
136
131
  Args:
137
132
  service (type[Any]) The service interface
138
133
  """
139
- ...
140
134
  @overload
141
135
  def add_scoped(self, implementation: Callable[..., T], /) -> None:
142
136
  """Adds a scoped service to provider, which will result in one instance every time it's provided in the same scope.
@@ -147,7 +141,6 @@ class Container:
147
141
  Args:
148
142
  implementation (Callable[..., T]) The service implementation
149
143
  """
150
- ...
151
144
  @overload
152
145
  def add_scoped(self, service: type[T], implementation: type[T] | Callable[..., T], /) -> None:
153
146
  """Adds a scoped service to provider, which will result in one instance every time it's provided in the same scope.
@@ -160,7 +153,6 @@ class Container:
160
153
  service (str | type[T]) The service interface
161
154
  implementation (type[T] | Callable[..., T]) The service implementation
162
155
  """
163
- ...
164
156
  @overload
165
157
  def add_scoped(self, service: str, implementation: type[T] | Callable[..., T] | T, /) -> None:
166
158
  """Adds a scoped service to provider, which will result in one instance every time it's provided in the same scope.
@@ -173,7 +165,6 @@ class Container:
173
165
  service (str) The service name
174
166
  implementation (type[T] | Callable[..., T] | T) The service implementation
175
167
  """
176
- ...
177
168
  def add_scoped(self, *args: Any) -> None:
178
169
  service, svc_type = self.__add_factory_pre(ScopedFactory, *args)
179
170
 
@@ -286,7 +277,7 @@ class Container:
286
277
  return True
287
278
  else:
288
279
  # check for factories of derived types
289
- for provided_service, _ in self.__factories.items():
280
+ for provided_service in self.__factories:
290
281
  if issubclass_typing(provided_service, cast(type[Any], service)):
291
282
  return True
292
283
 
@@ -318,10 +309,9 @@ class Container:
318
309
  if svc_def[0] is svc_type:
319
310
  factory = svc_def[1]
320
311
  break
321
- elif is_type(svc):
322
- if svc in self.__factories:
323
- factory = self.__factories[cast(type, svc)]
324
- break
312
+ elif is_type(svc) and svc in self.__factories:
313
+ factory = self.__factories[cast(type, svc)]
314
+ break
325
315
 
326
316
  # check for factories of derived types
327
317
  for svc in [svc_type, service]: # pyright: ignore[reportUnknownVariableType]
@@ -1,11 +1,13 @@
1
1
  from __future__ import annotations
2
- from typing import TypeVar, Callable, MutableMapping, cast
3
- from threading import Thread, local, current_thread, main_thread
4
2
 
3
+ from collections.abc import Callable, MutableMapping
4
+ from threading import Thread, current_thread, local, main_thread
5
+ from typing import TypeVar, cast
6
+
7
+ from di.core.exceptions.provide_exception import ProvideException
8
+ from di.core.helpers import get_service_name, is_context
5
9
  from di.core.log import LOG
6
10
  from di.core.scope import Scope
7
- from di.core.exceptions.provide_exception import ProvideException
8
- from di.core.helpers import is_context, get_service_name
9
11
 
10
12
  T = TypeVar('T')
11
13
 
@@ -38,15 +40,15 @@ class DefaultScope(Scope):
38
40
  def finalize(thread: Thread, dict: MutableMapping[type[T], T]) -> None:
39
41
  thread.join() # wait until thread is finished
40
42
  LOG.debug(f"Finalizing scope for thread '{current_thread().name}'")
41
- for service, implementation in dict.items():
43
+ for svc, implementation in dict.items():
42
44
  try:
43
- if is_context(service):
44
- LOG.debug(f"Disposing service '{get_service_name(service)}' on thread '{current_thread().name}'")
45
- getattr(implementation, "__exit__")(None, None, None)
45
+ if is_context(svc):
46
+ LOG.debug(f"Disposing service '{get_service_name(svc)}' on thread '{current_thread().name}'")
47
+ implementation.__exit__(None, None, None) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
46
48
 
47
- except Exception as ex: # pragma: no cover
49
+ except Exception as ex: # pragma: no cover # noqa: BLE001
48
50
  # swallow exception, as it's caught in the finalizer thread
49
- LOG.error(f"Disposing of service '{get_service_name(service)}' failed: {ex}")
51
+ LOG.error(f"Disposing of service '{get_service_name(svc)}' failed: {ex}")
50
52
 
51
53
 
52
54
  dict.clear()
@@ -60,7 +62,7 @@ class DefaultScope(Scope):
60
62
  if current_thread() != main_thread() and is_context(service):
61
63
  # finalizer is only implemented when thread is not main thread, otherwise object would never be exited (eg. finalized)
62
64
  LOG.debug(f"Initializing service '{get_service_name(service)}' on thread '{current_thread().name}'")
63
- impl = cast(T, getattr(impl, "__enter__")())
65
+ impl = cast(T, impl.__enter__()) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
64
66
  if not isinstance(impl, service): # pragma: no cover
65
67
  raise ProvideException(service, f"Service '{get_service_name(service)}' implementation's __enter__() method returned an object of different type than service")
66
68
 
@@ -1,9 +1,12 @@
1
1
  # pragma: no cover
2
- from typing import Mapping, overload
2
+ from collections.abc import Mapping
3
+ from typing import overload
4
+
3
5
  from typingutils import AnyType
4
6
 
5
7
  from di.core.helpers import get_service_name
6
8
 
9
+
7
10
  class FactoryProvideException(Exception):
8
11
  """
9
12
  The FactoryProvideException is raised when factory cannot provide service, because one or more
@@ -3,6 +3,7 @@ from typing import Any
3
3
 
4
4
  from di.core.helpers import get_service_name
5
5
 
6
+
6
7
  class ImplementationException(Exception):
7
8
  """
8
9
  The ImplementationException is raised at initialization time when factory cannot provide service using the
@@ -0,0 +1,4 @@
1
+
2
+ class InternalException(Exception):
3
+ """The InternalException is raised when an internal class is used outside the package.
4
+ """
@@ -3,6 +3,7 @@ from typing import overload
3
3
 
4
4
  from di.core.helpers import get_service_name
5
5
 
6
+
6
7
  class ProvideException(Exception):
7
8
  """
8
9
  The ProvideException is raised when provider cannot provide service.
@@ -1,11 +1,13 @@
1
1
  from typing import Any, cast
2
- from typingutils import get_optional_type
2
+
3
3
  from runtime.reflection.lite import Undefined
4
+ from typingutils import get_optional_type
4
5
 
5
6
  from di.core.helpers import get_provided_service_from_annotation
6
7
 
8
+
7
9
  class Dependency:
8
- __slots__ = [ "__name", "__service", "__factory", "__optional", "__default" ]
10
+ __slots__ = ["__default", "__factory", "__name", "__optional", "__service"]
9
11
 
10
12
  def __init__(self, name: str, service: type[Any], default: Any ):
11
13
  self.__name = name
@@ -1,21 +1,27 @@
1
- from typing import TypeVar, Callable, Generic, Any, cast
2
- from typingutils import get_optional_type, issubclass_typing, isinstance_typing
3
- from runtime.reflection.lite import Undefined, ParameterKind, get_signature, get_constructor
1
+ from collections.abc import Callable
2
+ from typing import Any, Generic, TypeVar, cast
4
3
 
5
- from di.core.scope import Scope
6
- from di.core.named_service import NamedService
7
- from di.core.service_request import ServiceRequest
4
+ from runtime.reflection.lite import (
5
+ ParameterKind,
6
+ Undefined,
7
+ get_constructor,
8
+ get_signature,
9
+ )
10
+ from typingutils import get_optional_type, isinstance_typing, issubclass_typing
8
11
 
9
- from di.core.exceptions.implementation_exception import ImplementationException
10
12
  from di.core.exceptions.factory_provide_exception import FactoryProvideException
13
+ from di.core.exceptions.implementation_exception import ImplementationException
11
14
  from di.core.exceptions.provide_exception import ProvideException
12
- from di.core.protocols.container import Container
13
15
  from di.core.factories.dependency import Dependency
16
+ from di.core.named_service import NamedService
17
+ from di.core.protocols.container import Container
18
+ from di.core.scope import Scope
19
+ from di.core.service_request import ServiceRequest
14
20
 
15
21
  T = TypeVar('T')
16
22
 
17
23
  class Factory(Generic[T]):
18
- __slots__ = ["__container", "__service", "__implementation", "__ctor", "__dependencies"]
24
+ __slots__ = ["__container", "__ctor", "__dependencies", "__implementation", "__service"]
19
25
 
20
26
  def __init__(self, container: Container, service: type[T], implementation: type[T] | Callable[..., T] | T | None = None):
21
27
  self.__container = container
@@ -25,7 +31,7 @@ class Factory(Generic[T]):
25
31
 
26
32
  if not implementation:
27
33
  if hasattr(service, "__origin__"):
28
- sig = get_signature(getattr(service, "__call__"), service)
34
+ sig = get_signature(service.__call__, service)
29
35
  else:
30
36
  sig = get_constructor(service)
31
37
  elif isinstance(implementation, type):
@@ -1,9 +1,10 @@
1
1
 
2
- from typing import TypeVar, Callable
2
+ from collections.abc import Callable
3
+ from typing import TypeVar
3
4
 
4
- from di.core.scope import Scope
5
5
  from di.core.factories.factory import Factory
6
6
  from di.core.protocols.container import Container
7
+ from di.core.scope import Scope
7
8
 
8
9
  T = TypeVar('T')
9
10
 
@@ -1,12 +1,14 @@
1
- from typing import TypeVar, Callable, cast
1
+ from collections.abc import Callable
2
+ from typing import TypeVar, cast
3
+
2
4
  from typingutils import is_type, isinstance_typing
3
5
 
4
- from di.core.log import LOG
6
+ from di.core.factories.factory import Factory
5
7
  from di.core.helpers import get_service_name
6
- from di.core.scope import Scope
8
+ from di.core.log import LOG
7
9
  from di.core.named_service import NamedService
8
- from di.core.factories.factory import Factory
9
10
  from di.core.protocols.container import Container
11
+ from di.core.scope import Scope
10
12
 
11
13
  T = TypeVar('T')
12
14
 
@@ -1,8 +1,9 @@
1
- from typing import TypeVar, Callable
1
+ from collections.abc import Callable
2
+ from typing import TypeVar
2
3
 
3
- from di.core.scope import Scope
4
4
  from di.core.factories.factory import Factory
5
5
  from di.core.protocols.container import Container
6
+ from di.core.scope import Scope
6
7
 
7
8
  T = TypeVar('T')
8
9
 
@@ -1,5 +1,6 @@
1
- from typing import TypeVar, Generic
1
+ from typing import Generic, TypeVar
2
2
 
3
+ from di.core.exceptions.internal_exception import InternalException
3
4
  from di.core.scope import Scope
4
5
 
5
6
  T = TypeVar("T")
@@ -15,7 +16,7 @@ class Factory(Generic[T]):
15
16
  """
16
17
 
17
18
  def __new__(cls):
18
- raise Exception("The Factory class is not intended for instantation") # pragma: no cover
19
+ raise InternalException("The Factory class is not intended for instantation") # pragma: no cover
19
20
 
20
21
  def provide(self, scope: Scope | None = None) -> T: # pragma: no cover
21
22
  raise NotImplementedError
@@ -1,23 +1,24 @@
1
- from typing import MutableMapping, Protocol, TypeVar, cast, runtime_checkable
1
+ from collections.abc import MutableMapping
2
2
  from types import TracebackType
3
- from typingutils import AnyType, issubclass_typing, get_type_name
3
+ from typing import Protocol, TypeVar, cast, runtime_checkable
4
4
 
5
- from di.core.factory import Factory
5
+ from typingutils import AnyType, get_type_name, issubclass_typing
6
6
 
7
+ from di.core.factory import Factory
7
8
 
8
- T = TypeVar('T', covariant=True)
9
+ T = TypeVar('T', covariant=True) # noqa: PLC0105
9
10
 
10
11
  @runtime_checkable
11
12
  class ContextManager(Protocol[T]): # pragma: no cover
12
13
  def __enter__(self) -> T: ...
13
- def __exit__(self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None) -> None: ...
14
+ def __exit__(self, /, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None) -> None: ...
14
15
 
15
16
 
16
17
  def get_service_name(service: AnyType | str) -> str: # pragma: no cover
17
18
  if isinstance(service, str):
18
19
  return service
19
20
  elif hasattr(service, "__name__"):
20
- return getattr(service, "__name__")
21
+ return cast(str, service.__name__) # pyright: ignore[reportAttributeAccessIssue, reportUnknownMemberType]
21
22
  else:
22
23
  return get_type_name(service)
23
24
 
@@ -26,7 +27,7 @@ def clean_service_name(service: str) -> str:
26
27
 
27
28
  def get_provided_service_from_annotation(annotation: AnyType) -> tuple[AnyType, bool]:
28
29
  if issubclass_typing(annotation, Factory):
29
- return cast(tuple[type], getattr(annotation, "__args__"))[0], True
30
+ return cast(tuple[type], annotation.__args__)[0], True # pyright: ignore[reportAttributeAccessIssue, reportUnknownMemberType]
30
31
  else:
31
32
  return annotation, False
32
33
 
@@ -35,12 +36,6 @@ __CONTEXT_SERVICES__: MutableMapping[type, bool] = {}
35
36
 
36
37
  def is_context(cls: type) -> bool:
37
38
  if cls not in __CONTEXT_SERVICES__:
38
- # reflection = reflect_class(cls)
39
-
40
- # if "__enter__" in reflection.functions and "__exit__" in reflection.functions:
41
- # result = reflection.functions["__enter__"].return_type is cls
42
- # else:
43
- # result = False
44
39
  if issubclass(cls, ContextManager):
45
40
  result = True
46
41
  else:
@@ -0,0 +1,4 @@
1
+ from logging import DEBUG, getLogger
2
+
3
+ LOG = getLogger("dependency-injection")
4
+ LOG.setLevel(DEBUG)
@@ -0,0 +1,6 @@
1
+ from di.core.exceptions.internal_exception import InternalException
2
+
3
+
4
+ class NamedService:
5
+ def __new__(cls):
6
+ raise InternalException("The NamedService is a special class not meant to be instantiated") # pragma: no cover
@@ -0,0 +1,7 @@
1
+ from typing import Generic, Protocol, TypeVar, runtime_checkable
2
+
3
+ T = TypeVar("T", covariant=True) # noqa: PLC0105
4
+
5
+ @runtime_checkable
6
+ class Factory(Protocol, Generic[T]): # pragma: no cover
7
+ ...
@@ -1,4 +1,4 @@
1
- from typing import Protocol, Any, TypeVar, overload, runtime_checkable
1
+ from typing import Any, Protocol, TypeVar, overload, runtime_checkable
2
2
 
3
3
  from di.core.scope import Scope
4
4
  from di.core.service_request import ServiceRequest
@@ -1,12 +1,13 @@
1
- from typing import TypeVar, Any, cast, overload
2
- from typingutils import issubclass_typing, get_optional_type
1
+ from typing import Any, TypeVar, cast, overload
2
+
3
+ from typingutils import get_optional_type, issubclass_typing
3
4
 
4
5
  from di.core.exceptions.factory_provide_exception import FactoryProvideException
5
- from di.core.scope import Scope
6
- from di.core.factory import Factory as PublicFactory
7
6
  from di.core.factories.factory import Factory
8
- from di.core.service_request import ServiceRequest
7
+ from di.core.factory import Factory as PublicFactory
9
8
  from di.core.protocols.container import Container
9
+ from di.core.scope import Scope
10
+ from di.core.service_request import ServiceRequest
10
11
 
11
12
  T = TypeVar('T')
12
13
 
@@ -41,7 +42,6 @@ class Provider:
41
42
  service (type[Any]) The service interface.
42
43
 
43
44
  """
44
- ...
45
45
  @overload
46
46
  def provide(self, service: type[T], scope: Scope) -> T:
47
47
  """
@@ -51,7 +51,6 @@ class Provider:
51
51
  service (type[Any]) The service interface.
52
52
  scope (Scope) A custom scope.
53
53
  """
54
- ...
55
54
  def provide(self, service: type[T], scope: Scope | None = None) -> T:
56
55
  return self._provide(service, scope)
57
56
 
@@ -63,7 +62,7 @@ class Provider:
63
62
 
64
63
  if svc_type and issubclass_typing(svc_type, PublicFactory):
65
64
  def factory() -> T:
66
- return self._provide(cast(type[T], getattr(svc_type, "__args__")[0]))
65
+ return self._provide(cast(type[T], svc_type.__args__[0])) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
67
66
  return factory # pyright: ignore[reportReturnType]
68
67
  else:
69
68
  result = self.__container._get(cast(type[T], service)) # pyright: ignore[reportPrivateUsage]
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
+
2
3
  from abc import ABC, abstractmethod
3
- from typing import Callable, TypeVar
4
+ from collections.abc import Callable
5
+ from typing import TypeVar
4
6
 
5
7
  T = TypeVar('T')
6
8
 
@@ -1,4 +1,4 @@
1
- from typing import TypeVar, Generic
1
+ from typing import Generic, TypeVar
2
2
 
3
3
  T = TypeVar("T")
4
4
 
@@ -6,7 +6,7 @@ class ServiceRequest(Generic[T]):
6
6
  """
7
7
  The ServiceRequest[T] class is used internally to request a service by name.
8
8
  """
9
- __slots__ = ["__name", "__type", "__default"]
9
+ __slots__ = ["__default", "__name", "__type"]
10
10
 
11
11
  def __init__(self, name: str, type: type[T], default: T):
12
12
  self.__name = name.lower()
@@ -1,15 +1,15 @@
1
1
  from di.core.exceptions.add_exception import AddException
2
- from di.core.exceptions.implementation_exception import ImplementationException
3
- from di.core.exceptions.factory_provide_exception import FactoryProvideException
4
2
  from di.core.exceptions.container_sealed_error import ContainerSealedError
5
- from di.core.exceptions.seal_exception import SealException
3
+ from di.core.exceptions.factory_provide_exception import FactoryProvideException
4
+ from di.core.exceptions.implementation_exception import ImplementationException
6
5
  from di.core.exceptions.provide_exception import ProvideException
6
+ from di.core.exceptions.seal_exception import SealException
7
7
 
8
8
  __all__ = [
9
9
  'AddException',
10
- 'ImplementationException',
11
- 'FactoryProvideException',
12
10
  'ContainerSealedError',
13
- 'SealException',
14
- 'ProvideException'
11
+ 'FactoryProvideException',
12
+ 'ImplementationException',
13
+ 'ProvideException',
14
+ 'SealException'
15
15
  ]
@@ -1,4 +0,0 @@
1
- from logging import getLogger, DEBUG
2
-
3
- LOG = getLogger("dependency-injection")
4
- LOG.setLevel(DEBUG)
@@ -1,3 +0,0 @@
1
- class NamedService():
2
- def __new__(cls):
3
- raise Exception("The NamedService is a special class not meant to be instantiated") # pragma: no cover
@@ -1,7 +0,0 @@
1
- from typing import Protocol, TypeVar, Generic, runtime_checkable
2
-
3
- T = TypeVar("T", covariant=True)
4
-
5
- @runtime_checkable
6
- class Factory(Generic[T], Protocol): # pragma: no cover
7
- ...