
Product
Rust Support Now in Beta
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
Python Inversion of Control (IoC) Container
pyioc3 is a lightweight and versatile Inversion of Control (IoC) container for Python. It simplifies the management of dependencies and enables cleaner, more modular code by promoting the use of Dependency Injection (DI) patterns. With pyioc3, you can effortlessly wire up your application's components, specify their lifecycles, and inject dependencies without the hassle of manual instantiation.
pyioc3 offers multiple configuration interfaces including two manual configuration APIs and a decorator-based autowiring API. These APIs are flexible, yet simple to use.
pyioc3 manual APIs support method chaining to minimize boiler-plate code and intermediate variables.
pyioc3 supports various scopes, including Singleton, Transient, and Requested. This provides fine-grained control of the lifecycle of your objects.
pyioc3 is an immutable ioc container that guarentees predictability of the dependency tree.
pyioc3 implements constructor based dependency injection making it easy to drop into existing applications.
pyioc3 pre-computes the dependency tree, resulting in fast instantiations to keep your code fast.
pyioc3 is designed to improve the maintainability, testability, and flexibility of your Python applications.
Install the package
pip install --user pyioc3
from pyioc3 import StaticContainerBuilder
container = (
StaticContainerBuilder()
.bind(Duck)
.bind(QuackProvider, Squeak)
.build()
)
duck = container.get(Duck)
duck.quack()
from pyioc3.builder import BuilderBase, ProviderBinding
class DuckBuilder(Duck):
def __init__(self):
super().__init__(target_t=Duck)
def with_quack_noise(self, noise: str) -> "DuckBuilder":
self.using_provider(
annotation=QuackProvider,
implementation=DynamicQuackProvider,
on_activate=lambda x: x.set_quack_noise(noise)
)
return self
rubber_duck = (
DuckBuilder()
.with_quack_noise("Squeak")
.build()
)
rubber_duck.quack()
from pyioc3.autowire import bind, AutoWireContainerBuilder
class QuackProvider:
def quack(self):
raise NotImplementedError()
@bind()
class Duck:
def __init__(self, quack: QuackProvider):
self._quack = quack
def quack(self):
self._quack.quack()
@bind(QuackProvider)
class Squeak(QuackProvider):
def quack(self):
print("Squeak")
duck = AutoWireContainerBuilder("my_package").build().get(Duck)
duck.quack()
A class that provides an implementation of some contract.
A rule that defines when a provider is instanciated.
Transient: A instanciation rule that causes a new instance of a provider to be created for each dependent reference. Requested: A instanciation rule that causes a new instance of a provider to be created once for each request recieved by the IOC container. Singleton: A instanciation rule that causes a new instance of a provider to be created only once.
Scope Examples:
Consider the given dependency tree.
If class C is bound with transient scope, class A and B will have a unique instance of C each time they are constructed.
a = ioc.get(A)
assert a.c is not a.b.c
a_again = ioc.get(A)
assert a_again.c is not a.c
assert a_again.b.c is not a.b.c
If class C is bound with requested scope, class A and B will share an instance of C each time they are constructed.
a = ioc.get(A)
assert a.c is a.b.c
a_again = ioc.get(A)
assert a_again.c is not a.c
assert a_again.b.c is not a.b.c
If class C is bound with singleton scope, class A and B will always recieve the same instance of C.
a = ioc.get(A)
assert a.c is a.b.c
a_again = ioc.get(A)
assert a_again.c is a.c
assert a_again.b.c is a.b.c
A Generic TypeVar used to identify the type, concrete or abstract, of an injectable.
A Generic TypeVar used to identify a factory method.
Represents a binding for providing instances created by factory functions.
FactoryBinding.factory:
Any callable that accepts a Container
and returns another callable.
FactoryBinding.annotion:
Any Type or forward reference used to uniquely identify this injectable.
Represents a binding for providing instances through dependency injection.
ProviderBinding.annotation:
Any Type or forward reference used to uniquely identify this injectable.
ProviderBinding.implementation:
Any Class
or Class-Like reference used as the injectable.
ProviderBinding.scope:
Any ScopeEnum
or str (one of "singleton", "transient", "requested") that
identifies the instantiation strategy.
ProviderBinding.on_activate:
Any callable that accepts an instance of ProviderBinding.implementation
and
returns the same instance.
ConstantBinding.annotation:
Any Type or forward reference used to uniquely identify this injectable.
ConstantBinding.value:
Any value used as the injectable.
A type union of FactoryBinding, ProviderBinding, and ConstantBinding.
An IOC Container
Container.get:
Retrieve an instance of the specified annotation from the container.
Args:
Returns:
Raises:
Bind classes, values, functions, and factories to a container.
ContainerBuilder.bind:
Bind a class.
Bind any callable type to an annotation. Dependencies will be injected into this object as needed when created.
Scoping can be set to control reuse.
Arguments:
Scopes:
Returns:
ContainerBuilder
ContainerBuilder.bind_constant:
Bind a constant value
This allows you to bind any object to an annotation in a singleton scope.
Arguments:
Returns:
ContainerBuilder
ContainerBuilder.bind_factory:
Bind a higher order function
This approach allows you to control the creation of objects and gives you access to the container. This lets you make runtime decision about how to create an instance.
Arguments:
Returns:
ContainerBuilder
ContainerBuidler.build:
Compute dependency graph and return the container
This call will roll over all the objects and compute the dependants of each member. The container itself is also added to the graph and can thus be injected using it's Type as the annotation.
Returns:
Container
ScopeEnum is an enumeration class representing different dependency scopes.
ScopeEnum.TRANSIENT:
Indicates a transient scope where a new instance is created for each request.
ScopeEnum.REQUESTED:
Indicates a requested scope where a single instance is created for the duration of a request (a single call to Container.get
), typically used in web applications.
ScopeEnum.SINGLETON:
Indicates a singleton scope where a single instance is created and shared across the entire application.
Implements ContainerBuilder
to allows the caller to staticly bind classes, values, functions, and factories to a container.
StaticContainerBuilder.__init__:
Create a StaticContainerBuilder.
Arguments:
Returns:
ContainerBuilder
Base class for building instances with dependency injection.
This class creates a new dependency tree each time build() it is run. This means that there is no distinction between SINGLETON and REQUESTED scope as the the underlaying container will only be activated once.
BuilderBase.__init__:
Initialize the builder with optional bindings.
The provided target_t will be automatically bound as a default. If included in bindings, the bindings entry will be used.
Arguments:
BuilderBase.using_provider:
Register a provider for dependency injection.
Arguments:
Returns:
BuilderBase.using_constant:
Register a constant for dependency injection.
Arguments:
Returns:
BuilderBase.using_factory:
Register a factory function for dependency injection.
Arguments:
Returns:
BuilderBase.build:
Build an instance of the specified target type using the registered dependencies.
Returns:
...
Implements ContainerBuilder
to allows the caller to automatically and staticaly bind classes, values, functions, and factories to a container.
This class facilitates the creation of an IoC container by automatically scanning and binding dependencies from the provided modules.
AutoWireContainerBuilder.__init__:
Initialize a new AutoWireContainerBuilder.
Arguments:
bind:
Decorator for binding a class for use in dependency injection.
Arguments:
ScopeEnum
enumeration, such as "singleton," "transient," or "requested." If not specified, the default scope, "transient" will be used.Returns:
bind_factory:
Decorator for binding a function factory for use in dependency injection.
This decorator allows you to bind a function factory to an interface or annotation, indicating that the factory should be used to create instances of the specified type. Function factories are used to construct instances with custom initialization or configuration.
Arguments:
Returns:
Base class for all custom PyIOC3 exceptions.
Raised if the dependency tree contains cycles.
Raised if a string-based scope is not valid.
Raised if the autowire api detects duplicate annotations.
Raised if a member is requested but not bound.
FAQs
Python IOC Container
We found that pyioc3 demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
Product
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.