A simple Dependency Container library
Project description
Python Dependency Container
A lightweight, flexible dependency injection container for Python with strict typing support.
Installation
pip install zarf
Features
- Simple API - Just four main methods:
register,resolve,can_resolve, andunregister - Type-Safe - Full type hints for modern Python development
- Flexible Registration - Register types, instances, or factory functions
- Named Services - Support for multiple implementations of the same interface
- Zero Dependencies - Pure Python implementation with no external dependencies
Basic Usage
from zarf import Container
# Create the container
container = Container()
# Register a concrete class
container.register(UserService)
# Register with a factory function
container.register(DatabaseService, lambda: DatabaseService("connection_string"))
# Register a specific instance
logger = ConsoleLogger()
container.register(ILogger, logger)
# Register with a name
container.register(ILogger, FileLogger("app.log"), "file_logger")
# Resolve services
user_service = container.resolve(UserService)
db = container.resolve(DatabaseService)
logger = container.resolve(ILogger)
file_logger = container.resolve(ILogger, "file_logger")
# Check if services exist
if container.can_resolve(CacheService):
cache = container.resolve(CacheService)
# Remove a service
container.unregister(ILogger, "file_logger")
Detailed Examples
Registering Services
The container supports multiple registration patterns:
# 1. Register a concrete class (will be instantiated when resolved)
container.register(ServiceA)
# 2. Register with a factory function
container.register(ServiceB, lambda: ServiceB("some_config"))
# 3. Register an instance directly
service_c = ServiceC()
container.register(ServiceC, service_c)
# 4. Register with an interface type and named implementations
container.register(IRepository, SqlRepository(), "sql")
container.register(IRepository, MongoRepository(), "mongo")
Dependency Injection
Implement dependency injection patterns:
# Register base services
container.register(ILogger, ConsoleLogger())
container.register(IDatabase, SqlDatabase("connection_string"))
# Register a service with dependencies
container.register(UserService, lambda: UserService(
container.resolve(ILogger),
container.resolve(IDatabase)
))
# Resolve the service (with all dependencies injected)
user_service = container.resolve(UserService)
Working with Interfaces
Create clean architecture with proper dependency inversion:
# Define an interface
class INotificationService:
def send(self, message: str) -> None:
pass
# Define implementations
class EmailNotificationService(INotificationService):
def send(self, message: str) -> None:
print(f"Sending email: {message}")
class SmsNotificationService(INotificationService):
def send(self, message: str) -> None:
print(f"Sending SMS: {message}")
# Register implementations with names
container.register(INotificationService, EmailNotificationService(), "email")
container.register(INotificationService, SmsNotificationService(), "sms")
# Use the services
email_service = container.resolve(INotificationService, "email")
sms_service = container.resolve(INotificationService, "sms")
email_service.send("Hello from email!")
sms_service.send("Hello from SMS!")
API Reference
Container Class
__init__()
Initialize a new dependency container.
register(service_type, implementation=None, name=None)
Register a service in the container.
service_type: The type/interface being registeredimplementation: Either an instance or a factory function (optional)name: Optional name to distinguish multiple implementations- Returns: Container instance (for fluent API)
resolve(service_type, name=None)
Resolve a service from the container.
service_type: The type/interface to resolvename: Optional name for named implementations- Returns: Instance of the requested service
- Raises: KeyError if service not found
can_resolve(service_type, name=None)
Check if a service can be resolved.
service_type: The type/interface to checkname: Optional name for named implementations- Returns: Boolean indicating if service is registered
unregister(service_type, name=None)
Remove a service registration.
service_type: The type/interface to unregistername: Optional name for named implementations- Returns: Boolean indicating if something was removed
Type Hinting
The container provides full type hinting support for modern Python development:
from typing import Protocol
class IUserRepository(Protocol):
def get_user(self, user_id: int) -> dict:
...
class UserRepository:
def get_user(self, user_id: int) -> dict:
return {"id": user_id, "name": "Test User"}
# Register and use with full type support
container.register(IUserRepository, UserRepository())
repo = container.resolve(IUserRepository) # Properly typed as IUserRepository
user = repo.get_user(1) # IDE provides proper completion
Requirements
- Python 3.6+
License
MIT 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 zarf-0.0.1.tar.gz.
File metadata
- Download URL: zarf-0.0.1.tar.gz
- Upload date:
- Size: 7.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e36e75d17b6682d7ed3821d0690bb2309dc5da4e323900ab4be07e771e0c3c05
|
|
| MD5 |
b06c03eac681dc250b8922b0aa354df0
|
|
| BLAKE2b-256 |
82d5e8a62452158a2065113269496f89532138abe0f0ce9770d2313240a89e78
|
File details
Details for the file zarf-0.0.1-py3-none-any.whl.
File metadata
- Download URL: zarf-0.0.1-py3-none-any.whl
- Upload date:
- Size: 6.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27c838bd14c29696b03340318fdb29e42c77d123dae5d9e7a0cd08dfe4ab26be
|
|
| MD5 |
b28cf68db9242155247a6f462afab9df
|
|
| BLAKE2b-256 |
00ebf8aeb641273499ef46b3b9ab39ec142900050b62349d0f5cea97ebfa07b8
|