Dependency injection container
Project description
A modern, type-safe dependency injection container for Python 3.10+
Unlike many other Python DI containers, Independency operates in the local scope with no global state. It's inspired by punq with a similar API, enhanced with full support for generics, advanced typing, and comprehensive testing utilities.
Features
- No Global State: Explicit container creation, no hidden dependencies
- Type Safety: Full support for generics, type hints, and static type checking
- Modern Python: Built for Python 3.10+ with modern typing features (PEP 585)
- Flexible Registrations: Singleton and transient scopes, factory functions
- Testing Support: Built-in
TestContainerfor easy dependency mocking - Build-time Validation: Dependency graph validation with cycle detection
- String Keys: Support for string-based dependency registration
- Self-injection: Container can be injected as a dependency
Installation
pip install independency
Quick Start
import independency
builder = independency.ContainerBuilder()
# register application dependencies
container = builder.build()
obj: SomeRegisteredClass = container.resolve(SomeRegisteredClass)
Usage
Registering Dependencies
# Transient: creates new object on each resolve
builder.register(User, User)
# Singleton: creates object only once
builder.singleton(User, User)
# Generics support
builder.singleton(Storage[int], Storage[int])
builder.singleton(Storage[str], Storage[str])
# String-based registration
builder.singleton('special_storage', Storage[int])
Factory Functions
The second argument is a factory, so you can provide any callable:
def create_db(config: Config) -> Database:
return Database(config.dsn)
builder.singleton(Config, Config)
builder.singleton(Database, create_db)
Explicit Dependencies
Use Dependency to pass specific dependencies to a factory:
from independency import Dependency as Dep
builder.singleton('primary_db', Database, dsn='postgresql://primary')
builder.singleton('cache_db', Database, dsn='redis://cache')
builder.singleton(UserService, db=Dep('primary_db'))
builder.singleton(CacheService, db=Dep('cache_db'))
Testing with Overrides
Independency provides a specialized TestContainer for easy mocking in tests:
# Create your production container
container = builder.build()
# Create a test container with overrides
test_container = container.create_test_container()
test_container = test_container.with_overridden_singleton(
Database,
MockDatabase
)
# Use in tests
service = test_container.resolve(UserService) # Gets MockDatabase injected
Examples
Basic HTTP Client
import requests
from independency import Container, ContainerBuilder
class Config:
def __init__(self, url: str):
self.url = url
class Getter:
def __init__(self, config: Config):
self.config = config
def get(self):
return requests.get(self.config.url)
def create_container() -> Container:
builder = ContainerBuilder()
builder.singleton(Config, Config, url='http://example.com')
builder.singleton(Getter, Getter)
return builder.build()
def main():
container = create_container()
getter: Getter = container.resolve(Getter)
print(getter.get().status_code)
if __name__ == '__main__':
main()
Multiple Instances with String Keys
When you need multiple instances of the same type:
from independency import Container, ContainerBuilder, Dependency as Dep
class Queue:
def __init__(self, url: str):
self.url = url
def pop(self):
...
class Consumer:
def __init__(self, q: Queue):
self.queue = q
def consume(self):
while True:
message = self.queue.pop()
# process message
def create_container() -> Container:
builder = ContainerBuilder()
builder.singleton('first_q', Queue, url='http://example.com')
builder.singleton('second_q', Queue, url='http://example2.com')
builder.singleton('c1', Consumer, q=Dep('first_q'))
builder.singleton('c2', Consumer, q=Dep('second_q'))
return builder.build()
def main():
container = create_container()
consumer: Consumer = container.resolve('c1')
consumer.consume()
if __name__ == '__main__':
main()
API Reference
ContainerBuilder
register(key, factory, **kwargs)- Register a transient dependency (new instance per resolve)singleton(key, factory, **kwargs)- Register a singleton dependency (single instance)build()- Build and validate the container
Container
resolve(key)- Resolve a dependency by type or string keycreate_test_container()- Create a test container from this container
TestContainer
with_overridden_singleton(key, factory, **kwargs)- Override a dependency for testingresolve(key)- Resolve a dependency (same as Container)
Development
Setup
# Install uv if you don't have it
pip install uv
# Install dependencies
uv sync --extra dev
Running Tests
make tests # Run pytest with 100% coverage requirement
make lint # Run all linters (flake8, mypy, pylint, black)
make pretty # Format code with black
Requirements
- Python 3.10 or higher
- No runtime dependencies (only dev dependencies for testing)
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Ensure
make testsandmake lintpass - Submit a pull request
If you find a bug or have a feature request, please open an issue on GitHub.
License
See the LICENSE file for details.
Credits
Inspired by punq - a similar dependency injection library for Python.
Project details
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 independency-1.4.tar.gz.
File metadata
- Download URL: independency-1.4.tar.gz
- Upload date:
- Size: 5.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.13.11 Linux/6.11.0-1018-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d892b6208a51e6e7fabd1fee56db365676597e0aa10106355a1dc3d87cf46ae7
|
|
| MD5 |
57ce6fd449b9b27728b4ca47d770136f
|
|
| BLAKE2b-256 |
7441ba9d8de6dcb00743edc2cdc9541697707aef03e8780dc99d0b348e093657
|
File details
Details for the file independency-1.4-py3-none-any.whl.
File metadata
- Download URL: independency-1.4-py3-none-any.whl
- Upload date:
- Size: 6.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.13.11 Linux/6.11.0-1018-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
806f898730d1e07eb389e227f81179a3396a6fe855aa0a6dee09393087e183a6
|
|
| MD5 |
144c39f643cb8f9723f037a0a26cda99
|
|
| BLAKE2b-256 |
138f3119be5464a33ad4dbc7b50f4cbf371084de94a66f38dece8fceefda5137
|