A modern, type-safe Dependency Injection framework for Python with support for async/await and context managers.
Project description
spritze
A modern, type-safe Dependency Injection framework for Python with support for async/await and context managers.
Features
- Type Safety: Full support for Python 3.11+ type hints with
AnnotatedandDepends - Scopes: APP (singleton) and REQUEST (per-request) scoping
- Async Support: Native async/await support for providers and injection
- Context Managers: Automatic lifecycle management with generators and async generators
- Framework Agnostic: Easy integration with Flask, FastAPI, Litestar, Django, and more
- No Globals: Explicit containers with per-request context management
- Clean Architecture: Follows Domain-Driven Design principles
Installation
uv add spritze
# or
pip install spritze
Quick Start
Basic Usage
from typing import Annotated
from spritze import Container, Scope, provider, Depends, init, inject
class DatabaseConfig:
def __init__(self, url: str) -> None:
self.url: str = url
class DatabaseConnection:
def __init__(self, config: DatabaseConfig) -> None:
self.config: DatabaseConfig = config
def query(self, sql: str) -> str:
return f"Executed: {sql} on {self.config.url}"
class UserService:
def __init__(self, db: DatabaseConnection) -> None:
self.db: DatabaseConnection = db
def get_user(self, user_id: int) -> str:
return self.db.query(f"SELECT * FROM users WHERE id = {user_id}")
class AppContainer(Container):
@provider(scope=Scope.APP)
def config(self) -> DatabaseConfig:
return DatabaseConfig("postgresql://localhost/db")
@provider(scope=Scope.REQUEST)
def database(self, config: DatabaseConfig) -> DatabaseConnection:
return DatabaseConnection(config)
@provider(scope=Scope.REQUEST)
def user_service(self, db: DatabaseConnection) -> UserService:
return UserService(db)
# Initialize container
container = AppContainer()
init(container)
@inject
def get_user_handler(
user_id: int,
service: Annotated[UserService, Depends()]
) -> str:
return service.get_user(user_id)
if __name__ == "__main__":
result = get_user_handler(123)
print(result) # -> Executed: SELECT * FROM users WHERE id = 123 on postgresql://localhost/db
Async Providers
import asyncio
from typing import Annotated
from spritze import Container, Scope, provider, Depends, init, inject
class AsyncDatabaseConnection:
def __init__(self, url: str) -> None:
self.url: str = url
async def query(self, sql: str) -> str:
await asyncio.sleep(0.1) # Simulate async operation
return f"Async executed: {sql} on {self.url}"
class AsyncUserService:
def __init__(self, db: AsyncDatabaseConnection) -> None:
self.db: AsyncDatabaseConnection = db
async def get_user(self, user_id: int) -> str:
return await self.db.query(f"SELECT * FROM users WHERE id = {user_id}")
class AsyncContainer(Container):
@provider(scope=Scope.APP)
def db_url(self) -> str:
return "postgresql://localhost/db"
@provider(scope=Scope.REQUEST)
async def database(self, url: str) -> AsyncDatabaseConnection:
return AsyncDatabaseConnection(url)
@provider(scope=Scope.REQUEST)
async def user_service(self, db: AsyncDatabaseConnection) -> AsyncUserService:
return AsyncUserService(db)
container = AsyncContainer()
init(container)
@inject
async def async_handler(
user_id: int,
service: Annotated[AsyncUserService, Depends()]
) -> str:
return await service.get_user(user_id)
async def main() -> None:
result = await async_handler(123)
print(result)
if __name__ == "__main__":
asyncio.run(main())
Context Managers
from typing import Annotated, Generator
from spritze import Container, Scope, provider, Depends, init, inject
class DatabaseConnection:
def __init__(self, url: str) -> None:
self.url: str = url
print(f"Connected to {url}")
def close(self) -> None:
print(f"Disconnected from {self.url}")
class AppContainer(Container):
@provider(scope=Scope.REQUEST)
def database(self) -> Generator[DatabaseConnection, None, None]:
db = DatabaseConnection("postgresql://localhost/db")
try:
yield db
finally:
db.close()
container = AppContainer()
init(container)
@inject
def handler(db: Annotated[DatabaseConnection, Depends()]) -> str:
return f"Using database: {db.url}"
# Database will be automatically closed after the request
result = handler()
Advanced Features
Multiple Containers
from spritze import Container, init, inject, Scope, provider
class CoreContainer(Container):
@provider(scope=Scope.APP)
def config(self) -> str:
return "core_config"
class FeatureContainer(Container):
@provider(scope=Scope.REQUEST)
def feature(self, config: str) -> str:
return f"feature_with_{config}"
# Initialize multiple containers
init((CoreContainer(), FeatureContainer()))
@inject
def handler(feature: Annotated[str, Depends()]) -> str:
return feature
Context Values
from spritze import Container, context, ContextField, Scope, provider
class RequestContext:
def __init__(self, user_id: int) -> None:
self.user_id: int = user_id
class AppContainer(Container):
request: ContextField[RequestContext] = context.get(RequestContext)
@provider(scope=Scope.REQUEST)
def user_service(self, request: RequestContext) -> str:
return f"User {request.user_id} service"
container = AppContainer()
container.context.update(RequestContext=RequestContext(user_id=123))
Examples
See examples/ for complete integrations:
- Flask:
examples/flask_example.py- Web application with request scoping - Litestar:
examples/litestar_example.py- Modern async web framework - Django:
examples/django_example.py- Traditional web framework - Multi-Container:
examples/multi_container_example.py- Complex dependency graphs
Architecture
Spritze follows Clean Architecture and Domain-Driven Design principles:
- Domain Layer: Core entities (
Provider,Transient) and value objects (Scope,ProviderType) - Application Layer: Decorators and global container management
- Infrastructure Layer: Context management and exception handling
- Repository Layer: Container implementation and dependency resolution
License
Apache 2.0 — see LICENSE
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spritze-0.2.0.tar.gz.
File metadata
- Download URL: spritze-0.2.0.tar.gz
- Upload date:
- Size: 23.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cabede964f9a882ef998642da83d24267e97afa2a6a753c8b1ef42b04928ac1
|
|
| MD5 |
d9266ec75380aa3b6ac4aa31e8200822
|
|
| BLAKE2b-256 |
264aedaedbee6a24a8f11d5e233c196fdb5dbea4ef9579762fcc1ef2ffabfac8
|
Provenance
The following attestation bundles were made for spritze-0.2.0.tar.gz:
Publisher:
release.yml on aSel1x/spritze
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spritze-0.2.0.tar.gz -
Subject digest:
4cabede964f9a882ef998642da83d24267e97afa2a6a753c8b1ef42b04928ac1 - Sigstore transparency entry: 614782578
- Sigstore integration time:
-
Permalink:
aSel1x/spritze@222dd4e79e53bec35efa35dd5579241f2e4bef52 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/aSel1x
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@222dd4e79e53bec35efa35dd5579241f2e4bef52 -
Trigger Event:
release
-
Statement type:
File details
Details for the file spritze-0.2.0-py3-none-any.whl.
File metadata
- Download URL: spritze-0.2.0-py3-none-any.whl
- Upload date:
- Size: 24.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd8531911a4d7283a2c7d90cea11298f507cfde142239d7243f439e04de6d998
|
|
| MD5 |
4754cde4968918c1e02ab62475490912
|
|
| BLAKE2b-256 |
d1b258eaf406549e2ae917d1d0843ee594b084ea49d7999a3751acfb4fd38fc0
|
Provenance
The following attestation bundles were made for spritze-0.2.0-py3-none-any.whl:
Publisher:
release.yml on aSel1x/spritze
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spritze-0.2.0-py3-none-any.whl -
Subject digest:
cd8531911a4d7283a2c7d90cea11298f507cfde142239d7243f439e04de6d998 - Sigstore transparency entry: 614782614
- Sigstore integration time:
-
Permalink:
aSel1x/spritze@222dd4e79e53bec35efa35dd5579241f2e4bef52 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/aSel1x
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@222dd4e79e53bec35efa35dd5579241f2e4bef52 -
Trigger Event:
release
-
Statement type: