Name | deps-injection JSON |
Version |
1.7.1
JSON |
| download |
home_page | None |
Summary | Easy dependency injection without wiring |
upload_time | 2024-12-29 19:16:16 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.8 |
license | MIT |
keywords |
dependency
di
injection
injector
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Injection
![PyPI - Version](https://img.shields.io/pypi/v/deps-injection?label=pypi%20version&color=012111012)
![GitHub License](https://img.shields.io/github/license/nightblure/injection?color=012111012)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/deps-injection)
[![Latest Release](https://github.com/nightblure/injection/actions/workflows/publish.yml/badge.svg)](https://github.com/nightblure/injection/actions/workflows/publish.yml)
[![Documentation Status](https://readthedocs.org/projects/injection/badge/?version=latest)](https://injection.readthedocs.io/en/latest/?badge=latest)
[![Tests And Linting](https://github.com/nightblure/injection/actions/workflows/ci.yml/badge.svg)](https://github.com/nightblure/injection/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/nightblure/injection/graph/badge.svg?token=2ZTFBlJqTb)](https://codecov.io/gh/nightblure/injection)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)
[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
[![MyPy Strict](https://img.shields.io/badge/mypy-strict-blue)](https://mypy.readthedocs.io/en/stable/getting_started.html#strict-mode-and-configuration)
[![Maintainability](https://api.codeclimate.com/v1/badges/1da49eb0b28eacae4624/maintainability)](https://codeclimate.com/github/nightblure/injection/maintainability)
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/nightblure/injection/total?color=102255102&label=Total%20downloads)
![PyPI - Month Downloads](https://img.shields.io/pypi/dm/deps-injection?color=102255102&label=Month%20downloads)
![GitHub Repo stars](https://img.shields.io/github/stars/nightblure/injection)
---
Easy dependency injection for all, works with Python 3.8-3.13. Main features and advantages:
* support **Python 3.8-3.13**;
* works with **FastAPI, **Litestar**, Flask** and **Django REST Framework**;
* support **dependency** **injection** via `Annotated` in `FastAPI`;
* support **async injections**;
* support [**auto injection by types**](https://injection.readthedocs.io/latest/injection/auto_injection.html);
* [**resources**](https://injection.readthedocs.io/latest/providers/resource.html) with **function scope**;
* no **wiring**;
* **overriding** dependencies for testing;
* **100%** code coverage;
* the code is fully **typed** and checked with [mypy](https://github.com/python/mypy);
* good [documentation](https://injection.readthedocs.io/latest/);
* intuitive and almost identical api with [dependency-injector](https://github.com/ets-labs/python-dependency-injector),
which will allow you to easily migrate to injection
(see [migration from dependency injector](https://injection.readthedocs.io/latest/dev/migration-from-dependency-injector.html));
---
## Installation
```shell
pip install deps-injection
```
## Compatibility between web frameworks and injection features
| Framework | Dependency injection with @inject | Overriding providers | Dependency injection with @autoinject |
|--------------------------------------------------------------------------|:---------------------------------:|:--------------------:|:-------------------------------------------:|
| [FastAPI](https://github.com/fastapi/fastapi) | ✅ | ✅ | ➖ |
| [Flask](https://github.com/pallets/flask) | ✅ | ✅ | ✅ |
| [Django REST Framework](https://github.com/encode/django-rest-framework) | ✅ | ✅ | ✅ |
| [Litestar](https://github.com/litestar-org/litestar) | ✅ | ✅ | ➖ | ➖ |
## Quickstart with FastAPI, SQLAlchemy and pytest
```python3
from contextlib import contextmanager
from random import Random
from typing import Annotated, Any, Callable, Dict, Iterator
import pytest
from fastapi import Depends, FastAPI
from sqlalchemy import create_engine, text
from sqlalchemy.orm import Session, sessionmaker
from starlette.testclient import TestClient
from injection import DeclarativeContainer, Provide, inject, providers
@contextmanager
def db_session_resource(session_factory: Callable[..., Session]) -> Iterator[Session]:
session = session_factory()
try:
yield session
except Exception:
session.rollback()
finally:
session.close()
class SomeDAO:
def __init__(self, db_session: Session) -> None:
self.db_session = db_session
def get_some_data(self, num: int) -> int:
stmt = text("SELECT :num").bindparams(num=num)
data: int = self.db_session.execute(stmt).scalar_one()
return data
class DIContainer(DeclarativeContainer):
db_engine = providers.Singleton(
create_engine,
url="sqlite:///db.db",
pool_size=20,
max_overflow=0,
pool_pre_ping=False,
)
session_factory = providers.Singleton(
sessionmaker,
db_engine.cast,
autoflush=False,
autocommit=False,
)
db_session = providers.Resource(
db_session_resource,
session_factory=session_factory.cast,
function_scope=True,
)
some_dao = providers.Factory(SomeDAO, db_session=db_session.cast)
SomeDAODependency = Annotated[SomeDAO, Depends(Provide[DIContainer.some_dao])]
app = FastAPI()
@app.get("/values/{value}")
@inject
async def sqla_resource_handler_async(
value: int,
some_dao: SomeDAODependency,
) -> Dict[str, Any]:
value = some_dao.get_some_data(num=value)
return {"detail": value}
@pytest.fixture(scope="session")
def test_client() -> TestClient:
client = TestClient(app)
return client
def test_sqla_resource(test_client: TestClient) -> None:
rnd = Random()
random_int = rnd.randint(-(10**6), 10**6)
response = test_client.get(f"/values/{random_int}")
assert response.status_code == 200
assert not DIContainer.db_session.initialized
body = response.json()
assert body["detail"] == random_int
```
Raw data
{
"_id": null,
"home_page": null,
"name": "deps-injection",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "dependency, di, injection, injector",
"author": null,
"author_email": "Ivan Belyaev <vanobel159@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/25/07/880b6cc675fb0ee600f9dfa4dc74459eb7656a5e080dc05d809c35051cd6/deps_injection-1.7.1.tar.gz",
"platform": null,
"description": "# Injection\n\n![PyPI - Version](https://img.shields.io/pypi/v/deps-injection?label=pypi%20version&color=012111012)\n![GitHub License](https://img.shields.io/github/license/nightblure/injection?color=012111012)\n\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/deps-injection)\n\n[![Latest Release](https://github.com/nightblure/injection/actions/workflows/publish.yml/badge.svg)](https://github.com/nightblure/injection/actions/workflows/publish.yml)\n[![Documentation Status](https://readthedocs.org/projects/injection/badge/?version=latest)](https://injection.readthedocs.io/en/latest/?badge=latest)\n\n[![Tests And Linting](https://github.com/nightblure/injection/actions/workflows/ci.yml/badge.svg)](https://github.com/nightblure/injection/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/nightblure/injection/graph/badge.svg?token=2ZTFBlJqTb)](https://codecov.io/gh/nightblure/injection)\n\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)\n[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)\n[![MyPy Strict](https://img.shields.io/badge/mypy-strict-blue)](https://mypy.readthedocs.io/en/stable/getting_started.html#strict-mode-and-configuration)\n\n[![Maintainability](https://api.codeclimate.com/v1/badges/1da49eb0b28eacae4624/maintainability)](https://codeclimate.com/github/nightblure/injection/maintainability)\n![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/nightblure/injection/total?color=102255102&label=Total%20downloads)\n\n![PyPI - Month Downloads](https://img.shields.io/pypi/dm/deps-injection?color=102255102&label=Month%20downloads)\n![GitHub Repo stars](https://img.shields.io/github/stars/nightblure/injection)\n\n---\n\nEasy dependency injection for all, works with Python 3.8-3.13. Main features and advantages:\n* support **Python 3.8-3.13**;\n* works with **FastAPI, **Litestar**, Flask** and **Django REST Framework**;\n* support **dependency** **injection** via `Annotated` in `FastAPI`;\n* support **async injections**;\n* support [**auto injection by types**](https://injection.readthedocs.io/latest/injection/auto_injection.html); \n* [**resources**](https://injection.readthedocs.io/latest/providers/resource.html) with **function scope**;\n* no **wiring**;\n* **overriding** dependencies for testing;\n* **100%** code coverage;\n* the code is fully **typed** and checked with [mypy](https://github.com/python/mypy);\n* good [documentation](https://injection.readthedocs.io/latest/);\n* intuitive and almost identical api with [dependency-injector](https://github.com/ets-labs/python-dependency-injector),\nwhich will allow you to easily migrate to injection\n(see [migration from dependency injector](https://injection.readthedocs.io/latest/dev/migration-from-dependency-injector.html));\n\n---\n\n## Installation\n```shell\npip install deps-injection\n```\n\n## Compatibility between web frameworks and injection features\n| Framework | Dependency injection with @inject | Overriding providers | Dependency injection with @autoinject |\n|--------------------------------------------------------------------------|:---------------------------------:|:--------------------:|:-------------------------------------------:|\n| [FastAPI](https://github.com/fastapi/fastapi) | \u2705 | \u2705 | \u2796 |\n| [Flask](https://github.com/pallets/flask) | \u2705 | \u2705 | \u2705 |\n| [Django REST Framework](https://github.com/encode/django-rest-framework) | \u2705 | \u2705 | \u2705 |\n| [Litestar](https://github.com/litestar-org/litestar) | \u2705 | \u2705 | \u2796 | \u2796 |\n\n\n## Quickstart with FastAPI, SQLAlchemy and pytest\n```python3\nfrom contextlib import contextmanager\nfrom random import Random\nfrom typing import Annotated, Any, Callable, Dict, Iterator\n\nimport pytest\nfrom fastapi import Depends, FastAPI\nfrom sqlalchemy import create_engine, text\nfrom sqlalchemy.orm import Session, sessionmaker\nfrom starlette.testclient import TestClient\n\nfrom injection import DeclarativeContainer, Provide, inject, providers\n\n\n@contextmanager\ndef db_session_resource(session_factory: Callable[..., Session]) -> Iterator[Session]:\n session = session_factory()\n try:\n yield session\n except Exception:\n session.rollback()\n finally:\n session.close()\n\n\nclass SomeDAO:\n def __init__(self, db_session: Session) -> None:\n self.db_session = db_session\n\n def get_some_data(self, num: int) -> int:\n stmt = text(\"SELECT :num\").bindparams(num=num)\n data: int = self.db_session.execute(stmt).scalar_one()\n return data\n\n\nclass DIContainer(DeclarativeContainer):\n db_engine = providers.Singleton(\n create_engine,\n url=\"sqlite:///db.db\",\n pool_size=20,\n max_overflow=0,\n pool_pre_ping=False,\n )\n\n session_factory = providers.Singleton(\n sessionmaker,\n db_engine.cast,\n autoflush=False,\n autocommit=False,\n )\n\n db_session = providers.Resource(\n db_session_resource,\n session_factory=session_factory.cast,\n function_scope=True,\n )\n\n some_dao = providers.Factory(SomeDAO, db_session=db_session.cast)\n\n\nSomeDAODependency = Annotated[SomeDAO, Depends(Provide[DIContainer.some_dao])]\n\napp = FastAPI()\n\n\n@app.get(\"/values/{value}\")\n@inject\nasync def sqla_resource_handler_async(\n value: int,\n some_dao: SomeDAODependency,\n) -> Dict[str, Any]:\n value = some_dao.get_some_data(num=value)\n return {\"detail\": value}\n\n\n@pytest.fixture(scope=\"session\")\ndef test_client() -> TestClient:\n client = TestClient(app)\n return client\n\n\ndef test_sqla_resource(test_client: TestClient) -> None:\n rnd = Random()\n random_int = rnd.randint(-(10**6), 10**6)\n\n response = test_client.get(f\"/values/{random_int}\")\n\n assert response.status_code == 200\n assert not DIContainer.db_session.initialized\n body = response.json()\n assert body[\"detail\"] == random_int\n \n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Easy dependency injection without wiring",
"version": "1.7.1",
"project_urls": {
"Changelog": "https://github.com/nightblure/injection/releases",
"Documentation": "https://injection.readthedocs.io/latest/",
"Homepage": "https://pypi.org/project/deps-injection/",
"Issues": "https://github.com/nightblure/injection/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc",
"Repository": "https://github.com/nightblure/injection.git"
},
"split_keywords": [
"dependency",
" di",
" injection",
" injector"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "a84bde5f48001d089b0cc48f06f0c715969d9b07d62f3bbd1ac6ed10c0a18ed2",
"md5": "ae6d09b9a0ef0b2eed8b325cb15937ca",
"sha256": "a3e62c79e44ad5e291ea5c47e84c2778787f96143d85fa440a4f05c119cd4f3e"
},
"downloads": -1,
"filename": "deps_injection-1.7.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ae6d09b9a0ef0b2eed8b325cb15937ca",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 16719,
"upload_time": "2024-12-29T19:16:14",
"upload_time_iso_8601": "2024-12-29T19:16:14.307697Z",
"url": "https://files.pythonhosted.org/packages/a8/4b/de5f48001d089b0cc48f06f0c715969d9b07d62f3bbd1ac6ed10c0a18ed2/deps_injection-1.7.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2507880b6cc675fb0ee600f9dfa4dc74459eb7656a5e080dc05d809c35051cd6",
"md5": "7714eb0a065cabfa6e1bf2f8e3047a17",
"sha256": "4cf75ecd122b7eb9c7509d2ae6098cd1a9e38d8c10bad15e2201049ccce32935"
},
"downloads": -1,
"filename": "deps_injection-1.7.1.tar.gz",
"has_sig": false,
"md5_digest": "7714eb0a065cabfa6e1bf2f8e3047a17",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 12646,
"upload_time": "2024-12-29T19:16:16",
"upload_time_iso_8601": "2024-12-29T19:16:16.988942Z",
"url": "https://files.pythonhosted.org/packages/25/07/880b6cc675fb0ee600f9dfa4dc74459eb7656a5e080dc05d809c35051cd6/deps_injection-1.7.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-29 19:16:16",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "nightblure",
"github_project": "injection",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "deps-injection"
}