anydi 0.55.1__py3-none-any.whl → 0.57.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.
@@ -0,0 +1,266 @@
1
+ Metadata-Version: 2.4
2
+ Name: anydi
3
+ Version: 0.57.0
4
+ Summary: Dependency Injection library
5
+ Keywords: dependency injection,dependencies,di,async,asyncio,application
6
+ Author: Anton Ruhlov
7
+ Author-email: Anton Ruhlov <antonruhlov@gmail.com>
8
+ License-Expression: MIT
9
+ Classifier: Intended Audience :: Information Technology
10
+ Classifier: Intended Audience :: System Administrators
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Topic :: Internet
14
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Topic :: Software Development
18
+ Classifier: Typing :: Typed
19
+ Classifier: Environment :: Web Environment
20
+ Classifier: Intended Audience :: Developers
21
+ Classifier: License :: OSI Approved :: MIT License
22
+ Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: 3.14
28
+ Classifier: Programming Language :: Python :: 3 :: Only
29
+ Requires-Dist: typing-extensions>=4.15.0,<5
30
+ Requires-Dist: anyio>=3.7.1
31
+ Requires-Dist: wrapt>=1.17.0
32
+ Requires-Python: >=3.10.0, <3.15
33
+ Project-URL: Repository, https://github.com/antonrh/anydi
34
+ Description-Content-Type: text/markdown
35
+
36
+ # AnyDI
37
+
38
+ <div style="text-align: center;">
39
+
40
+ Modern, lightweight Dependency Injection library using type annotations.
41
+
42
+ [![CI](https://github.com/antonrh/anydi/actions/workflows/ci.yml/badge.svg)](https://github.com/antonrh/anydi/actions/workflows/ci.yml)
43
+ [![Coverage](https://codecov.io/gh/antonrh/anydi/branch/main/graph/badge.svg)](https://codecov.io/gh/antonrh/anydi)
44
+ [![Documentation](https://readthedocs.org/projects/anydi/badge/?version=latest)](https://anydi.readthedocs.io/en/latest/)
45
+
46
+ </div>
47
+
48
+ ---
49
+ Documentation
50
+
51
+ http://anydi.readthedocs.io/
52
+
53
+ ---
54
+
55
+ `AnyDI` is a modern, lightweight Dependency Injection library suitable for any synchronous or asynchronous applications with Python 3.10+, based on type annotations ([PEP 484](https://peps.python.org/pep-0484/)).
56
+
57
+ The key features are:
58
+
59
+ * **Type-safe**: Dependency resolution is driven by type hints.
60
+ * **Async-ready**: Works the same for sync and async providers or injections.
61
+ * **Scoped**: Built-in singleton, transient, and request lifetimes.
62
+ * **Simple**: Small surface area keeps boilerplate low.
63
+ * **Fast**: Resolver still adds only microseconds of overhead.
64
+ * **Named**: `Annotated[...]` makes multiple bindings per type simple.
65
+ * **Managed**: Providers can open/close resources via context managers.
66
+ * **Modular**: Compose containers or modules for large apps.
67
+ * **Scanning**: Auto-discovers injectable callables.
68
+ * **Integrated**: Extensions for popular frameworks.
69
+ * **Testable**: Override providers directly in tests.
70
+
71
+ ## Installation
72
+
73
+ ```shell
74
+ pip install anydi
75
+ ```
76
+
77
+ ## Comprehensive Example
78
+
79
+ ### Define a Service (`app/services.py`)
80
+
81
+ ```python
82
+ class GreetingService:
83
+ def greet(self, name: str) -> str:
84
+ return f"Hello, {name}!"
85
+ ```
86
+
87
+ ### Create the Container and Providers (`app/container.py`)
88
+
89
+ ```python
90
+ from anydi import Container
91
+
92
+ from app.services import GreetingService
93
+
94
+
95
+ container = Container()
96
+
97
+
98
+ @container.provider(scope="singleton")
99
+ def service() -> GreetingService:
100
+ return GreetingService()
101
+ ```
102
+
103
+ ### Resolve Dependencies Directly
104
+
105
+ ```python
106
+ from app.container import container
107
+ from app.services import GreetingService
108
+
109
+
110
+ service = container.resolve(GreetingService)
111
+
112
+ if __name__ == "__main__":
113
+ print(service.greet("World"))
114
+ ```
115
+
116
+ ### Inject Into Functions (`app/main.py`)
117
+
118
+ ```python
119
+ from anydi import Provide
120
+
121
+ from app.container import container
122
+ from app.services import GreetingService
123
+
124
+
125
+ def greet(service: Provide[GreetingService]) -> str:
126
+ return service.greet("World")
127
+
128
+
129
+ if __name__ == "__main__":
130
+ print(container.run(greet))
131
+ ```
132
+
133
+ ### Test with Overrides (`tests/test_app.py`)
134
+
135
+ ```python
136
+ from unittest import mock
137
+
138
+ from app.container import container
139
+ from app.services import GreetingService
140
+ from app.main import greet
141
+
142
+
143
+ def test_greet() -> None:
144
+ service_mock = mock.Mock(spec=GreetingService)
145
+ service_mock.greet.return_value = "Mocked"
146
+
147
+ with container.override(GreetingService, service_mock):
148
+ result = container.run(greet)
149
+
150
+ assert result == "Mocked"
151
+ ```
152
+
153
+ ### Integrate with FastAPI (`app/api.py`)
154
+
155
+ ```python
156
+ from typing import Annotated
157
+
158
+ import anydi.ext.fastapi
159
+ from fastapi import FastAPI
160
+
161
+ from anydi import Provide
162
+ from app.container import container
163
+ from app.services import GreetingService
164
+
165
+
166
+ app = FastAPI()
167
+
168
+
169
+ @app.get("/greeting")
170
+ async def greet(
171
+ service: Provide[GreetingService]
172
+ ) -> dict[str, str]:
173
+ return {"greeting": service.greet("World")}
174
+
175
+
176
+ anydi.ext.fastapi.install(app, container)
177
+ ```
178
+
179
+ ### Test the FastAPI Integration (`test_api.py`)
180
+
181
+ ```python
182
+ from unittest import mock
183
+
184
+ from fastapi.testclient import TestClient
185
+
186
+ from app.api import app
187
+ from app.container import container
188
+ from app.services import GreetingService
189
+
190
+
191
+ client = TestClient(app)
192
+
193
+
194
+ def test_api_greeting() -> None:
195
+ service_mock = mock.Mock(spec=GreetingService)
196
+ service_mock.greet.return_value = "Mocked"
197
+
198
+ with container.override(GreetingService, service_mock):
199
+ response = client.get("/greeting")
200
+
201
+ assert response.json() == {"greeting": "Mocked"}
202
+ ```
203
+
204
+ ### Integrate with Django Ninja
205
+
206
+ Install the Django integration extras:
207
+
208
+ ```sh
209
+ pip install 'anydi-django[ninja]'
210
+ ```
211
+
212
+ Expose the container factory (`app/container.py`):
213
+
214
+ ```python
215
+ from anydi import Container
216
+
217
+ from app.services import GreetingService
218
+
219
+
220
+ container = Container()
221
+
222
+
223
+ @container.provider(scope="singleton")
224
+ def service() -> GreetingService:
225
+ return GreetingService()
226
+ ```
227
+
228
+ Configure Django (`settings.py`):
229
+
230
+ ```python
231
+ INSTALLED_APPS = [
232
+ ...
233
+ "anydi_django",
234
+ ]
235
+
236
+ ANYDI = {
237
+ "CONTAINER_FACTORY": "app.container.container",
238
+ "PATCH_NINJA": True,
239
+ }
240
+ ```
241
+
242
+ Wire Django Ninja (`urls.py`):
243
+
244
+ ```python
245
+ from typing import Annotated, Any
246
+
247
+ from anydi import Provide
248
+ from django.http import HttpRequest
249
+ from django.urls import path
250
+ from ninja import NinjaAPI
251
+
252
+ from app.services import GreetingService
253
+
254
+
255
+ api = NinjaAPI()
256
+
257
+
258
+ @api.get("/greeting")
259
+ def greet(request: HttpRequest, service: Provide[GreetingService]) -> Any:
260
+ return {"greeting": service.greet("World")}
261
+
262
+
263
+ urlpatterns = [
264
+ path("api/", api.urls),
265
+ ]
266
+ ```
@@ -0,0 +1,25 @@
1
+ anydi/__init__.py,sha256=bQKzn9qfNnIMi1m3J-DdSknSDwNg8j08fdQg_-Edkto,613
2
+ anydi/_async_lock.py,sha256=3dwZr0KthXFYha0XKMyXf8jMmGb1lYoNC0O5w29V9ic,1104
3
+ anydi/_container.py,sha256=Zdy0KtOVRlyBSblAk2MEFp13RwJkfljpB2szR5VTHQQ,22975
4
+ anydi/_context.py,sha256=-9QqeMWo9OpZVXZxZCQgIsswggl3Ch7lgx1KiFX_ezc,3752
5
+ anydi/_decorators.py,sha256=J3W261ZAG7q4XKm4tbAv1wsWr9ysx9_5MUbUvSJB_MQ,2809
6
+ anydi/_injector.py,sha256=IxKTh2rzMHrsW554tbiJl33Hb5sRGKYY_NU1rC4UvxE,4378
7
+ anydi/_module.py,sha256=2kN5uEXLd2Dsc58gz5IWK43wJewr_QgIVGSO3iWp798,2609
8
+ anydi/_provider.py,sha256=OV1WFHTYv7W2U0XDk_Kql1r551Vhq8o-pUV5ep1HQcU,1574
9
+ anydi/_resolver.py,sha256=-MF2KsERF5qzU6uqYPF1fI58isgsjxXPLERylzFFDHE,28787
10
+ anydi/_scanner.py,sha256=rbRkHzyd2zMu7AFLffN6_tZJcMaW9gy7E-lVdHLHYrs,4294
11
+ anydi/_types.py,sha256=gpanGqXjF9WQFFn62kyIod6m1dE97vV-L2u2Y2nWie8,2933
12
+ anydi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ anydi/ext/django/__init__.py,sha256=Ve8lncLU9dPY_Vjt4zihPgsSxwAtFHACn0XvBM5JG8k,367
14
+ anydi/ext/fastapi.py,sha256=8kXdO6RPwRbPyUh6YirdEPE-clJKXE--n-TAYI2hZf8,2326
15
+ anydi/ext/faststream.py,sha256=XT80r1FGL-xlU7r8urm9sNpUfl4OPMJseW4dade_fR4,1836
16
+ anydi/ext/pydantic_settings.py,sha256=jVJZ1wPaPpsxdNPlJj9yq282ebqLZ9tckWpZ0eIwWLg,1533
17
+ anydi/ext/pytest_plugin.py,sha256=M54DkA-KxD9GqLnXdoCyn-Qur2c44MB6d0AgJuYCZ5w,16171
18
+ anydi/ext/starlette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ anydi/ext/starlette/middleware.py,sha256=MxnzshAs-CMvjJp0r457k52MzBL8O4KAuClnF6exBdU,803
20
+ anydi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ anydi/testing.py,sha256=cHg3mMScZbEep9smRqSNQ81BZMQOkyugHe8TvKdPnEg,1347
22
+ anydi-0.57.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
23
+ anydi-0.57.0.dist-info/entry_points.txt,sha256=AgOcQYM5KyS4D37QcYb00tiid0QA-pD1VrjHHq4QAps,44
24
+ anydi-0.57.0.dist-info/METADATA,sha256=w3aIoTTCQHgCRT1X-JnQ_VrEUz1hUl--PcktWO8fw2M,6534
25
+ anydi-0.57.0.dist-info/RECORD,,
@@ -1,193 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: anydi
3
- Version: 0.55.1
4
- Summary: Dependency Injection library
5
- Keywords: dependency injection,dependencies,di,async,asyncio,application
6
- Author: Anton Ruhlov
7
- Author-email: Anton Ruhlov <antonruhlov@gmail.com>
8
- License-Expression: MIT
9
- Classifier: Intended Audience :: Information Technology
10
- Classifier: Intended Audience :: System Administrators
11
- Classifier: Operating System :: OS Independent
12
- Classifier: Development Status :: 5 - Production/Stable
13
- Classifier: Topic :: Internet
14
- Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
15
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
- Classifier: Topic :: Software Development :: Libraries
17
- Classifier: Topic :: Software Development
18
- Classifier: Typing :: Typed
19
- Classifier: Environment :: Web Environment
20
- Classifier: Intended Audience :: Developers
21
- Classifier: License :: OSI Approved :: MIT License
22
- Classifier: Programming Language :: Python :: 3
23
- Classifier: Programming Language :: Python :: 3.10
24
- Classifier: Programming Language :: Python :: 3.11
25
- Classifier: Programming Language :: Python :: 3.12
26
- Classifier: Programming Language :: Python :: 3.13
27
- Classifier: Programming Language :: Python :: 3.14
28
- Classifier: Programming Language :: Python :: 3 :: Only
29
- Requires-Dist: typing-extensions>=4.15.0,<5
30
- Requires-Dist: anyio>=3.7.1
31
- Requires-Dist: wrapt>=1.17.0,<2
32
- Requires-Python: >=3.10.0, <3.15
33
- Project-URL: Repository, https://github.com/antonrh/anydi
34
- Description-Content-Type: text/markdown
35
-
36
- # AnyDI
37
-
38
- <div style="text-align: center;">
39
-
40
- Modern, lightweight Dependency Injection library using type annotations.
41
-
42
- [![CI](https://github.com/antonrh/anydi/actions/workflows/ci.yml/badge.svg)](https://github.com/antonrh/anydi/actions/workflows/ci.yml)
43
- [![Coverage](https://codecov.io/gh/antonrh/anydi/branch/main/graph/badge.svg)](https://codecov.io/gh/antonrh/anydi)
44
- [![Documentation](https://readthedocs.org/projects/anydi/badge/?version=latest)](https://anydi.readthedocs.io/en/latest/)
45
-
46
- </div>
47
-
48
- ---
49
- Documentation
50
-
51
- http://anydi.readthedocs.io/
52
-
53
- ---
54
-
55
- `AnyDI` is a modern, lightweight Dependency Injection library suitable for any synchronous or asynchronous applications with Python 3.10+, based on type annotations ([PEP 484](https://peps.python.org/pep-0484/)).
56
-
57
- The key features are:
58
-
59
- * **Type-safe**: Resolves dependencies using type annotations.
60
- * **Async Support**: Compatible with both synchronous and asynchronous providers and injections.
61
- * **Scoping**: Supports singleton, transient, and request scopes.
62
- * **Easy to Use**: Designed for simplicity and minimal boilerplate.
63
- * **Named Dependencies**: Supports named dependencies using `Annotated` type.
64
- * **Resource Management**: Manages resources using context managers.
65
- * **Modular: Facilitates** a modular design with support for multiple modules.
66
- * **Scanning**: Automatically scans for injectable functions and classes.
67
- * **Integrations**: Provides easy integration with popular frameworks and libraries.
68
- * **Testing**: Simplifies testing by allowing provider overrides.
69
-
70
- ## Installation
71
-
72
- ```shell
73
- pip install anydi
74
- ```
75
-
76
- ## Quick Example
77
-
78
- *app.py*
79
-
80
- ```python
81
- from anydi import auto, Container
82
-
83
- container = Container()
84
-
85
-
86
- @container.provider(scope="singleton")
87
- def message() -> str:
88
- return "Hello, World!"
89
-
90
-
91
- @container.inject
92
- def say_hello(message: str = auto) -> None:
93
- print(message)
94
-
95
-
96
- if __name__ == "__main__":
97
- say_hello()
98
- ```
99
-
100
- ## FastAPI Example
101
-
102
- *app.py*
103
-
104
- ```python
105
- from typing import Annotated
106
-
107
- from fastapi import FastAPI
108
-
109
- import anydi.ext.fastapi
110
- from anydi import Container
111
- from anydi.ext.fastapi import Inject
112
-
113
- container = Container()
114
-
115
-
116
- @container.provider(scope="singleton")
117
- def message() -> str:
118
- return "Hello, World!"
119
-
120
-
121
- app = FastAPI()
122
-
123
-
124
- @app.get("/hello")
125
- def say_hello(message: Annotated[str, Inject()]) -> dict[str, str]:
126
- return {"message": message}
127
-
128
-
129
- # Install the container into the FastAPI app
130
- anydi.ext.fastapi.install(app, container)
131
- ```
132
-
133
-
134
-
135
- ## Django Ninja Example
136
-
137
- ### Install
138
-
139
- ```sh
140
- pip install 'anydi-django[ninja]'
141
- ```
142
-
143
- *container.py*
144
-
145
- ```python
146
- from anydi import Container
147
-
148
-
149
- def get_container() -> Container:
150
- container = Container()
151
-
152
- @container.provider(scope="singleton")
153
- def message() -> str:
154
- return "Hello, World!"
155
-
156
- return container
157
- ```
158
-
159
- *settings.py*
160
-
161
- ```python
162
- INSTALLED_APPS = [
163
- ...
164
- "anydi_django",
165
- ]
166
-
167
- ANYDI = {
168
- "CONTAINER_FACTORY": "myapp.container.get_container",
169
- "PATCH_NINJA": True,
170
- }
171
- ```
172
-
173
- *urls.py*
174
-
175
- ```python
176
- from django.http import HttpRequest
177
- from django.urls import path
178
- from ninja import NinjaAPI
179
-
180
- from anydi import auto
181
-
182
- api = NinjaAPI()
183
-
184
-
185
- @api.get("/hello")
186
- def say_hello(request: HttpRequest, message: str = auto) -> dict[str, str]:
187
- return {"message": message}
188
-
189
-
190
- urlpatterns = [
191
- path("api/", api.urls),
192
- ]
193
- ```
@@ -1,24 +0,0 @@
1
- anydi/__init__.py,sha256=Cz-beqReX0d05SFDmYcrzIs3FqQkWAwpy1Aqzd5db34,547
2
- anydi/_async_lock.py,sha256=3dwZr0KthXFYha0XKMyXf8jMmGb1lYoNC0O5w29V9ic,1104
3
- anydi/_container.py,sha256=6C8LM9PxMahKnu7YLMGJ50dPzYLRknZ9G9RKwyB18wE,24853
4
- anydi/_context.py,sha256=-9QqeMWo9OpZVXZxZCQgIsswggl3Ch7lgx1KiFX_ezc,3752
5
- anydi/_decorators.py,sha256=J3W261ZAG7q4XKm4tbAv1wsWr9ysx9_5MUbUvSJB_MQ,2809
6
- anydi/_module.py,sha256=2kN5uEXLd2Dsc58gz5IWK43wJewr_QgIVGSO3iWp798,2609
7
- anydi/_provider.py,sha256=OV1WFHTYv7W2U0XDk_Kql1r551Vhq8o-pUV5ep1HQcU,1574
8
- anydi/_resolver.py,sha256=olWUYp0PfsWUt7hp2MW69734T29ck6fu3s7Nk4-U7rU,25183
9
- anydi/_scanner.py,sha256=oycIC9kw9fsIG9qgtRHeBkj3HjmcLK0FTqWLXTLLSWE,3636
10
- anydi/_types.py,sha256=l3xQ0Zn15gRAwvBoQ9PRfCBigi2rrtSqGV-C50xXrLw,1780
11
- anydi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- anydi/ext/django/__init__.py,sha256=Ve8lncLU9dPY_Vjt4zihPgsSxwAtFHACn0XvBM5JG8k,367
13
- anydi/ext/fastapi.py,sha256=FflFBdK-moyv9Vsfem4NyNt8jgPwFLweeCl5cfU0Iks,2348
14
- anydi/ext/faststream.py,sha256=dJPInvi0JUx-SS8H4aBRl3u-PAW6S_TqqfxVOl3D1L0,1929
15
- anydi/ext/pydantic_settings.py,sha256=0GQjw7QpQlT5p6GxFClXYdtc6J42PClmAnRWPEzMjvY,1488
16
- anydi/ext/pytest_plugin.py,sha256=Es1K1S6_2gIdTUYkbw2d1aZcHnjJutGFafVsLPGcVJc,4684
17
- anydi/ext/starlette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- anydi/ext/starlette/middleware.py,sha256=MxnzshAs-CMvjJp0r457k52MzBL8O4KAuClnF6exBdU,803
19
- anydi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- anydi/testing.py,sha256=JNXA-XGjkU7PMturkzDzumDcLlnYOLzCtBUQ9HyQMLM,4309
21
- anydi-0.55.1.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
22
- anydi-0.55.1.dist-info/entry_points.txt,sha256=AgOcQYM5KyS4D37QcYb00tiid0QA-pD1VrjHHq4QAps,44
23
- anydi-0.55.1.dist-info/METADATA,sha256=TEL8yqko7Et9BJW8uiUq8r-Hjjj5PcYYXBS91eHTuPE,4799
24
- anydi-0.55.1.dist-info/RECORD,,
File without changes