CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pinject

A pythonic dependency injection library that assembles objects into graphs in an easy, maintainable way

Pending
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive error system providing clear, actionable feedback for dependency injection issues, from binding conflicts to circular dependencies. All errors inherit from the base Error class.

Capabilities

Base Error Class

Base exception class for all Pinject-related errors.

class Error(Exception):
    """Base exception class for all Pinject errors."""

Binding Resolution Errors

Errors related to resolving dependencies and finding appropriate bindings.

class AmbiguousArgNameError(Error):
    """Multiple bindings match the same argument name, creating ambiguity."""

class MissingRequiredBindingError(Error):
    """Required binding not found during dependency resolution."""

class NothingInjectableForArgError(Error):
    """No injectable found for a required argument."""

class OnlyInstantiableViaProviderFunctionError(Error):
    """Class can only be instantiated through a provider function."""

class NonExplicitlyBoundClassError(Error):
    """Class not explicitly bound when only_use_explicit_bindings=True."""

Binding Configuration Errors

Errors that occur during binding specification and configuration.

class ConflictingExplicitBindingsError(Error):
    """Multiple explicit bindings defined for the same key."""

class ConflictingRequiredBindingError(Error):
    """Conflicting implicit bindings for the same requirement."""

class InvalidBindingTargetError(Error):
    """Binding target has wrong type for the binding."""

class MultipleBindingTargetArgsError(Error):
    """Multiple binding targets specified for the same key."""

class NoBindingTargetArgsError(Error):
    """No binding target specified when required."""

class EmptyBindingSpecError(Error):
    """BindingSpec has neither configure() method nor provider methods."""

Decorator Usage Errors

Errors related to incorrect usage of Pinject decorators.

class DecoratorAppliedToNonInitError(Error):
    """Decorator applied to non-__init__ method."""

class DuplicateDecoratorError(Error):
    """Same decorator applied twice to the same method."""

class EmptyProvidesDecoratorError(Error):
    """@provides() decorator used without arguments."""

class TooManyArgsToInjectDecoratorError(Error):
    """Both arg_names and all_except specified in @inject decorator."""

class NoRemainingArgsToInjectError(Error):
    """All arguments marked as directly passed, leaving none to inject."""

class PargsDisallowedWhenCopyingArgsError(Error):
    """*args not allowed with copy_args decorators."""

Argument and Annotation Errors

Errors related to argument specification and annotation handling.

class NoSuchArgError(Error):
    """Reference to non-existent argument."""

class NoSuchArgToInjectError(Error):
    """Cannot inject into non-existent argument."""

class MultipleAnnotationsForSameArgError(Error):
    """Same argument annotated multiple times."""

class DirectlyPassingInjectedArgsError(Error):
    """Injected arguments passed directly to provider function."""

class WrongArgTypeError(Error):
    """Argument has wrong type."""

class WrongArgElementTypeError(Error):
    """Array/sequence element has wrong type."""

class EmptySequenceArgError(Error):
    """Empty sequence provided where non-empty sequence expected."""

Scoping Errors

Errors related to object scope configuration and usage.

class BadDependencyScopeError(Error):
    """Invalid dependency relationship between scopes."""

class UnknownScopeError(Error):
    """Reference to unknown scope identifier."""

class OverridingDefaultScopeError(Error):
    """Attempt to override built-in scope (SINGLETON, PROTOTYPE)."""

Circular Dependency Errors

Errors related to circular dependency detection.

class CyclicInjectionError(Error):
    """Circular dependency detected in object graph."""

Method Configuration Errors

Errors related to BindingSpec method configuration.

class ConfigureMethodMissingArgsError(Error):
    """BindingSpec configure method missing required arguments."""

Injection Policy Errors

Errors related to injection policies and restrictions.

class InjectingNoneDisallowedError(Error):
    """None injection attempted when allow_injecting_none=False."""

Usage Examples

Handling Ambiguous Bindings

import pinject

class DatabaseService(object):
    def __init__(self):
        pass

class MockDatabaseService(object):
    def __init__(self):
        pass

# This will cause AmbiguousArgNameError
class UserService(object):
    def __init__(self, database_service):  # Ambiguous: which DatabaseService?
        self.db = database_service

try:
    obj_graph = pinject.new_object_graph(classes=[DatabaseService, MockDatabaseService])
    user_service = obj_graph.provide(UserService)
except pinject.AmbiguousArgNameError as e:
    print(f"Ambiguous binding: {e}")
    
    # Solution: Use explicit bindings or annotations
    class MyBindingSpec(pinject.BindingSpec):
        def configure(self, bind):
            bind('database_service').to_class(DatabaseService)
    
    obj_graph = pinject.new_object_graph(
        classes=[DatabaseService, MockDatabaseService],
        binding_specs=[MyBindingSpec()]
    )
    user_service = obj_graph.provide(UserService)  # Success

Handling Missing Bindings

import pinject

class UserService(object):
    def __init__(self, database_service):  # database_service not available
        self.db = database_service

try:
    obj_graph = pinject.new_object_graph()
    user_service = obj_graph.provide(UserService)
except pinject.MissingRequiredBindingError as e:
    print(f"Missing binding: {e}")
    print("Solution: Provide the required class or binding")
    
    # Solution: Add the missing class
    class DatabaseService(object):
        def __init__(self):
            pass
    
    obj_graph = pinject.new_object_graph(classes=[DatabaseService])
    user_service = obj_graph.provide(UserService)  # Success

Handling Circular Dependencies

import pinject

class ServiceA(object):
    def __init__(self, service_b):
        self.service_b = service_b

class ServiceB(object):
    def __init__(self, service_a):
        self.service_a = service_a

try:
    obj_graph = pinject.new_object_graph()
    service_a = obj_graph.provide(ServiceA)
except pinject.CyclicInjectionError as e:
    print(f"Circular dependency: {e}")
    
    # Solution: Break the cycle with lazy injection or redesign
    class ServiceA(object):
        def __init__(self, service_b):
            self.service_b = service_b
    
    class ServiceB(object):
        def __init__(self):
            self.service_a = None  # Set later to break cycle
        
        def set_service_a(self, service_a):
            self.service_a = service_a
    
    obj_graph = pinject.new_object_graph()
    service_a = obj_graph.provide(ServiceA)
    service_b = obj_graph.provide(ServiceB)
    service_b.set_service_a(service_a)  # Manual resolution

Handling Decorator Errors

import pinject

class InvalidService(object):
    @pinject.inject(['nonexistent_arg'])
    def __init__(self, real_arg):
        self.arg = real_arg

try:
    obj_graph = pinject.new_object_graph()
    service = obj_graph.provide(InvalidService)
except pinject.NoSuchArgToInjectError as e:
    print(f"Invalid injection specification: {e}")
    
    # Solution: Fix the decorator
    class ValidService(object):
        @pinject.inject(['real_arg'])
        def __init__(self, real_arg):
            self.arg = real_arg

Handling Scope Errors

import pinject

class MyBindingSpec(pinject.BindingSpec):
    def configure(self, bind):
        # This will cause UnknownScopeError
        bind('service').to_class(object, in_scope='unknown_scope')

try:
    obj_graph = pinject.new_object_graph(binding_specs=[MyBindingSpec()])
except pinject.UnknownScopeError as e:
    print(f"Unknown scope: {e}")
    
    # Solution: Use valid scope or define custom scope
    class ValidBindingSpec(pinject.BindingSpec):
        def configure(self, bind):
            bind('service').to_class(object, in_scope=pinject.SINGLETON)

Error Context and Debugging

import pinject

# Enable detailed error reporting
obj_graph = pinject.new_object_graph(use_short_stack_traces=False)

class ComplexService(object):
    def __init__(self, dep1, dep2, dep3):
        pass

try:
    service = obj_graph.provide(ComplexService)
except pinject.Error as e:
    # All Pinject errors provide detailed context
    print(f"Error type: {type(e).__name__}")
    print(f"Error message: {e}")
    print(f"Error occurred during: ComplexService instantiation")
    
    # Errors include location information and context
    # to help identify the exact source of the problem

Install with Tessl CLI

npx tessl i tessl/pypi-pinject

docs

binding-specs.md

decorators.md

error-handling.md

field-initialization.md

index.md

object-graph.md

scoping.md

tile.json