anydi 0.22.0__tar.gz → 0.37.4__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 (99) hide show
  1. anydi-0.37.4/.editorconfig +26 -0
  2. anydi-0.37.4/.github/workflows/ci.yml +60 -0
  3. anydi-0.37.4/.gitignore +83 -0
  4. anydi-0.37.4/.readthedocs.yml +15 -0
  5. anydi-0.37.4/Makefile +18 -0
  6. {anydi-0.22.0 → anydi-0.37.4}/PKG-INFO +71 -24
  7. {anydi-0.22.0 → anydi-0.37.4}/README.md +59 -6
  8. anydi-0.37.4/anydi/__init__.py +32 -0
  9. anydi-0.37.4/anydi/_container.py +1071 -0
  10. anydi-0.37.4/anydi/_context.py +84 -0
  11. anydi-0.37.4/anydi/_provider.py +232 -0
  12. anydi-0.37.4/anydi/_types.py +68 -0
  13. anydi-0.37.4/anydi/_utils.py +142 -0
  14. anydi-0.37.4/anydi/ext/_utils.py +83 -0
  15. anydi-0.37.4/anydi/ext/django/__init__.py +9 -0
  16. anydi-0.37.4/anydi/ext/django/_container.py +18 -0
  17. anydi-0.37.4/anydi/ext/django/_settings.py +39 -0
  18. anydi-0.37.4/anydi/ext/django/_utils.py +128 -0
  19. anydi-0.37.4/anydi/ext/django/apps.py +85 -0
  20. anydi-0.37.4/anydi/ext/django/middleware.py +28 -0
  21. anydi-0.37.4/anydi/ext/django/ninja/__init__.py +16 -0
  22. anydi-0.37.4/anydi/ext/django/ninja/_operation.py +75 -0
  23. anydi-0.37.4/anydi/ext/django/ninja/_signature.py +64 -0
  24. {anydi-0.22.0 → anydi-0.37.4}/anydi/ext/fastapi.py +11 -27
  25. anydi-0.37.4/anydi/ext/faststream.py +58 -0
  26. anydi-0.37.4/anydi/ext/pydantic_settings.py +48 -0
  27. anydi-0.37.4/anydi/ext/pytest_plugin.py +158 -0
  28. {anydi-0.22.0 → anydi-0.37.4}/anydi/ext/starlette/middleware.py +2 -16
  29. anydi-0.37.4/docs/examples/basic.md +184 -0
  30. anydi-0.37.4/docs/extensions/django.md +172 -0
  31. anydi-0.37.4/docs/extensions/fastapi.md +193 -0
  32. anydi-0.37.4/docs/extensions/faststream.md +45 -0
  33. anydi-0.37.4/docs/extensions/pydantic_settings.md +45 -0
  34. anydi-0.37.4/docs/index.md +152 -0
  35. anydi-0.37.4/docs/usage.md +825 -0
  36. anydi-0.37.4/mkdocs.yml +38 -0
  37. {anydi-0.22.0 → anydi-0.37.4}/pyproject.toml +66 -33
  38. anydi-0.37.4/tests/__init__.py +0 -0
  39. anydi-0.37.4/tests/conftest.py +6 -0
  40. anydi-0.37.4/tests/ext/__init__.py +0 -0
  41. anydi-0.37.4/tests/ext/django/__init__.py +0 -0
  42. anydi-0.37.4/tests/ext/django/api/__init__.py +0 -0
  43. anydi-0.37.4/tests/ext/django/api/router.py +30 -0
  44. anydi-0.37.4/tests/ext/django/api/test_router.py +15 -0
  45. anydi-0.37.4/tests/ext/django/api/urls.py +11 -0
  46. anydi-0.37.4/tests/ext/django/conftest.py +12 -0
  47. anydi-0.37.4/tests/ext/django/container.py +26 -0
  48. anydi-0.37.4/tests/ext/django/scan/__init__.py +0 -0
  49. anydi-0.37.4/tests/ext/django/services.py +28 -0
  50. anydi-0.37.4/tests/ext/django/settings.py +22 -0
  51. anydi-0.37.4/tests/ext/django/test_views.py +50 -0
  52. anydi-0.37.4/tests/ext/django/urls.py +18 -0
  53. anydi-0.37.4/tests/ext/django/views.py +40 -0
  54. anydi-0.37.4/tests/ext/fastapi/__init__.py +0 -0
  55. anydi-0.37.4/tests/ext/fastapi/app.py +86 -0
  56. anydi-0.37.4/tests/ext/fastapi/conftest.py +24 -0
  57. anydi-0.37.4/tests/ext/fastapi/test_auto_register.py +34 -0
  58. anydi-0.37.4/tests/ext/fastapi/test_ext.py +57 -0
  59. anydi-0.37.4/tests/ext/fastapi/test_routes.py +76 -0
  60. anydi-0.37.4/tests/ext/faststream/__init__.py +0 -0
  61. anydi-0.37.4/tests/ext/faststream/test_ext.py +57 -0
  62. anydi-0.37.4/tests/ext/faststream/test_subscribers.py +54 -0
  63. anydi-0.37.4/tests/ext/fixtures.py +36 -0
  64. anydi-0.37.4/tests/ext/starlette/__init__.py +0 -0
  65. anydi-0.37.4/tests/ext/starlette/app.py +52 -0
  66. anydi-0.37.4/tests/ext/starlette/conftest.py +24 -0
  67. anydi-0.37.4/tests/ext/starlette/test_routes.py +52 -0
  68. anydi-0.37.4/tests/ext/test_pydantic.py +43 -0
  69. anydi-0.37.4/tests/ext/test_pytest_plugin.py +72 -0
  70. anydi-0.37.4/tests/fixtures.py +36 -0
  71. anydi-0.37.4/tests/scan_app/__init__.py +17 -0
  72. anydi-0.37.4/tests/scan_app/a/__init__.py +0 -0
  73. anydi-0.37.4/tests/scan_app/a/a1/__init__.py +2 -0
  74. anydi-0.37.4/tests/scan_app/a/a1/handlers.py +6 -0
  75. anydi-0.37.4/tests/scan_app/a/a2/__init__.py +0 -0
  76. anydi-0.37.4/tests/scan_app/a/a2/a21/__init__.py +0 -0
  77. anydi-0.37.4/tests/scan_app/a/a2/a21/handlers.py +6 -0
  78. anydi-0.37.4/tests/scan_app/a/a3/__init__.py +0 -0
  79. anydi-0.37.4/tests/scan_app/a/a3/handlers.py +12 -0
  80. anydi-0.37.4/tests/scan_app/b/__init__.py +0 -0
  81. anydi-0.37.4/tests/scan_app/b/handlers.py +20 -0
  82. anydi-0.37.4/tests/test_container.py +1771 -0
  83. anydi-0.37.4/tests/test_provider.py +177 -0
  84. anydi-0.37.4/tests/test_utils.py +71 -0
  85. anydi-0.37.4/uv.lock +1471 -0
  86. anydi-0.22.0/anydi/__init__.py +0 -32
  87. anydi-0.22.0/anydi/_container.py +0 -831
  88. anydi-0.22.0/anydi/_context.py +0 -326
  89. anydi-0.22.0/anydi/_logger.py +0 -3
  90. anydi-0.22.0/anydi/_module.py +0 -124
  91. anydi-0.22.0/anydi/_scanner.py +0 -233
  92. anydi-0.22.0/anydi/_types.py +0 -115
  93. anydi-0.22.0/anydi/_utils.py +0 -111
  94. anydi-0.22.0/anydi/ext/_utils.py +0 -62
  95. anydi-0.22.0/anydi/ext/pytest_plugin.py +0 -132
  96. {anydi-0.22.0 → anydi-0.37.4}/LICENSE +0 -0
  97. {anydi-0.22.0 → anydi-0.37.4}/anydi/ext/__init__.py +0 -0
  98. {anydi-0.22.0 → anydi-0.37.4}/anydi/ext/starlette/__init__.py +0 -0
  99. {anydi-0.22.0 → anydi-0.37.4}/anydi/py.typed +0 -0
@@ -0,0 +1,26 @@
1
+ # https://editorconfig.org/
2
+
3
+ root = true
4
+
5
+ [*]
6
+ indent_style = space
7
+ indent_size = 4
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+ end_of_line = lf
11
+ charset = utf-8
12
+
13
+ # Docstrings and comments use max_line_length = 88
14
+ [*.py]
15
+ max_line_length = 88
16
+
17
+ [Makefile]
18
+ indent_style = tab
19
+
20
+ # Use 2 spaces for the HTML files
21
+ [*.html]
22
+ indent_size = 2
23
+
24
+ # The JSON/YAML files contain newlines inconsistently
25
+ [*.{json,yml,yaml}]
26
+ indent_size = 2
@@ -0,0 +1,60 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ lint:
13
+ name: Code quality
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v4
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v5
20
+ with:
21
+ enable-cache: true
22
+ - name: Set up Python
23
+ run: uv python install
24
+ - name: Install dependencies
25
+ run: uv sync --all-extras --dev
26
+ - name: Static type checking
27
+ run: uv run mypy anydi tests
28
+ - name: Code formatting
29
+ run: uv run ruff check anydi tests && uv run ruff format anydi tests --check
30
+
31
+ tests:
32
+ name: Run unit tests ${{ matrix.name }}
33
+ runs-on: ${{ matrix.os }}
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ include:
38
+ - {name: '3.13', python: '3.13', os: ubuntu-latest}
39
+ - {name: '3.12', python: '3.12', os: ubuntu-latest}
40
+ - {name: '3.11', python: '3.11', os: ubuntu-latest}
41
+ - {name: '3.10', python: '3.10', os: ubuntu-latest}
42
+ - {name: '3.9', python: '3.9', os: ubuntu-latest}
43
+
44
+ steps:
45
+ - name: Checkout
46
+ uses: actions/checkout@v4
47
+ - name: Install uv and set the python version
48
+ uses: astral-sh/setup-uv@v5
49
+ with:
50
+ python-version: ${{ matrix.python-version }}
51
+ enable-cache: true
52
+ - name: Install dependencies
53
+ run: uv sync --all-extras --dev
54
+ - name: Run tests
55
+ run: |
56
+ uv run pytest -vv tests --ignore=tests/ext/test_pytest_plugin.py --cov=anydi -p no:anydi
57
+ uv run pytest -vv tests/ext/test_pytest_plugin.py --cov=anydi --cov-append --cov-report=xml
58
+ - name: Upload coverage to Codecov
59
+ uses: codecov/codecov-action@v3
60
+ if: matrix.python == '3.9'
@@ -0,0 +1,83 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .pytest_cache
6
+ .mypy_cache
7
+ .ruff_cache
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ env/
15
+ .venv
16
+ build/
17
+ develop-eggs/
18
+ dist/
19
+ downloads/
20
+ eggs/
21
+ .eggs/
22
+ lib/
23
+ lib64/
24
+ parts/
25
+ sdist/
26
+ var/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *,cover
50
+ .hypothesis/
51
+ pyunit.xml
52
+
53
+ # Translations
54
+ *.mo
55
+ *.pot
56
+
57
+ # Django stuff:
58
+ *.log
59
+
60
+ # Sphinx documentation
61
+ docs/_build/
62
+
63
+ # PyBuilder
64
+ target/
65
+
66
+ #Ipython Notebook
67
+ .ipynb_checkpoints
68
+ *.ipynb
69
+
70
+ # OS-X thumbnails
71
+ .DS_Store
72
+
73
+ # vi swap files
74
+ *.swp
75
+
76
+ # PyCharm project settings
77
+ .idea
78
+
79
+ # dotenv file
80
+ .env
81
+
82
+
83
+ /app
@@ -0,0 +1,15 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-20.04
5
+ tools:
6
+ python: "3.10"
7
+ jobs:
8
+ post_create_environment:
9
+ - pip install poetry
10
+ - poetry config virtualenvs.create false
11
+ post_install:
12
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install -E docs
13
+
14
+ mkdocs:
15
+ configuration: mkdocs.yml
anydi-0.37.4/Makefile ADDED
@@ -0,0 +1,18 @@
1
+ .PHONY: help lint fmt test
2
+ .DEFAULT_GOAL := help
3
+
4
+ help:
5
+ @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
6
+
7
+ lint: ## Run code linters
8
+ uv run mypy anydi tests
9
+ uv run ruff check anydi tests
10
+ uv run ruff format anydi tests --check
11
+
12
+ fmt: ## Run code formatters
13
+ uv run ruff check anydi tests --fix
14
+ uv run ruff format anydi tests
15
+
16
+ test: ## Run unit tests
17
+ uv run pytest -vv tests --ignore=tests/ext/test_pytest_plugin.py --cov=anydi -p no:anydi -p no:testanydi
18
+ uv run pytest -vv tests/ext/test_pytest_plugin.py --cov=anydi --cov-append
@@ -1,13 +1,12 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: anydi
3
- Version: 0.22.0
3
+ Version: 0.37.4
4
4
  Summary: Dependency Injection library
5
- Home-page: https://github.com/antonrh/anydi
6
- License: MIT
7
- Keywords: dependency injection,dependencies,di,async,asyncio,application
8
- Author: Anton Ruhlov
9
- Author-email: antonruhlov@gmail.com
10
- Requires-Python: >=3.8,<4.0
5
+ Project-URL: Repository, https://github.com/antonrh/anydi
6
+ Author-email: Anton Ruhlov <antonruhlov@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Keywords: application,async,asyncio,dependencies,dependency injection,di
11
10
  Classifier: Development Status :: 5 - Production/Stable
12
11
  Classifier: Environment :: Web Environment
13
12
  Classifier: Intended Audience :: Developers
@@ -16,26 +15,22 @@ Classifier: Intended Audience :: System Administrators
16
15
  Classifier: License :: OSI Approved :: MIT License
17
16
  Classifier: Operating System :: OS Independent
18
17
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3 :: Only
20
19
  Classifier: Programming Language :: Python :: 3.9
21
20
  Classifier: Programming Language :: Python :: 3.10
22
21
  Classifier: Programming Language :: Python :: 3.11
23
22
  Classifier: Programming Language :: Python :: 3.12
24
- Classifier: Programming Language :: Python :: 3 :: Only
25
- Classifier: Programming Language :: Python :: 3.7
23
+ Classifier: Programming Language :: Python :: 3.13
26
24
  Classifier: Topic :: Internet
27
25
  Classifier: Topic :: Software Development
28
26
  Classifier: Topic :: Software Development :: Libraries
29
27
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
30
28
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
29
  Classifier: Typing :: Typed
32
- Provides-Extra: async
33
- Provides-Extra: docs
34
- Requires-Dist: anyio (>=3.6.2,<4.0.0) ; extra == "async"
35
- Requires-Dist: mkdocs (>=1.4.2,<2.0.0) ; extra == "docs"
36
- Requires-Dist: mkdocs-material (>=9.1.13,<10.0.0) ; extra == "docs"
37
- Requires-Dist: typing-extensions (>=4.8.0,<5.0.0)
38
- Project-URL: Repository, https://github.com/antonrh/anydi
30
+ Requires-Python: ~=3.9
31
+ Requires-Dist: anyio>=3.7.1
32
+ Requires-Dist: typing-extensions<5,>=4.12.1
33
+ Requires-Dist: wrapt<2,>=1.17.0
39
34
  Description-Content-Type: text/markdown
40
35
 
41
36
  # AnyDI
@@ -56,9 +51,6 @@ Description-Content-Type: text/markdown
56
51
  </a>
57
52
  </p>
58
53
 
59
- > [!IMPORTANT]
60
- > Library renamed to `anydi` from `pyxdi` starting from version `0.19.0`.
61
-
62
54
  ---
63
55
  Documentation
64
56
 
@@ -66,7 +58,7 @@ http://anydi.readthedocs.io/
66
58
 
67
59
  ---
68
60
 
69
- `AnyDI` is a modern, lightweight Dependency Injection library suitable for any synchronous or asynchronous applications with Python 3.8+, based on type annotations ([PEP 484](https://peps.python.org/pep-0484/)).
61
+ `AnyDI` is a modern, lightweight Dependency Injection library suitable for any synchronous or asynchronous applications with Python 3.9+, based on type annotations ([PEP 484](https://peps.python.org/pep-0484/)).
70
62
 
71
63
  The key features are:
72
64
 
@@ -92,7 +84,7 @@ pip install anydi
92
84
  *app.py*
93
85
 
94
86
  ```python
95
- from anydi import Container, dep
87
+ from anydi import auto, Container
96
88
 
97
89
  container = Container()
98
90
 
@@ -103,7 +95,7 @@ def message() -> str:
103
95
 
104
96
 
105
97
  @container.inject
106
- def say_hello(message: str = dep()) -> None:
98
+ def say_hello(message: str = auto) -> None:
107
99
  print(message)
108
100
 
109
101
 
@@ -142,3 +134,58 @@ def say_hello(message: str = Inject()) -> dict[str, str]:
142
134
  anydi.ext.fastapi.install(app, container)
143
135
  ```
144
136
 
137
+
138
+
139
+ ## Django Ninja Example
140
+
141
+ *container.py*
142
+
143
+ ```python
144
+ from anydi import Container
145
+
146
+
147
+ def get_container() -> Container:
148
+ container = Container()
149
+
150
+ @container.provider(scope="singleton")
151
+ def message() -> str:
152
+ return "Hello, World!"
153
+
154
+ return container
155
+ ```
156
+
157
+ *settings.py*
158
+
159
+ ```python
160
+ INSTALLED_APPS = [
161
+ ...
162
+ "anydi.ext.django",
163
+ ]
164
+
165
+ ANYDI = {
166
+ "CONTAINER_FACTORY": "myapp.container.get_container",
167
+ "PATCH_NINJA": True,
168
+ }
169
+ ```
170
+
171
+ *urls.py*
172
+
173
+ ```python
174
+ from django.http import HttpRequest
175
+ from django.urls import path
176
+ from ninja import NinjaAPI
177
+
178
+ from anydi import auto
179
+
180
+ api = NinjaAPI()
181
+
182
+
183
+ @api.get("/hello")
184
+ def say_hello(request: HttpRequest, message: str = auto) -> dict[str, str]:
185
+ return {"message": message}
186
+
187
+
188
+ urlpatterns = [
189
+ path("api/", api.urls),
190
+ ]
191
+ ```
@@ -16,9 +16,6 @@
16
16
  </a>
17
17
  </p>
18
18
 
19
- > [!IMPORTANT]
20
- > Library renamed to `anydi` from `pyxdi` starting from version `0.19.0`.
21
-
22
19
  ---
23
20
  Documentation
24
21
 
@@ -26,7 +23,7 @@ http://anydi.readthedocs.io/
26
23
 
27
24
  ---
28
25
 
29
- `AnyDI` is a modern, lightweight Dependency Injection library suitable for any synchronous or asynchronous applications with Python 3.8+, based on type annotations ([PEP 484](https://peps.python.org/pep-0484/)).
26
+ `AnyDI` is a modern, lightweight Dependency Injection library suitable for any synchronous or asynchronous applications with Python 3.9+, based on type annotations ([PEP 484](https://peps.python.org/pep-0484/)).
30
27
 
31
28
  The key features are:
32
29
 
@@ -52,7 +49,7 @@ pip install anydi
52
49
  *app.py*
53
50
 
54
51
  ```python
55
- from anydi import Container, dep
52
+ from anydi import auto, Container
56
53
 
57
54
  container = Container()
58
55
 
@@ -63,7 +60,7 @@ def message() -> str:
63
60
 
64
61
 
65
62
  @container.inject
66
- def say_hello(message: str = dep()) -> None:
63
+ def say_hello(message: str = auto) -> None:
67
64
  print(message)
68
65
 
69
66
 
@@ -101,3 +98,59 @@ def say_hello(message: str = Inject()) -> dict[str, str]:
101
98
  # Install the container into the FastAPI app
102
99
  anydi.ext.fastapi.install(app, container)
103
100
  ```
101
+
102
+
103
+
104
+ ## Django Ninja Example
105
+
106
+ *container.py*
107
+
108
+ ```python
109
+ from anydi import Container
110
+
111
+
112
+ def get_container() -> Container:
113
+ container = Container()
114
+
115
+ @container.provider(scope="singleton")
116
+ def message() -> str:
117
+ return "Hello, World!"
118
+
119
+ return container
120
+ ```
121
+
122
+ *settings.py*
123
+
124
+ ```python
125
+ INSTALLED_APPS = [
126
+ ...
127
+ "anydi.ext.django",
128
+ ]
129
+
130
+ ANYDI = {
131
+ "CONTAINER_FACTORY": "myapp.container.get_container",
132
+ "PATCH_NINJA": True,
133
+ }
134
+ ```
135
+
136
+ *urls.py*
137
+
138
+ ```python
139
+ from django.http import HttpRequest
140
+ from django.urls import path
141
+ from ninja import NinjaAPI
142
+
143
+ from anydi import auto
144
+
145
+ api = NinjaAPI()
146
+
147
+
148
+ @api.get("/hello")
149
+ def say_hello(request: HttpRequest, message: str = auto) -> dict[str, str]:
150
+ return {"message": message}
151
+
152
+
153
+ urlpatterns = [
154
+ path("api/", api.urls),
155
+ ]
156
+ ```
@@ -0,0 +1,32 @@
1
+ """AnyDI public objects and functions."""
2
+
3
+ from typing import Any, cast
4
+
5
+ from ._container import (
6
+ Container,
7
+ Module,
8
+ injectable,
9
+ provider,
10
+ request,
11
+ singleton,
12
+ transient,
13
+ )
14
+ from ._provider import Provider
15
+ from ._types import Marker, Scope
16
+
17
+ # Alias for dependency auto marker
18
+ auto = cast(Any, Marker())
19
+
20
+
21
+ __all__ = [
22
+ "Container",
23
+ "Module",
24
+ "Provider",
25
+ "Scope",
26
+ "auto",
27
+ "injectable",
28
+ "provider",
29
+ "request",
30
+ "singleton",
31
+ "transient",
32
+ ]