
Product
Secure Your AI-Generated Code with Socket MCP
Socket MCP brings real-time security checks to AI-generated code, helping developers catch risky dependencies before they enter the codebase.
.. image:: https://travis-ci.org/jblawatt/python-simple-di.svg?branch=master .. image:: https://img.shields.io/pypi/v/python-simple-di.svg
python-simple-di is a simple dependency injection container implementation. With its help you can create instances and its dependencies on runtime.
.. contents::
1.7.0
inject
and inject_many
decorator. (WARNING: inject_many
uses resolve_many
that makes use of the unsorted items
dict-method. So there is no garanty that the first instance is the first registered instance.)resolve
also accepts a type as parameter name
and will return the first instance subclassing that type (first result of resolve_many
). (WARNING: resolve_many
that makes use of the unsorted items
dict-method. So there is no garanty that the first instance is the first registered instance.)1.6.0
resolve_many
and resolve_many_lazy
gives you the possibility to resolve multiple objects depending on their class.register
can be used as decorator now.with
block.mixins
can container a list or a type of types that will be used to create the new type.1.5.2
You can install it via pip: ::
pip install python-simple-di
or via easy_install: ::
easy_install -U python-simple-di
To configure the di.DIContainer
you need to pass a dict with the needed configuration in it. Alternativly you can use an instance of di.DIConfig
which is used internal anyway.
Define the objects name as key to access it at runtime. The value needs to be the configuration to create the instance.
sys.path
if the instance is requested. Examples:.. code-block:: python
'type': 'path.to.my.Type'
'type': path.to.my.Type
# or
'type': '/add/to/sys/path:add.to.sys.path.Type'
list
of values to pass as Arguments or a dict
to pass as Keyword Arguments. To mix both, you can define a dictionary with an empty string or None as key and a list as value. Examples:.. code:: python
'args': ['first', 3, 'third']
# or
'args': {'one': '1', 'two':'two'}
# or
'args': {'': [1, 'two'], 'three': 3}
.. code:: python
'lazy': False # default: True
singleton (optional, default: True): If this option is set to True
, the created instance will be saved inside the container. Next time the same instance will be returned. If this value is set to False
a new instance will be created every time.
properties (optional): This option is similar to the args
option. After an instance was created a buildup is called. This buildup fills the given properties with the given values in this dictionary. Examples:
.. code-block:: python
{
'type': 'some.Person',
'propeties': {
'first_name': 'John',
'last_name': 'Doe'
}
}
.. code:: python
'type': 'path.to.implementet.Type',
'assert_type': 'path.to.parent.Type'
.. code:: python
'type': 'myapp.views.ClassBasedView',
'factory_method': 'as_view'
Argument Resolvers
With the help of the resolver the magic comes into play. Thanks to this small classes it is possible to trigger the dependencies of a type at runtime.
The following resolver be brought by the default package. Individual resolver can be implemented by extending the base class di.Resolver
.
ReferenceResolver ................. The ReferenceResolver offers the possibility to an attribute within the python path to refer. This must be the path and the object, as a Python dotted path.
Example:
.. code:: python
{
'args': {
'output_stream': ReferenceResolver('sys.stdout')
}
}
di
also provides some shortcuts for this name:
di.ref('sys.stdout')
as shortcut for type.di.reference('sys.stdout')
as shortcut for the type.'ref:sys.stdout'
as prefix of the configured type to lazy use the resolver.RelationResolver ................ The RelationResolver allows the resolution of an object of this container at runtime.
Example:
.. code:: python
{
'object_a': {
'type': 'some.ClassName'
},
'object_b': {
'type': 'some.other.ClassName',
'args': [
RelationResolver('object_a')
]
},
}
di
also provides some shortcuts for this name:
di.rel('object_a')
as shortcut for type.di.relation('object_a')
as shortcut for the type.'rel:object_a'
as prefix of the configured type to lazy use the resolver.ModuleResover .............
Sometimes it may be necessary to pass an entire module as a parameter. For this purpose the ModuleResolver available.
Example:
.. code:: python
{
'type': 'some.ClassName',
'args': {
'serializer': ModuleResolver('json')
}
}
Di also provides some shortcuts for this name.
di.mod('json')
as shortcut for type.di.module('json')
as shortcut for the type.'mod:json'
as prefix of the configured type to lazy use the resolver.FactoryResolver ...............
With the help of FactoryResolver the return value of a function as an argument can be passed to the specified type.
Example.
.. code:: python
{
'type': 'some.ClassName',
'args': [
FactoryResolver('path.to.the.factory_method')
]
}
Di also provides some shortcuts for this name.
di.fac('path.to.the.factory_method')
as shortcut for type.di.factory('path.to.the.factory_method')
as shortcut for the type.'factory:path.to.the.factory_method'
as prefix of the configured type to lazy use the resolver.AttributeResolver .................
With the Resolver an attribute of an instance can be passed as an argument. This can be very useful if you are using the django web framework and want to pass a settings value as an argument fo an instance.
Example:
.. code:: python
{
'type': 'some.ClassName':
'args': {
'debug': AttributeResolver('django.conf.settings.DEBUG')
}
}
Di also provides some shortcuts for this name.
di.attr('django.conf.settings.DEBUG')
as shortcut for type.di.attribute('django.conf.settings.DEBUG')
as shortcut for the type.'attr:django.conf.settings.DEBUG'
as prefix of the configured type to lazy use the resolver.Events
You can pass an EventDispatcher into the DiContainer. This Dispatcher will be called if anything interesting happens inside the Container. BaseType is di.DIEventDispatcher
.
Usage .....
Simply create a dictionary with your type configuration and pass it as settings argument to the DIContainer
. The Dictionarys key is the type key to resolve the instance.
.. code:: python
# create the container
container = DIContainer(config)
# resolve the instance
instance = container.resolve('instance_key')
# resolve the instance type only
type_of_instance_key = container.resolve_type('instance_key')
Resolve Lazy
Sometimes it may be necessary to create an instance at its first useage. So there are the following two messages, that returns a di.Proxy
instance at first.
To use this Feature you need to provide a proxy_type_name
and install the specific package for this. I recommend lazy-object-proxy
with its type Proxy
. Which is the default value for this argument. It is not shipped with this package because of the many different other implementations and thier different licence.
If you use this in combination with django you can use django.utils.functional.SimpleLazyObject
. But at this moment the resolve_type_lazy
is not working properly with SimpleLazyObject
.
.. code:: python
# create the container
container = DIContainer(config, proxy_type_name='lazy_object_proxy.Proxy')
# lazy resolves the instance
instance = container.resolve_lazy('instance_key')
# lazy resolves the instance type only
type_of_instance_key = container.resolve_type_lazy('instance_key')
Child Container
If you need the same container but override some settings you can create a child container and pass the deviant settings into it.
This is the unittest that explains this function at its best.
.. code:: python
container = DIContainer({
'one': {
'type': 'mock.Mock',
'properties': {
'source': 'parent'
}
},
'two': {
'type': 'mock.Mock',
'properties': {
'source': 'parent'
}
}
})
self.assertEqual(container.one.source, 'parent')
self.assertEqual(container.two.source, 'parent')
child_container = container.create_child_container({
'two': {
'type': 'mock.Mock',
'properties': {
'source': 'child'
}
}
})
self.assertEqual(child_container.one.source, 'parent')
self.assertEqual(child_container.two.source, 'child')
self.assertEqual(container.one.source, 'parent')
self.assertEqual(container.two.source, 'parent')
Decorators
Some method of the di.DIContainer
can be used as decorator zu register or inject instances within your code.
Register by decorator
......................
The method register
can be used as decorator for classes or factory methods. With this
you do not need to provide the instances configuration at container creation.
Passing the settings is optional.
.. code:: python
@container.register("my_service", dict(args={'init_arg': 'test'}))
class MyService(object):
def __init__(self, init_arg):
self.init_arg = init_arg
def get_data(self, args):
pass
Inject with decorator
......................
The method :code:inject
gives you the possibility to inject instances into a
method if a keyword argument was not provided. that makes the loosely coupeling
and testing very easy:
.. code:: python
@container.inject(service='some_service')
def some_method(value, service):
service.do_work(value)
some_method("hello world")
some_method("hello world", ExplicitService())
Inject many with decorator
..........................
The method :code:inject_many
gives you the possibility to inject multiple instances depending on
their type.
.. code-block:: python
@container.inject_many(hooks=SomeHookClass)
def method(data, hook_instances):
for hook in hook_instance:
hook.hook(data)
# ...
FAQs
A simple dependency injection container.
We found that python-simple-di 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 MCP brings real-time security checks to AI-generated code, helping developers catch risky dependencies before they enter the codebase.
Security News
As vulnerability data bottlenecks grow, the federal government is formally investigating NIST’s handling of the National Vulnerability Database.
Research
Security News
Socket’s Threat Research Team has uncovered 60 npm packages using post-install scripts to silently exfiltrate hostnames, IP addresses, DNS servers, and user directories to a Discord-controlled endpoint.