A pythonic dependency injection library that assembles objects into graphs in an easy, maintainable way
npx @tessl/cli install tessl/pypi-pinject@0.14.0A pythonic dependency injection library that simplifies object graph assembly and management. Pinject enables developers to build maintainable, testable applications by decoupling object creation from business logic, using implicit bindings based on naming conventions and automatic constructor injection.
pip install pinjectimport pinjectFor specific functions and classes:
from pinject import (
new_object_graph, BindingSpec, inject, injectable, provides, annotate_arg,
copy_args_to_internal_fields, copy_args_to_public_fields,
SINGLETON, PROTOTYPE, Scope
)import pinject
class OuterClass(object):
def __init__(self, inner_class):
self.inner_class = inner_class
class InnerClass(object):
def __init__(self):
self.forty_two = 42
# Create an object graph
obj_graph = pinject.new_object_graph()
# Provide instances with automatic dependency injection
outer_class = obj_graph.provide(OuterClass)
print(outer_class.inner_class.forty_two) # 42Pinject's design centers around automatic dependency resolution:
This pythonic approach minimizes boilerplate code by automatically inferring dependencies from parameter names and class structures, while supporting advanced features like custom binding specifications, object graph validation, and circular dependency detection.
Core functionality for creating and configuring dependency injection containers. Object graphs serve as the central point for providing instances with automatic dependency resolution.
def new_object_graph(
modules=None,
classes=None,
binding_specs=None,
only_use_explicit_bindings=False,
allow_injecting_none=False,
configure_method_name='configure',
dependencies_method_name='dependencies',
get_arg_names_from_class_name=None,
get_arg_names_from_provider_fn_name=None,
id_to_scope=None,
is_scope_usable_from_scope=None,
use_short_stack_traces=True
):
"""
Creates a new ObjectGraph for dependency injection.
Args:
modules: Modules to search for classes (default: all imported modules)
classes: Specific classes to create implicit bindings for
binding_specs: BindingSpec classes to get bindings from
only_use_explicit_bindings: Whether to only use explicit bindings
allow_injecting_none: Whether to allow None injection
configure_method_name: Name of binding spec configure method
dependencies_method_name: Name of binding spec dependencies method
get_arg_names_from_class_name: Function to get arg names from class name
get_arg_names_from_provider_fn_name: Function to get arg names from provider
id_to_scope: Mapping of scope IDs to scope instances
is_scope_usable_from_scope: Function to check scope compatibility
use_short_stack_traces: Whether to use short stack traces in errors
Returns:
ObjectGraph: New object graph instance
"""
class ObjectGraph:
"""Container for dependency injection and object creation."""
def provide(self, cls):
"""
Provides an instance of the given class with dependency injection.
Args:
cls: Class to instantiate
Returns:
Instance of cls with dependencies injected
"""Decorators for controlling injection behavior, marking classes as injectable, defining provider methods, and specifying argument annotations for precise dependency resolution.
def inject(arg_names=None, all_except=None): ...
def injectable(fn): ...
def provides(arg_name=None, annotated_with=None, in_scope=None): ...
def annotate_arg(arg_name, with_annotation): ...Dependency Injection Decorators
Custom binding configuration through BindingSpec classes that define explicit relationships between interfaces and implementations, enabling complex dependency scenarios.
class BindingSpec(object):
def configure(self, bind): ...Object lifecycle control through built-in and custom scopes, managing when and how instances are created and shared across the application.
SINGLETON: _SingletonScopeId
PROTOTYPE: _PrototypeScopeId
class Scope(object):
def provide(self, binding_key, default_provider_fn): ...Scoping and Lifecycle Management
Convenience decorators for automatically copying constructor arguments to instance fields, reducing boilerplate code in class initializers.
def copy_args_to_internal_fields(fn): ...
def copy_args_to_public_fields(fn): ...Field Initialization Utilities
Comprehensive error system providing clear, actionable feedback for dependency injection issues, from binding conflicts to circular dependencies.
class Error(Exception): ...
class AmbiguousArgNameError(Error): ...
class BadDependencyScopeError(Error): ...
class ConflictingExplicitBindingsError(Error): ...
class CyclicInjectionError(Error): ...
# ... and 23 more specific error types