API Reference¶
This page provides a comprehensive reference for all PyInj classes, functions, and constants.
Core Classes¶
Container¶
pyinj.Container
The main dependency injection container that manages services and their lifecycles.
Methods¶
register(token: Token[T], provider: Callable[[], T], scope: Scope = Scope.TRANSIENT) -> None
Register a provider function for a token.
token
: Token identifying the dependencyprovider
: Function that creates instancesscope
: Lifecycle scope (SINGLETON, REQUEST, SESSION, TRANSIENT)
get(token: Token[T]) -> T
Synchronously resolve a dependency.
token
: Token to resolve- Returns: Instance of type T
- Raises:
ResolutionError
if dependency cannot be resolved
aget(token: Token[T]) -> Awaitable[T]
Asynchronously resolve a dependency.
token
: Token to resolve- Returns: Awaitable instance of type T
- Raises:
ResolutionError
if dependency cannot be resolved
override(token: Token[T], instance: T) -> None
Override a registered dependency with a specific instance (useful for testing).
token
: Token to overrideinstance
: Instance to use instead of the registered provider
clear_overrides() -> None
Clear all dependency overrides.
register_context_sync(token: Token[T], context_provider: Callable[[], ContextManager[T]]) -> None
Register a synchronous context manager provider.
token
: Token identifying the dependencycontext_provider
: Function returning a context manager
register_context_async(token: Token[T], context_provider: Callable[[], AsyncContextManager[T]]) -> None
Register an asynchronous context manager provider.
token
: Token identifying the dependencycontext_provider
: Function returning an async context manager
request_scope() -> ContextManager[Container]
Create a synchronous request scope context manager.
async_request_scope() -> AsyncContextManager[Container]
Create an asynchronous request scope context manager.
session_scope() -> ContextManager[Container]
Create a session scope context manager.
aclose() -> Awaitable[None]
Asynchronously clean up all managed resources.
Token¶
pyinj.Token[T]
A typed identifier for dependencies with pre-computed hash for O(1) lookups.
Constructor¶
Token(name: str, type_: type[T], scope: Scope = Scope.TRANSIENT, qualifier: str | None = None, tags: tuple[str, ...] = ())
name
: Human-readable nametype_
: Expected Python typescope
: Default lifecycle scopequalifier
: Optional qualifier for multiple instances of same typetags
: Optional tags for discovery/metadata
Properties¶
name: str
Human-readable name of the token.
type_: type[T]
The expected Python type for this token.
scope: Scope
Default lifecycle scope.
qualifier: str | None
Optional qualifier string.
tags: tuple[str, ...]
Immutable tuple of tags.
qualified_name: str
Fully qualified name including module, type, qualifier, and token name.
Methods¶
with_scope(scope: Scope) -> Token[T]
Return a copy with a different scope.
with_qualifier(qualifier: str) -> Token[T]
Return a copy with a qualifier.
with_tags(*tags: str) -> Token[T]
Return a copy with additional tags.
validate(instance: object) -> bool
Validate that an instance matches the token's expected type.
TokenFactory¶
pyinj.TokenFactory
Factory for creating and caching commonly used tokens.
Methods¶
create(name: str, type_: type[T], scope: Scope = Scope.TRANSIENT, qualifier: str | None = None, tags: tuple[str, ...] = ()) -> Token[T]
Create a token with caching for common patterns.
singleton(name: str, type_: type[T]) -> Token[T]
Create a singleton-scoped token.
request(name: str, type_: type[T]) -> Token[T]
Create a request-scoped token.
session(name: str, type_: type[T]) -> Token[T]
Create a session-scoped token.
transient(name: str, type_: type[T]) -> Token[T]
Create a transient-scoped token.
qualified(qualifier: str, type_: type[T], scope: Scope = Scope.TRANSIENT) -> Token[T]
Create a qualified token.
clear_cache() -> None
Clear the internal token cache.
cache_size: int
Number of cached tokens.
Enums¶
Scope¶
pyinj.Scope
Enumeration of dependency lifecycle scopes.
Values¶
SINGLETON
One instance per container (process-wide).
REQUEST
One instance per request context.
SESSION
One instance per session context.
TRANSIENT
New instance for every resolution.
Decorators and Markers¶
inject¶
pyinj.inject(func: Callable = None, *, container: Container | None = None, cache: bool = True) -> Callable
Decorator that automatically injects dependencies based on type annotations.
func
: Function to decoratecontainer
: Container to use (uses default if None)cache
: Whether to cache dependency analysis- Returns: Decorated function with dependency injection
Usage¶
@inject
def handler(logger: Logger, db: Database) -> None:
# Dependencies automatically injected
pass
@inject(container=my_container)
async def async_handler(service: AsyncService) -> None:
# Use specific container
pass
Inject¶
pyinj.Inject[T]
Marker class for explicit dependency injection.
Usage¶
from typing import Annotated
@inject
def handler(
logger: Logger, # Simple injection
cache: Annotated[Cache, Inject(lambda: MockCache())] # Custom provider
) -> None:
pass
Given¶
pyinj.Given[T]
Scala-style marker for implicit dependencies (alias for Inject[T]).
Depends¶
pyinj.Depends(provider: Callable[[], T]) -> T
FastAPI-compatible dependency marker.
def handler(service: Service = Depends(lambda: ServiceImpl())) -> None:
pass
Contextual Containers¶
ContextualContainer¶
pyinj.ContextualContainer
Base class adding request/session context support via contextvars
. The main Container
class inherits from this.
Methods¶
resolve_from_context(token: Token[T]) -> T | None
Resolve dependency from current context without creating new instances.
store_in_context(token: Token[T], instance: T) -> None
Store instance in appropriate context based on token scope.
clear_request_context() -> None
Clear current request context.
clear_session_context() -> None
Clear current session context.
clear_all_contexts() -> None
Clear all contexts including singletons.
RequestScope¶
pyinj.RequestScope
Helper class for managing request-scoped dependencies.
Usage¶
async with RequestScope(container) as scope:
service = scope.resolve(ServiceToken)
SessionScope¶
pyinj.SessionScope
Helper class for managing session-scoped dependencies.
Exceptions¶
PyInjError¶
pyinj.exceptions.PyInjError
Base exception for all PyInj errors.
ResolutionError¶
pyinj.exceptions.ResolutionError
Raised when a dependency cannot be resolved.
Properties¶
token: Token[Any]
The token that couldn't be resolved.
chain: list[Token[Any]]
The resolution chain leading to the error.
cause: str
Human-readable cause description.
CircularDependencyError¶
pyinj.exceptions.CircularDependencyError
Raised when circular dependency is detected. Inherits from ResolutionError
.
AsyncCleanupRequiredError¶
pyinj.exceptions.AsyncCleanupRequiredError
Raised when synchronous cleanup is attempted on async-only resources.
Container Management Functions¶
get_default_container¶
pyinj.get_default_container() -> Container
Get the global default container.
- Returns: The default container instance
- Raises:
RuntimeError
if no default container is set
set_default_container¶
pyinj.set_default_container(container: Container) -> None
Set the global default container.
container
: Container instance to use as default
Metaclass Support¶
Injectable¶
pyinj.Injectable
Metaclass for automatic service registration.
Usage¶
class EmailService(metaclass=Injectable):
__injectable__ = True
__token_name__ = "email_service"
__scope__ = Scope.SINGLETON
def __init__(self, logger: Logger):
self.logger = logger
Type Annotations¶
Protocols¶
PyInj works with Python's Protocol
system for structural typing:
from typing import Protocol, runtime_checkable
@runtime_checkable
class Logger(Protocol):
def info(self, message: str) -> None: ...
def error(self, message: str) -> None: ...
Generic Support¶
PyInj fully supports generic types:
from typing import Generic, TypeVar
T = TypeVar('T')
class Repository(Protocol, Generic[T]):
def save(self, entity: T) -> None: ...
def find_by_id(self, id: int) -> T | None: ...
USER_REPO = Token[Repository[User]]("user_repo")
Constants and Configuration¶
Version Information¶
pyinj.__version__
String containing the current PyInj version.
pyinj.__author__
Author information.
Performance Characteristics¶
- Token resolution: O(1) time complexity due to pre-computed hashes
- Injection analysis: Cached for repeated use of
@inject
- Memory overhead: ~500 bytes per registered service
- Thread safety: Full thread and async safety via
contextvars
- Circular dependency detection: Early detection with detailed error chains
Type Safety Features¶
- PEP 561 compliant: Includes
py.typed
marker file - Full static analysis: Works with mypy, basedpyright, pyright
- Protocol validation: Runtime checking with
@runtime_checkable
- Generic preservation: Complete generic type support throughout the API
- Zero runtime type overhead: Type checking is compile-time only (unless explicitly requested)
This API reference covers all public interfaces in PyInj. For examples and usage patterns, see the other documentation sections.