CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-dependency-injector

Dependency injection framework for Python

Pending
Overview
Eval results
Files

resources.mddocs/

Resource Management

Resource management provides base classes and providers for handling resource lifecycles with automatic initialization and cleanup. Resources represent objects that require explicit setup and teardown, such as database connections, file handles, or network connections.

Capabilities

Base Resource Classes

Abstract base classes that define the resource interface for synchronous and asynchronous resources.

class Resource:
    """Abstract synchronous resource with initialization and cleanup."""
    def __init__(self, *args, **kwargs): ...
    
    def init(self, *args, **kwargs):
        """
        Initialize the resource.
        
        Parameters:
        - *args: Positional arguments for initialization
        - **kwargs: Keyword arguments for initialization
        
        Returns:
        The initialized resource object
        """
    
    def shutdown(self, resource):
        """
        Shutdown and cleanup the resource.
        
        Parameters:
        - resource: The resource object to cleanup
        """
    
    def __enter__(self):
        """Context manager entry."""
    
    def __exit__(self, *exc_info):
        """Context manager exit with cleanup."""

class AsyncResource:
    """Abstract asynchronous resource with async initialization and cleanup."""
    def __init__(self, *args, **kwargs): ...
    
    async def init(self, *args, **kwargs):
        """
        Asynchronously initialize the resource.
        
        Parameters:
        - *args: Positional arguments for initialization
        - **kwargs: Keyword arguments for initialization
        
        Returns:
        The initialized resource object
        """
    
    async def shutdown(self, resource):
        """
        Asynchronously shutdown and cleanup the resource.
        
        Parameters:
        - resource: The resource object to cleanup
        """
    
    async def __aenter__(self):
        """Async context manager entry."""
    
    async def __aexit__(self, *exc_info):
        """Async context manager exit with cleanup."""

Synchronous Resource Implementation

Implementation pattern for synchronous resources that require initialization and cleanup.

Usage example:

from dependency_injector.resources import Resource

class DatabaseResource(Resource):
    def init(self, connection_string, pool_size=10):
        """Initialize database connection pool."""
        print(f"Connecting to database: {connection_string}")
        connection_pool = create_connection_pool(
            connection_string,
            pool_size=pool_size
        )
        print(f"Created connection pool with {pool_size} connections")
        return connection_pool
    
    def shutdown(self, connection_pool):
        """Close all database connections."""
        print("Closing database connection pool")
        connection_pool.close_all()
        print("Database connections closed")

# Usage with provider
from dependency_injector import providers

database = providers.Resource(
    DatabaseResource,
    connection_string="postgresql://localhost/mydb",
    pool_size=20
)

# Initialize resource
db_pool = database()  # Calls init() method
# Use database pool
result = db_pool.execute("SELECT * FROM users")
# Cleanup is handled automatically or manually
database.shutdown()  # Calls shutdown() method

Asynchronous Resource Implementation

Implementation pattern for asynchronous resources with async/await support.

Usage example:

from dependency_injector.resources import AsyncResource
import asyncio
import aioredis

class RedisResource(AsyncResource):
    async def init(self, host="localhost", port=6379, db=0):
        """Initialize async Redis connection."""
        print(f"Connecting to Redis: {host}:{port}/{db}")
        redis_client = await aioredis.from_url(
            f"redis://{host}:{port}/{db}"
        )
        print("Redis connection established")
        return redis_client
    
    async def shutdown(self, redis_client):
        """Close Redis connection."""
        print("Closing Redis connection")
        await redis_client.close()
        print("Redis connection closed")

# Usage with provider
redis = providers.Resource(
    RedisResource,
    host="localhost",
    port=6379,
    db=0
)

# Async usage
async def main():
    redis_client = await redis()  # Calls init() method
    await redis_client.set("key", "value")
    value = await redis_client.get("key")
    print(f"Retrieved value: {value}")
    await redis.shutdown()  # Calls shutdown() method

asyncio.run(main())

File Resource Implementation

Example of file resource management with proper cleanup.

from dependency_injector.resources import Resource

class FileResource(Resource):
    def init(self, filepath, mode="r", encoding="utf-8"):
        """Open file handle."""
        print(f"Opening file: {filepath} (mode: {mode})")
        file_handle = open(filepath, mode, encoding=encoding)
        return file_handle
    
    def shutdown(self, file_handle):
        """Close file handle."""
        print(f"Closing file: {file_handle.name}")
        file_handle.close()

# Usage
config_file = providers.Resource(
    FileResource,
    filepath="config.json",
    mode="r"
)

# Use as context manager
with config_file() as f:
    config_data = f.read()
# File is automatically closed

HTTP Client Resource Implementation

Example of HTTP client resource with connection pooling.

from dependency_injector.resources import AsyncResource
import aiohttp

class HttpClientResource(AsyncResource):
    async def init(self, base_url, timeout=30, connector_limit=100):
        """Initialize HTTP client session."""
        print(f"Creating HTTP client for: {base_url}")
        timeout_config = aiohttp.ClientTimeout(total=timeout)
        connector = aiohttp.TCPConnector(limit=connector_limit)
        
        session = aiohttp.ClientSession(
            base_url=base_url,
            timeout=timeout_config,
            connector=connector
        )
        print("HTTP client session created")
        return session
    
    async def shutdown(self, session):
        """Close HTTP client session."""
        print("Closing HTTP client session")
        await session.close()
        print("HTTP client session closed")

# Usage
api_client = providers.Resource(
    HttpClientResource,
    base_url="https://api.example.com",
    timeout=60
)

async def make_request():
    client = await api_client()
    async with client.get("/users") as response:
        data = await response.json()
        return data

Resource Provider Integration

Resources integrate with the dependency injection system through resource providers.

from dependency_injector import containers, providers
from dependency_injector.resources import Resource

class DatabaseResource(Resource):
    def init(self, connection_string):
        return create_database_connection(connection_string)
    
    def shutdown(self, connection):
        connection.close()

class Container(containers.DeclarativeContainer):
    config = providers.Configuration()
    
    # Resource provider
    database = providers.Resource(
        DatabaseResource,
        connection_string=config.database.url
    )
    
    # Other providers can use the resource
    user_repository = providers.Factory(
        UserRepository,
        database=database  # Automatically initialized resource
    )

# Container automatically manages resource lifecycle
container = Container()
container.config.from_dict({
    "database": {"url": "postgresql://localhost/mydb"}
})

# Initialize all resources
await container.init_resources()

# Use services that depend on resources
user_repo = container.user_repository()
users = user_repo.get_all_users()

# Shutdown all resources
await container.shutdown_resources()

Resource Context Managers

Resources support context manager protocols for automatic cleanup.

# Synchronous context manager
class DatabaseResource(Resource):
    def init(self, connection_string):
        return create_connection(connection_string)
    
    def shutdown(self, connection):
        connection.close()

# Usage as context manager
database = providers.Resource(DatabaseResource, "postgresql://localhost/db")

with database() as db_connection:
    # Use database connection
    result = db_connection.execute("SELECT * FROM users")
# Connection is automatically closed

# Asynchronous context manager
class AsyncDatabaseResource(AsyncResource):
    async def init(self, connection_string):
        return await create_async_connection(connection_string)
    
    async def shutdown(self, connection):
        await connection.close()

# Usage as async context manager
async_database = providers.Resource(AsyncDatabaseResource, "postgresql://localhost/db")

async with async_database() as db_connection:
    # Use async database connection
    result = await db_connection.execute("SELECT * FROM users")
# Connection is automatically closed

Resource Dependency Injection

Resources can be injected into functions and methods using dependency wiring.

from dependency_injector.wiring import inject, Provide, Closing

@inject
def process_users(
    database = Provide[Container.database],
    cache = Provide[Container.redis],
    # Resource cleanup markers
    db_cleanup = Closing[Container.database],
    cache_cleanup = Closing[Container.redis]
):
    # Use resources
    users = database.query("SELECT * FROM users")
    cache.set("users", users)
    
    # Resources will be automatically cleaned up
    return users

# Wire container
container.wire(modules=[__name__])

Resource Error Handling

Proper error handling in resource initialization and cleanup.

from dependency_injector.resources import Resource

class RobustDatabaseResource(Resource):
    def init(self, connection_string, max_retries=3):
        """Initialize with retry logic."""
        for attempt in range(max_retries):
            try:
                print(f"Database connection attempt {attempt + 1}")
                connection = create_connection(connection_string)
                print("Database connection successful")
                return connection
            except ConnectionError as e:
                print(f"Connection failed: {e}")
                if attempt == max_retries - 1:
                    raise
                time.sleep(2 ** attempt)  # Exponential backoff
    
    def shutdown(self, connection):
        """Shutdown with error handling."""
        try:
            if connection and not connection.is_closed():
                connection.close()
                print("Database connection closed")
        except Exception as e:
            print(f"Error closing database connection: {e}")
            # Log error but don't raise to avoid masking original exceptions

Resource Composition

Combining multiple resources into composite resources.

class CompositeResource(Resource):
    def init(self, db_config, redis_config):
        """Initialize multiple resources."""
        database = DatabaseResource().init(**db_config)
        redis = RedisResource().init(**redis_config)
        
        return {
            "database": database,
            "redis": redis
        }
    
    def shutdown(self, resources):
        """Shutdown all resources."""
        if "database" in resources:
            DatabaseResource().shutdown(resources["database"])
        if "redis" in resources:
            RedisResource().shutdown(resources["redis"])

# Usage
composite = providers.Resource(
    CompositeResource,
    db_config={"connection_string": "postgresql://localhost/db"},
    redis_config={"host": "localhost", "port": 6379}
)

Install with Tessl CLI

npx tessl i tessl/pypi-dependency-injector

docs

containers.md

index.md

providers.md

resources.md

schema.md

wiring.md

tile.json