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.
- {dependency_injection_pattern-0.0.7/src/dependency_injection_pattern.egg-info → dependency_injection_pattern-0.0.8}/PKG-INFO +5 -5
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/pyproject.toml +4 -4
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8/src/dependency_injection_pattern.egg-info}/PKG-INFO +5 -5
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/SOURCES.txt +1 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/requires.txt +2 -2
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/__init__.py +5 -5
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/container.py +21 -31
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/default_scope.py +13 -11
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/factory_provide_exception.py +4 -1
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/implementation_exception.py +1 -0
- dependency_injection_pattern-0.0.8/src/di/core/exceptions/internal_exception.py +4 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/provide_exception.py +1 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/dependency.py +4 -2
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/factory.py +16 -10
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/scoped_factory.py +3 -2
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/singleton_factory.py +6 -4
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factories/transient_factory.py +3 -2
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factory.py +3 -2
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/helpers.py +8 -13
- dependency_injection_pattern-0.0.8/src/di/core/log.py +4 -0
- dependency_injection_pattern-0.0.8/src/di/core/named_service.py +6 -0
- dependency_injection_pattern-0.0.8/src/di/core/protocols/factory.py +7 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/protocols/provider.py +1 -1
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/provider.py +7 -8
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/scope.py +3 -1
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/service_request.py +2 -2
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/exceptions.py +7 -7
- dependency_injection_pattern-0.0.7/src/di/core/log.py +0 -4
- dependency_injection_pattern-0.0.7/src/di/core/named_service.py +0 -3
- dependency_injection_pattern-0.0.7/src/di/core/protocols/factory.py +0 -7
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/LICENSE +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/README.md +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/setup.cfg +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/dependency_links.txt +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/dependency_injection_pattern.egg-info/top_level.txt +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/add_exception.py +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/container_sealed_error.py +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/exceptions/seal_exception.py +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/protocols/container.py +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_container.py +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_examples.py +0 -0
- {dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_factory.py +0 -0
- {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.
|
|
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.
|
|
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>=
|
|
33
|
-
Requires-Dist: pytest-cov>=
|
|
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
|
[](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.
|
|
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>=
|
|
43
|
-
"pytest-cov>=
|
|
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.
|
|
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.
|
|
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>=
|
|
33
|
-
Requires-Dist: pytest-cov>=
|
|
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
|
[](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
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/__init__.py
RENAMED
|
@@ -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
|
]
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/container.py
RENAMED
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from
|
|
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__ = ["
|
|
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
|
|
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
|
-
|
|
323
|
-
|
|
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
|
|
43
|
+
for svc, implementation in dict.items():
|
|
42
44
|
try:
|
|
43
|
-
if is_context(
|
|
44
|
-
LOG.debug(f"Disposing service '{get_service_name(
|
|
45
|
-
|
|
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(
|
|
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,
|
|
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
|
|
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
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from typing import Any, cast
|
|
2
|
-
|
|
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__ = [
|
|
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
|
|
2
|
-
from
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
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", "
|
|
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(
|
|
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
|
|
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
|
|
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.
|
|
6
|
+
from di.core.factories.factory import Factory
|
|
5
7
|
from di.core.helpers import get_service_name
|
|
6
|
-
from di.core.
|
|
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
|
|
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
|
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/factory.py
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
from typing import
|
|
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
|
|
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
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/helpers.py
RENAMED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import MutableMapping
|
|
2
2
|
from types import TracebackType
|
|
3
|
-
from
|
|
3
|
+
from typing import Protocol, TypeVar, cast, runtime_checkable
|
|
4
4
|
|
|
5
|
-
from
|
|
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
|
|
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],
|
|
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:
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/core/provider.py
RENAMED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
|
|
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.
|
|
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],
|
|
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,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
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__ = ["
|
|
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()
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/src/di/exceptions.py
RENAMED
|
@@ -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.
|
|
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
|
-
'
|
|
14
|
-
'
|
|
11
|
+
'FactoryProvideException',
|
|
12
|
+
'ImplementationException',
|
|
13
|
+
'ProvideException',
|
|
14
|
+
'SealException'
|
|
15
15
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_container.py
RENAMED
|
File without changes
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_examples.py
RENAMED
|
File without changes
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_factory.py
RENAMED
|
File without changes
|
{dependency_injection_pattern-0.0.7 → dependency_injection_pattern-0.0.8}/tests/test_provider.py
RENAMED
|
File without changes
|