Merge remote-tracking branch 'origin/2.0-change-injections-style' into 2.0

This commit is contained in:
Roman Mogilatov 2016-05-22 16:27:46 +03:00
commit 5bc6ad0165
15 changed files with 442 additions and 539 deletions

View File

@ -55,20 +55,20 @@ Installation
Example Example
------- -------
Brief example below demonstrates usage of *Dependency Injector* catalogs and
providers for definition of several IoC containers for some microservice
system that consists from several business and platform services:
.. code-block:: python .. code-block:: python
"""Dependency Injector example.""" """Example of several Dependency Injector IoC containers."""
import sys
import sqlite3 import sqlite3
import boto.s3.connection
from boto.s3.connection import S3Connection import example.services
from dependency_injector import catalogs from dependency_injector import catalogs
from dependency_injector import providers from dependency_injector import providers
from dependency_injector import injections
from example import services
class Platform(catalogs.DeclarativeCatalog): class Platform(catalogs.DeclarativeCatalog):
@ -76,7 +76,7 @@ Example
database = providers.Singleton(sqlite3.connect, ':memory:') database = providers.Singleton(sqlite3.connect, ':memory:')
s3 = providers.Singleton(S3Connection, s3 = providers.Singleton(boto.s3.connection.S3Connection,
aws_access_key_id='KEY', aws_access_key_id='KEY',
aws_secret_access_key='SECRET') aws_secret_access_key='SECRET')
@ -84,32 +84,105 @@ Example
class Services(catalogs.DeclarativeCatalog): class Services(catalogs.DeclarativeCatalog):
"""Catalog of business service providers.""" """Catalog of business service providers."""
users = providers.Factory(services.Users, users = providers.Factory(example.services.Users,
db=Platform.database) db=Platform.database)
photos = providers.Factory(services.Photos, photos = providers.Factory(example.services.Photos,
db=Platform.database, db=Platform.database,
s3=Platform.s3) s3=Platform.s3)
auth = providers.Factory(services.Auth, auth = providers.Factory(example.services.Auth,
db=Platform.database, db=Platform.database,
token_ttl=3600) token_ttl=3600)
Next example demonstrates usage of ``@inject`` decorator with IoC containers
defined above:
@injections.inject(users_service=Services.users) .. code-block:: python
@injections.inject(auth_service=Services.auth)
@injections.inject(photos_service=Services.photos) """Dependency Injector @inject decorator example."""
def main(argv, users_service, auth_service, photos_service):
from dependency_injector.injections import inject
from catalogs import Services
@inject(users_service=Services.users)
@inject(auth_service=Services.auth)
@inject(photos_service=Services.photos)
def main(users_service, auth_service, photos_service):
"""Main function.""" """Main function."""
login, password, photo_path = argv[1:] user = users_service.get_user('user')
auth_service.authenticate(user, 'secret')
user = users_service.get_user(login) photos_service.upload_photo(user['id'], 'photo.jpg')
auth_service.authenticate(user, password)
photos_service.upload_photo(user['id'], photo_path)
if __name__ == '__main__': if __name__ == '__main__':
main(sys.argv) main()
Alternative definition styles
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*Dependecy Injector* supports few other styles of dependency injections
definition.
IoC containers from previous example could look like these:
.. code-block:: python
class Platform(catalogs.DeclarativeCatalog):
"""Catalog of platform service providers."""
database = providers.Singleton(sqlite3.connect) \
.args(':memory:')
s3 = providers.Singleton(boto.s3.connection.S3Connection) \
.kwargs(aws_access_key_id='KEY',
aws_secret_access_key='SECRET')
class Services(catalogs.DeclarativeCatalog):
"""Catalog of business service providers."""
users = providers.Factory(example.services.Users) \
.kwargs(db=Platform.database)
photos = providers.Factory(example.services.Photos) \
.kwargs(db=Platform.database,
s3=Platform.s3)
auth = providers.Factory(example.services.Auth) \
.kwargs(db=Platform.database,
token_ttl=3600)
or like this these:
.. code-block:: python
class Platform(catalogs.DeclarativeCatalog):
"""Catalog of platform service providers."""
database = providers.Singleton(sqlite3.connect)
database.args(':memory:')
s3 = providers.Singleton(boto.s3.connection.S3Connection)
s3.kwargs(aws_access_key_id='KEY',
aws_secret_access_key='SECRET')
class Services(catalogs.DeclarativeCatalog):
"""Catalog of business service providers."""
users = providers.Factory(example.services.Users)
users.kwargs(db=Platform.database)
photos = providers.Factory(example.services.Photos)
photos.kwargs(db=Platform.database,
s3=Platform.s3)
auth = providers.Factory(example.services.Auth)
auth.kwargs(db=Platform.database,
token_ttl=3600)
You can get more *Dependency Injector* examples in ``/examples`` directory on You can get more *Dependency Injector* examples in ``/examples`` directory on
GitHub: GitHub:

View File

@ -1,13 +1,15 @@
"""Injections module.""" """Injections module."""
import itertools
import six import six
from dependency_injector.utils import ( from dependency_injector.utils import (
is_provider, is_provider,
is_delegated_provider,
is_injection, is_injection,
is_arg_injection, is_arg_injection,
is_kwarg_injection, is_kwarg_injection,
is_delegated_provider,
fetch_cls_init, fetch_cls_init,
) )
@ -36,7 +38,7 @@ class Injection(object):
""" """
__IS_INJECTION__ = True __IS_INJECTION__ = True
__slots__ = ('injectable', 'call_injectable') __slots__ = ('injectable', 'get_value')
def __init__(self, injectable): def __init__(self, injectable):
"""Initializer. """Initializer.
@ -47,24 +49,14 @@ class Injection(object):
:py:class:`dependency_injector.providers.Provider` :py:class:`dependency_injector.providers.Provider`
""" """
self.injectable = injectable self.injectable = injectable
self.call_injectable = (is_provider(injectable) and
not is_delegated_provider(injectable)) if not is_provider(injectable) or is_delegated_provider(injectable):
def injectable():
return self.injectable
self.get_value = injectable
super(Injection, self).__init__() super(Injection, self).__init__()
@property
def value(self):
"""Read-only property that represents injectable value.
Injectable values and delegated providers are provided "as is".
Other providers will be called every time, when injection needs to
be done.
:rtype: object
"""
if self.call_injectable:
return self.injectable.provide()
return self.injectable
def __str__(self): def __str__(self):
"""Return string representation of provider. """Return string representation of provider.
@ -227,11 +219,11 @@ def inject(*args, **kwargs):
def decorated(*args, **kwargs): def decorated(*args, **kwargs):
"""Decorated with dependency injection callback.""" """Decorated with dependency injection callback."""
if decorated.args: if decorated.args:
args = tuple(arg.value for arg in decorated.args) + args args = tuple(arg.get_value() for arg in decorated.args) + args
for kwarg in decorated.kwargs: for kwarg in decorated.kwargs:
if kwarg.name not in kwargs: if kwarg.name not in kwargs:
kwargs[kwarg.name] = kwarg.value kwargs[kwarg.name] = kwarg.get_value()
return callback(*args, **kwargs) return callback(*args, **kwargs)
@ -246,18 +238,16 @@ def inject(*args, **kwargs):
def _parse_args_injections(args): def _parse_args_injections(args):
"""Parse positional argument injections according to current syntax."""
return tuple(Arg(arg) if not is_injection(arg) else arg return tuple(Arg(arg) if not is_injection(arg) else arg
for arg in args for arg in args
if not is_injection(arg) or is_arg_injection(arg)) if not is_injection(arg) or is_arg_injection(arg))
def _parse_kwargs_injections(args, kwargs): def _parse_kwargs_injections(args, kwargs):
"""Parse keyword argument injections according to current syntax."""
kwarg_injections = tuple(injection kwarg_injections = tuple(injection
for injection in args for injection in args
if is_kwarg_injection(injection)) if is_kwarg_injection(injection))
if kwargs: if kwargs:
kwarg_injections += tuple(KwArg(name, value) kwarg_injections += tuple(itertools.starmap(KwArg,
for name, value in six.iteritems(kwargs)) six.iteritems(kwargs)))
return kwarg_injections return kwarg_injections

View File

@ -3,70 +3,46 @@
import six import six
from dependency_injector.providers.base import Provider from dependency_injector.providers.base import Provider
from dependency_injector.injections import ( from dependency_injector.injections import Arg, KwArg
_parse_args_injections,
_parse_kwargs_injections,
)
from dependency_injector.utils import represent_provider from dependency_injector.utils import represent_provider
from dependency_injector.errors import Error from dependency_injector.errors import Error
@six.python_2_unicode_compatible @six.python_2_unicode_compatible
class Callable(Provider): class Callable(Provider):
""":py:class:`Callable` provider calls wrapped callable on every call. r""":py:class:`Callable` provider calls wrapped callable on every call.
:py:class:`Callable` provider provides callable that is called on every :py:class:`Callable` provider provides callable that is called on every
provider call with some predefined dependency injections. provider call with some predefined dependency injections.
:py:class:`Callable` syntax of passing injections is the same like :py:class:`Callable` supports positional and keyword argument injections:
:py:class:`Factory` one:
.. code-block:: python .. code-block:: python
# simplified syntax for passing positional and keyword argument
# injections:
some_function = Callable(some_function, 'arg1', 'arg2', arg3=3, arg4=4)
# extended (full) syntax for passing positional and keyword argument
# injections:
some_function = Callable(some_function, some_function = Callable(some_function,
injections.Arg(1), 'positional_arg1', 'positional_arg2',
injections.Arg(2), keyword_argument1=3, keyword_argument=4)
injections.KwArg('some_arg', 3),
injections.KwArg('other_arg', 4))
.. py:attribute:: provides # or
Provided callable. some_function = Callable(some_function) \
.args('positional_arg1', 'positional_arg2') \
.kwargs(keyword_argument1=3, keyword_argument=4)
:type: callable # or
.. py:attribute:: args some_function = Callable(some_function)
some_function.args('positional_arg1', 'positional_arg2')
Tuple of positional argument injections. some_function.kwargs(keyword_argument1=3, keyword_argument=4)
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
""" """
__slots__ = ('provides', 'args', 'kwargs') __slots__ = ('_provides', '_args', '_kwargs')
def __init__(self, provides, *args, **kwargs): def __init__(self, provides, *args, **kwargs):
"""Initializer. """Initializer.
:param provides: Wrapped callable. :param provides: Wrapped callable.
:type provides: callable :type provides: callable
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections.
:type kwargs: dict
""" """
if not callable(provides): if not callable(provides):
raise Error('Provider {0} expected to get callable, ' raise Error('Provider {0} expected to get callable, '
@ -74,12 +50,12 @@ class Callable(Provider):
self.__class__.__name__)), self.__class__.__name__)),
provides)) provides))
self.provides = provides self._provides = provides
self._args = tuple()
self._kwargs = tuple()
self.args = tuple() self.args(*args)
self.kwargs = tuple() self.kwargs(**kwargs)
self.add_injections(*args, **kwargs)
super(Callable, self).__init__() super(Callable, self).__init__()
@ -89,19 +65,30 @@ class Callable(Provider):
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`] :rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
""" """
return self.args + self.kwargs return self._args + self._kwargs
def add_injections(self, *args, **kwargs): def args(self, *args):
"""Add provider injections. """Add postional argument injections.
:param args: Tuple of injections. :param args: Tuple of injections.
:type args: tuple :type args: tuple
:return: Reference ``self``
"""
self._args += tuple(Arg(value) for value in args)
return self
def kwargs(self, **kwargs):
"""Add keyword argument injections.
:param kwargs: Dictionary of injections. :param kwargs: Dictionary of injections.
:type kwargs: dict :type kwargs: dict
:return: Reference ``self``
""" """
self.args += _parse_args_injections(args) self._kwargs += tuple(KwArg(name, value)
self.kwargs += _parse_kwargs_injections(args, kwargs) for name, value in six.iteritems(kwargs))
return self
def _provide(self, *args, **kwargs): def _provide(self, *args, **kwargs):
"""Return provided instance. """Return provided instance.
@ -114,21 +101,21 @@ class Callable(Provider):
:rtype: object :rtype: object
""" """
if self.args: if self._args:
args = tuple(arg.value for arg in self.args) + args args = tuple(arg.get_value() for arg in self._args) + args
for kwarg in self.kwargs: for kwarg in self._kwargs:
if kwarg.name not in kwargs: if kwarg.name not in kwargs:
kwargs[kwarg.name] = kwarg.value kwargs[kwarg.name] = kwarg.get_value()
return self.provides(*args, **kwargs) return self._provides(*args, **kwargs)
def __str__(self): def __str__(self):
"""Return string representation of provider. """Return string representation of provider.
:rtype: str :rtype: str
""" """
return represent_provider(provider=self, provides=self.provides) return represent_provider(provider=self, provides=self._provides)
__repr__ = __str__ __repr__ = __str__
@ -138,24 +125,6 @@ class DelegatedCallable(Callable):
:py:class:`DelegatedCallable` is a :py:class:`Callable`, that is injected :py:class:`DelegatedCallable` is a :py:class:`Callable`, that is injected
"as is". "as is".
.. py:attribute:: provides
Provided callable.
:type: callable
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
""" """
__IS_DELEGATED__ = True __IS_DELEGATED__ = True

View File

@ -1,40 +1,53 @@
"""Dependency injector creational providers.""" """Dependency injector creational providers."""
import six
from dependency_injector.providers.callable import Callable from dependency_injector.providers.callable import Callable
from dependency_injector.utils import ( from dependency_injector.injections import Attribute
is_attribute_injection, from dependency_injector.utils import GLOBAL_LOCK
GLOBAL_LOCK,
)
from dependency_injector.errors import Error from dependency_injector.errors import Error
class Factory(Callable): class Factory(Callable):
""":py:class:`Factory` provider creates new instance on every call. r""":py:class:`Factory` provider creates new instance on every call.
:py:class:`Factory` supports different syntaxes of passing injections: :py:class:`Factory` supports positional & keyword argument injections,
as well as attribute injections.
Positional and keyword argument injections could be defined like this:
.. code-block:: python .. code-block:: python
# simplified syntax for passing positional and keyword argument
# injections only:
factory = Factory(SomeClass, 'arg1', 'arg2', arg3=3, arg4=4)
# extended (full) syntax for passing any type of injections:
factory = Factory(SomeClass, factory = Factory(SomeClass,
injections.Arg(1), 'positional_arg1', 'positional_arg2',
injections.Arg(2), keyword_argument1=3, keyword_argument=4)
injections.KwArg('some_arg', 3),
injections.KwArg('other_arg', 4), # or
injections.Attribute('some_attribute', 5))
factory = Factory(SomeClass) \
.args('positional_arg1', 'positional_arg2') \
.kwargs(keyword_argument1=3, keyword_argument=4)
# or
factory = Factory(SomeClass)
factory.args('positional_arg1', 'positional_arg2')
factory.kwargs(keyword_argument1=3, keyword_argument=4)
Attribute injections are defined by using :py:meth:`Factory.attributes`:
.. code-block:: python
factory = Factory(SomeClass) \
.attributes(attribute1=1, attribute2=2)
Retrieving of provided instance can be performed via calling Retrieving of provided instance can be performed via calling
:py:class:`Factory` object: :py:class:`Factory` object:
.. code-block:: python .. code-block:: python
factory = Factory(SomeClass, factory = Factory(SomeClass)
some_arg1=1,
some_arg2=2)
some_object = factory() some_object = factory()
.. py:attribute:: provided_type .. py:attribute:: provided_type
@ -45,41 +58,17 @@ class Factory(Callable):
:type: type | None :type: type | None
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
provided_type = None provided_type = None
__slots__ = ('cls', 'attributes') __slots__ = ('cls', '_attributes')
def __init__(self, provides, *args, **kwargs): def __init__(self, provides, *args, **kwargs):
"""Initializer. """Initializer.
@ -87,23 +76,17 @@ class Factory(Callable):
:param provides: Class or other callable that provides object :param provides: Class or other callable that provides object
for creation. for creation.
:type provides: type | callable :type provides: type | callable
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections.
:type kwargs: dict
""" """
if (self.__class__.provided_type and if (self.__class__.provided_type and
not issubclass(provides, self.__class__.provided_type)): not issubclass(provides, self.__class__.provided_type)):
raise Error('{0} can provide only {1} instances'.format( raise Error('{0} can provide only {1} instances'.format(
self.__class__, self.__class__.provided_type)) self.__class__, self.__class__.provided_type))
self.attributes = tuple() self._attributes = tuple()
super(Factory, self).__init__(provides, *args, **kwargs) super(Factory, self).__init__(provides, *args, **kwargs)
self.cls = self.provides self.cls = self._provides
@property @property
def injections(self): def injections(self):
@ -111,22 +94,18 @@ class Factory(Callable):
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`] :rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
""" """
return self.args + self.kwargs + self.attributes return super(Factory, self).injections + self._attributes
def add_injections(self, *args, **kwargs): def attributes(self, **kwargs):
"""Add provider injections. """Add attribute injections.
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections. :param kwargs: Dictionary of injections.
:type kwargs: dict :type kwargs: dict
"""
self.attributes += tuple(injection
for injection in args
if is_attribute_injection(injection))
super(Factory, self).add_injections(*args, **kwargs) :return: Reference ``self``
"""
self._attributes += tuple(Attribute(name, value)
for name, value in six.iteritems(kwargs))
return self return self
def _provide(self, *args, **kwargs): def _provide(self, *args, **kwargs):
@ -140,17 +119,17 @@ class Factory(Callable):
:rtype: object :rtype: object
""" """
if self.args: if self._args:
args = tuple(arg.value for arg in self.args) + args args = tuple(arg.get_value() for arg in self._args) + args
for kwarg in self.kwargs: for kwarg in self._kwargs:
if kwarg.name not in kwargs: if kwarg.name not in kwargs:
kwargs[kwarg.name] = kwarg.value kwargs[kwarg.name] = kwarg.get_value()
instance = self.provides(*args, **kwargs) instance = self._provides(*args, **kwargs)
for attribute in self.attributes: for attribute in self._attributes:
setattr(instance, attribute.name, attribute.value) setattr(instance, attribute.name, attribute.get_value())
return instance return instance
@ -169,36 +148,12 @@ class DelegatedFactory(Factory):
:type: type | None :type: type | None
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
__IS_DELEGATED__ = True __IS_DELEGATED__ = True
@ -219,9 +174,7 @@ class Singleton(Factory):
.. code-block:: python .. code-block:: python
singleton = Singleton(SomeClass, singleton = Singleton(SomeClass)
some_arg1=1,
some_arg2=2)
some_object = singleton() some_object = singleton()
.. py:attribute:: provided_type .. py:attribute:: provided_type
@ -232,45 +185,15 @@ class Singleton(Factory):
:type: type | None :type: type | None
.. py:attribute:: instance
Read-only reference to singleton's instance.
:type: object
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
__slots__ = ('instance',) __slots__ = ('_instance',)
def __init__(self, provides, *args, **kwargs): def __init__(self, provides, *args, **kwargs):
"""Initializer. """Initializer.
@ -278,14 +201,8 @@ class Singleton(Factory):
:param provides: Class or other callable that provides object :param provides: Class or other callable that provides object
for creation. for creation.
:type provides: type | callable :type provides: type | callable
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections.
:type kwargs: dict
""" """
self.instance = None self._instance = None
super(Singleton, self).__init__(provides, *args, **kwargs) super(Singleton, self).__init__(provides, *args, **kwargs)
def reset(self): def reset(self):
@ -293,7 +210,7 @@ class Singleton(Factory):
:rtype: None :rtype: None
""" """
self.instance = None self._instance = None
def _provide(self, *args, **kwargs): def _provide(self, *args, **kwargs):
"""Return provided instance. """Return provided instance.
@ -306,13 +223,13 @@ class Singleton(Factory):
:rtype: object :rtype: object
""" """
if self.instance: if self._instance:
return self.instance return self._instance
with GLOBAL_LOCK: with GLOBAL_LOCK:
self.instance = super(Singleton, self)._provide(*args, **kwargs) self._instance = super(Singleton, self)._provide(*args, **kwargs)
return self.instance return self._instance
class DelegatedSingleton(Singleton): class DelegatedSingleton(Singleton):
@ -329,42 +246,12 @@ class DelegatedSingleton(Singleton):
:type: type | None :type: type | None
.. py:attribute:: instance
Read-only reference to singleton's instance.
:type: object
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
__IS_DELEGATED__ = True __IS_DELEGATED__ = True

View File

@ -13,7 +13,9 @@ Development version
2.0.0 2.0.0
------ ------
- Drop backward compatibilities of 1.x. - Introduce new injections style for ``Callable``, ``Factory`` &
``Singleton`` providers.
- Increase performance of retrieving injections in 2 times (+100%).
- Drop providers: - Drop providers:
- ``Static`` - ``Static``
- ``Value`` - ``Value``
@ -21,6 +23,7 @@ Development version
- ``Class`` - ``Class``
- ``Config`` - ``Config``
- Drop ``Method`` injections. - Drop ``Method`` injections.
- Drop backward compatibilities of 1.x.
1.17.0 1.17.0
------ ------

View File

@ -1,8 +1,8 @@
Dependency Injector example Dependency Injector IoC containers example
=========================== ==========================================
Instructions for running: Instructions for running
.. code-block:: bash .. code-block:: bash
python main.py dependency-injector secret myself.jpg python main.py

View File

@ -0,0 +1,33 @@
"""Example of several Dependency Injector IoC containers."""
import sqlite3
import boto.s3.connection
import example.services
from dependency_injector import catalogs
from dependency_injector import providers
class Platform(catalogs.DeclarativeCatalog):
"""Catalog of platform service providers."""
database = providers.Singleton(sqlite3.connect, ':memory:')
s3 = providers.Singleton(boto.s3.connection.S3Connection,
aws_access_key_id='KEY',
aws_secret_access_key='SECRET')
class Services(catalogs.DeclarativeCatalog):
"""Catalog of business service providers."""
users = providers.Factory(example.services.Users,
db=Platform.database)
photos = providers.Factory(example.services.Photos,
db=Platform.database,
s3=Platform.s3)
auth = providers.Factory(example.services.Auth,
db=Platform.database,
token_ttl=3600)

View File

@ -0,0 +1,37 @@
"""Example of several Dependency Injector IoC containers.
Alternative injections definition style #1.
"""
import sqlite3
import boto.s3.connection
import example.services
from dependency_injector import catalogs
from dependency_injector import providers
class Platform(catalogs.DeclarativeCatalog):
"""Catalog of platform service providers."""
database = providers.Singleton(sqlite3.connect) \
.args(':memory:')
s3 = providers.Singleton(boto.s3.connection.S3Connection) \
.kwargs(aws_access_key_id='KEY',
aws_secret_access_key='SECRET')
class Services(catalogs.DeclarativeCatalog):
"""Catalog of business service providers."""
users = providers.Factory(example.services.Users) \
.kwargs(db=Platform.database)
photos = providers.Factory(example.services.Photos) \
.kwargs(db=Platform.database,
s3=Platform.s3)
auth = providers.Factory(example.services.Auth) \
.kwargs(db=Platform.database,
token_ttl=3600)

View File

@ -0,0 +1,37 @@
"""Example of several Dependency Injector IoC containers.
Alternative injections definition style #2.
"""
import sqlite3
import boto.s3.connection
import example.services
from dependency_injector import catalogs
from dependency_injector import providers
class Platform(catalogs.DeclarativeCatalog):
"""Catalog of platform service providers."""
database = providers.Singleton(sqlite3.connect)
database.args(':memory:')
s3 = providers.Singleton(boto.s3.connection.S3Connection)
s3.kwargs(aws_access_key_id='KEY',
aws_secret_access_key='SECRET')
class Services(catalogs.DeclarativeCatalog):
"""Catalog of business service providers."""
users = providers.Factory(example.services.Users)
users.kwargs(db=Platform.database)
photos = providers.Factory(example.services.Photos)
photos.kwargs(db=Platform.database,
s3=Platform.s3)
auth = providers.Factory(example.services.Auth)
auth.kwargs(db=Platform.database,
token_ttl=3600)

View File

@ -1,53 +1,19 @@
"""Dependency Injector example.""" """Dependency Injector @inject decorator example."""
import sys from dependency_injector.injections import inject
import sqlite3
from boto.s3.connection import S3Connection from catalogs import Services
from dependency_injector import catalogs
from dependency_injector import providers
from dependency_injector import injections
from example import services
class Platform(catalogs.DeclarativeCatalog): @inject(users_service=Services.users)
"""Catalog of platform service providers.""" @inject(auth_service=Services.auth)
@inject(photos_service=Services.photos)
database = providers.Singleton(sqlite3.connect, ':memory:') def main(users_service, auth_service, photos_service):
s3 = providers.Singleton(S3Connection,
aws_access_key_id='KEY',
aws_secret_access_key='SECRET')
class Services(catalogs.DeclarativeCatalog):
"""Catalog of business service providers."""
users = providers.Factory(services.Users,
db=Platform.database)
photos = providers.Factory(services.Photos,
db=Platform.database,
s3=Platform.s3)
auth = providers.Factory(services.Auth,
db=Platform.database,
token_ttl=3600)
@injections.inject(users_service=Services.users)
@injections.inject(auth_service=Services.auth)
@injections.inject(photos_service=Services.photos)
def main(argv, users_service, auth_service, photos_service):
"""Main function.""" """Main function."""
login, password, photo_path = argv[1:] user = users_service.get_user('user')
auth_service.authenticate(user, 'secret')
user = users_service.get_user(login) photos_service.upload_photo(user['id'], 'photo.jpg')
auth_service.authenticate(user, password)
photos_service.upload_photo(user['id'], photo_path)
if __name__ == '__main__': if __name__ == '__main__':
main(sys.argv) main()

View File

@ -382,7 +382,8 @@ class CopyingTests(unittest.TestCase):
"""Test catalog providers copying.""" """Test catalog providers copying."""
class CatalogA(catalogs.DeclarativeCatalog): class CatalogA(catalogs.DeclarativeCatalog):
p11 = providers.Object(0) p11 = providers.Object(0)
p12 = providers.Factory(dict, p11=p11) p12 = providers.Factory(dict) \
.kwargs(p11=p11)
@catalogs.copy(CatalogA) @catalogs.copy(CatalogA)
class CatalogA1(CatalogA): class CatalogA1(CatalogA):

View File

@ -2,12 +2,7 @@
import unittest2 as unittest import unittest2 as unittest
from dependency_injector import ( from dependency_injector import providers, utils, errors
providers,
injections,
utils,
errors,
)
class CallableTests(unittest.TestCase): class CallableTests(unittest.TestCase):
@ -35,60 +30,51 @@ class CallableTests(unittest.TestCase):
New simplified syntax. New simplified syntax.
""" """
provider = providers.Callable(self.example, 1, 2, 3, 4) provider = providers.Callable(self.example) \
.args(1, 2, 3, 4)
self.assertTupleEqual(provider(), (1, 2, 3, 4)) self.assertTupleEqual(provider(), (1, 2, 3, 4))
def test_call_with_keyword_args(self): def test_call_with_keyword_args(self):
"""Test call with keyword args. """Test call with keyword args."""
provider = providers.Callable(self.example) \
.kwargs(arg1=1, arg2=2, arg3=3, arg4=4)
New simplified syntax.
"""
provider = providers.Callable(self.example,
arg1=1,
arg2=2,
arg3=3,
arg4=4)
self.assertTupleEqual(provider(), (1, 2, 3, 4)) self.assertTupleEqual(provider(), (1, 2, 3, 4))
def test_call_with_positional_and_keyword_args(self): def test_call_with_positional_and_keyword_args(self):
"""Test call with positional and keyword args. """Test call with positional and keyword args."""
provider = providers.Callable(self.example) \
.args(1, 2) \
.kwargs(arg3=3, arg4=4)
Simplified syntax of positional and keyword arg injections.
"""
provider = providers.Callable(self.example, 1, 2, arg3=3, arg4=4)
self.assertTupleEqual(provider(), (1, 2, 3, 4))
def test_call_with_positional_and_keyword_args_extended_syntax(self):
"""Test call with positional and keyword args.
Extended syntax of positional and keyword arg injections.
"""
provider = providers.Callable(self.example,
injections.Arg(1),
injections.Arg(2),
injections.KwArg('arg3', 3),
injections.KwArg('arg4', 4))
self.assertTupleEqual(provider(), (1, 2, 3, 4)) self.assertTupleEqual(provider(), (1, 2, 3, 4))
def test_call_with_context_args(self): def test_call_with_context_args(self):
"""Test call with context args.""" """Test call with context args."""
provider = providers.Callable(self.example, 1, 2) provider = providers.Callable(self.example) \
.args(1, 2)
self.assertTupleEqual(provider(3, 4), (1, 2, 3, 4)) self.assertTupleEqual(provider(3, 4), (1, 2, 3, 4))
def test_call_with_context_kwargs(self): def test_call_with_context_kwargs(self):
"""Test call with context kwargs.""" """Test call with context kwargs."""
provider = providers.Callable(self.example, provider = providers.Callable(self.example) \
injections.KwArg('arg1', 1)) .kwargs(arg1=1)
self.assertTupleEqual(provider(arg2=2, arg3=3, arg4=4), (1, 2, 3, 4)) self.assertTupleEqual(provider(arg2=2, arg3=3, arg4=4), (1, 2, 3, 4))
def test_call_with_context_args_and_kwargs(self): def test_call_with_context_args_and_kwargs(self):
"""Test call with context args and kwargs.""" """Test call with context args and kwargs."""
provider = providers.Callable(self.example, 1) provider = providers.Callable(self.example) \
.args(1)
self.assertTupleEqual(provider(2, arg3=3, arg4=4), (1, 2, 3, 4)) self.assertTupleEqual(provider(2, arg3=3, arg4=4), (1, 2, 3, 4))
def test_call_overridden(self): def test_call_overridden(self):
"""Test creation of new instances on overridden provider.""" """Test creation of new instances on overridden provider."""
provider = providers.Callable(self.example) provider = providers.Callable(self.example)
provider.override(providers.Object((4, 3, 2, 1))) provider.override(providers.Object((4, 3, 2, 1)))
provider.override(providers.Object((1, 2, 3, 4))) provider.override(providers.Object((1, 2, 3, 4)))
@ -96,24 +82,20 @@ class CallableTests(unittest.TestCase):
def test_injections(self): def test_injections(self):
"""Test getting a full list of injections using injections property.""" """Test getting a full list of injections using injections property."""
provider = providers.Callable(self.example, 1, 2, arg3=3, arg4=4) provider = providers.Callable(self.example) \
.args(1, 2) \
.kwargs(arg3=3, arg4=4)
self.assertEquals(len(provider.injections), 4) self.assertEquals(len(provider.injections), 4)
def test_repr(self): def test_repr(self):
"""Test representation of provider.""" """Test representation of provider."""
provider = providers.Callable(self.example, provider = providers.Callable(self.example) \
injections.KwArg( .kwargs(arg1=providers.Factory(dict),
'arg1', arg2=providers.Factory(list),
providers.Factory(dict)), arg3=providers.Factory(set),
injections.KwArg( arg4=providers.Factory(tuple))
'arg2',
providers.Factory(list)),
injections.KwArg(
'arg3',
providers.Factory(set)),
injections.KwArg(
'arg4',
providers.Factory(tuple)))
self.assertEqual(repr(provider), self.assertEqual(repr(provider),
'<dependency_injector.providers.callable.' '<dependency_injector.providers.callable.'
'Callable({0}) at {1}>'.format( 'Callable({0}) at {1}>'.format(

View File

@ -2,12 +2,7 @@
import unittest2 as unittest import unittest2 as unittest
from dependency_injector import ( from dependency_injector import providers, injections, utils, errors
providers,
injections,
utils,
errors,
)
class Example(object): class Example(object):
@ -47,7 +42,8 @@ class FactoryTests(unittest.TestCase):
provided_type = Example provided_type = Example
example_provider = ExampleProvider(Example, 1, 2) example_provider = ExampleProvider(Example) \
.args(1, 2)
self.assertIsInstance(example_provider(), Example) self.assertIsInstance(example_provider(), Example)
@ -61,7 +57,8 @@ class FactoryTests(unittest.TestCase):
class NewExampe(Example): class NewExampe(Example):
"""Example class subclass.""" """Example class subclass."""
example_provider = ExampleProvider(NewExampe, 1, 2) example_provider = ExampleProvider(NewExampe) \
.args(1, 2)
self.assertIsInstance(example_provider(), NewExampe) self.assertIsInstance(example_provider(), NewExampe)
@ -76,8 +73,9 @@ class FactoryTests(unittest.TestCase):
ExampleProvider(list) ExampleProvider(list)
def test_call(self): def test_call(self):
"""Test creation of new instances.""" """Test call."""
provider = providers.Factory(Example) provider = providers.Factory(Example)
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -86,11 +84,9 @@ class FactoryTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_init_positional_args(self): def test_call_with_init_positional_args(self):
"""Test creation of new instances with init positional args. """Test call with init positional args."""
provider = providers.Factory(Example) \
New simplified syntax. .args('i1', 'i2')
"""
provider = providers.Factory(Example, 'i1', 'i2')
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -106,11 +102,9 @@ class FactoryTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_init_keyword_args(self): def test_call_with_init_keyword_args(self):
"""Test creation of new instances with init keyword args. """Test call with init keyword args."""
provider = providers.Factory(Example) \
New simplified syntax. .kwargs(init_arg1='i1', init_arg2='i2')
"""
provider = providers.Factory(Example, init_arg1='i1', init_arg2='i2')
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -126,33 +120,10 @@ class FactoryTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_init_positional_and_keyword_args(self): def test_call_with_init_positional_and_keyword_args(self):
"""Test creation of new instances with init positional and keyword args. """Test call with init positional and keyword args."""
provider = providers.Factory(Example) \
Simplified syntax of positional and keyword arg injections. .args('i1') \
""" .kwargs(init_arg2='i2')
provider = providers.Factory(Example, 'i1', init_arg2='i2')
instance1 = provider()
instance2 = provider()
self.assertEqual(instance1.init_arg1, 'i1')
self.assertEqual(instance1.init_arg2, 'i2')
self.assertEqual(instance2.init_arg1, 'i1')
self.assertEqual(instance2.init_arg2, 'i2')
self.assertIsNot(instance1, instance2)
self.assertIsInstance(instance1, Example)
self.assertIsInstance(instance2, Example)
def test_call_with_init_positional_and_keyword_args_extended_syntax(self):
"""Test creation of new instances with init positional and keyword args.
Extended syntax of positional and keyword arg injections.
"""
provider = providers.Factory(Example,
injections.Arg('i1'),
injections.KwArg('init_arg2', 'i2'))
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -168,10 +139,9 @@ class FactoryTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_attributes(self): def test_call_with_attributes(self):
"""Test creation of new instances with attribute injections.""" """Test call with attribute injections."""
provider = providers.Factory(Example, provider = providers.Factory(Example) \
injections.Attribute('attribute1', 'a1'), .attributes(attribute1='a1', attribute2='a2')
injections.Attribute('attribute2', 'a2'))
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -187,8 +157,10 @@ class FactoryTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_context_args(self): def test_call_with_context_args(self):
"""Test creation of new instances with context args.""" """Test call with context args."""
provider = providers.Factory(Example, 11, 22) provider = providers.Factory(Example) \
.args(11, 22)
instance = provider(33, 44) instance = provider(33, 44)
self.assertEqual(instance.init_arg1, 11) self.assertEqual(instance.init_arg1, 11)
@ -197,9 +169,9 @@ class FactoryTests(unittest.TestCase):
self.assertEqual(instance.init_arg4, 44) self.assertEqual(instance.init_arg4, 44)
def test_call_with_context_kwargs(self): def test_call_with_context_kwargs(self):
"""Test creation of new instances with context kwargs.""" """Test call with context kwargs."""
provider = providers.Factory(Example, provider = providers.Factory(Example) \
injections.KwArg('init_arg1', 1)) .kwargs(init_arg1=1)
instance1 = provider(init_arg2=22) instance1 = provider(init_arg2=22)
self.assertEqual(instance1.init_arg1, 1) self.assertEqual(instance1.init_arg1, 1)
@ -210,8 +182,10 @@ class FactoryTests(unittest.TestCase):
self.assertEqual(instance2.init_arg2, 22) self.assertEqual(instance2.init_arg2, 22)
def test_call_with_context_args_and_kwargs(self): def test_call_with_context_args_and_kwargs(self):
"""Test creation of new instances with context args and kwargs.""" """Test call with context args and kwargs."""
provider = providers.Factory(Example, 11) provider = providers.Factory(Example) \
.args(11)
instance = provider(22, init_arg3=33, init_arg4=44) instance = provider(22, init_arg3=33, init_arg4=44)
self.assertEqual(instance.init_arg1, 11) self.assertEqual(instance.init_arg1, 11)
@ -220,7 +194,7 @@ class FactoryTests(unittest.TestCase):
self.assertEqual(instance.init_arg4, 44) self.assertEqual(instance.init_arg4, 44)
def test_call_overridden(self): def test_call_overridden(self):
"""Test creation of new instances on overridden provider.""" """Test call on overridden provider."""
provider = providers.Factory(Example) provider = providers.Factory(Example)
overriding_provider1 = providers.Factory(dict) overriding_provider1 = providers.Factory(dict)
overriding_provider2 = providers.Factory(list) overriding_provider2 = providers.Factory(list)
@ -237,20 +211,19 @@ class FactoryTests(unittest.TestCase):
def test_injections(self): def test_injections(self):
"""Test getting a full list of injections using injections property.""" """Test getting a full list of injections using injections property."""
provider = providers.Factory(Example, provider = providers.Factory(Example) \
injections.Arg(1), .args(1) \
injections.KwArg('init_arg2', 2), .kwargs(init_arg2=2) \
injections.Attribute('attribute1', 3), .attributes(attribute1=3, attribute2=4)
injections.Attribute('attribute2', 4))
self.assertEquals(len(provider.injections), 4) self.assertEquals(len(provider.injections), 4)
def test_repr(self): def test_repr(self):
"""Test representation of provider.""" """Test representation of provider."""
provider = providers.Factory(Example, provider = providers.Factory(Example) \
injections.KwArg('init_arg1', .kwargs(init_arg1=providers.Factory(dict),
providers.Factory(dict)), init_arg2=providers.Factory(list))
injections.KwArg('init_arg2',
providers.Factory(list)))
self.assertEqual(repr(provider), self.assertEqual(repr(provider),
'<dependency_injector.providers.creational.' '<dependency_injector.providers.creational.'
'Factory({0}) at {1}>'.format( 'Factory({0}) at {1}>'.format(
@ -300,7 +273,8 @@ class SingletonTests(unittest.TestCase):
provided_type = Example provided_type = Example
example_provider = ExampleProvider(Example, 1, 2) example_provider = ExampleProvider(Example) \
.args(1, 2)
self.assertIsInstance(example_provider(), Example) self.assertIsInstance(example_provider(), Example)
@ -314,7 +288,8 @@ class SingletonTests(unittest.TestCase):
class NewExampe(Example): class NewExampe(Example):
"""Example class subclass.""" """Example class subclass."""
example_provider = ExampleProvider(NewExampe, 1, 2) example_provider = ExampleProvider(NewExampe) \
.args(1, 2)
self.assertIsInstance(example_provider(), NewExampe) self.assertIsInstance(example_provider(), NewExampe)
@ -331,6 +306,7 @@ class SingletonTests(unittest.TestCase):
def test_call(self): def test_call(self):
"""Test getting of instances.""" """Test getting of instances."""
provider = providers.Singleton(Example) provider = providers.Singleton(Example)
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -339,11 +315,9 @@ class SingletonTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_init_positional_args(self): def test_call_with_init_positional_args(self):
"""Test getting of instances with init positional args. """Test getting of instances with init positional args."""
provider = providers.Singleton(Example) \
New simplified syntax. .args('i1', 'i2')
"""
provider = providers.Singleton(Example, 'i1', 'i2')
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -359,11 +333,9 @@ class SingletonTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_init_keyword_args(self): def test_call_with_init_keyword_args(self):
"""Test getting of instances with init keyword args. """Test getting of instances with init keyword args."""
provider = providers.Singleton(Example) \
New simplified syntax. .kwargs(init_arg1='i1', init_arg2='i2')
"""
provider = providers.Singleton(Example, init_arg1='i1', init_arg2='i2')
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -379,33 +351,10 @@ class SingletonTests(unittest.TestCase):
self.assertIsInstance(instance2, Example) self.assertIsInstance(instance2, Example)
def test_call_with_init_positional_and_keyword_args(self): def test_call_with_init_positional_and_keyword_args(self):
"""Test getting of instances with init positional and keyword args. """Test getting of instances with init positional and keyword args."""
provider = providers.Singleton(Example) \
Simplified syntax of positional and keyword arg injections. .args('i1') \
""" .kwargs(init_arg2='i2')
provider = providers.Singleton(Example, 'i1', init_arg2='i2')
instance1 = provider()
instance2 = provider()
self.assertEqual(instance1.init_arg1, 'i1')
self.assertEqual(instance1.init_arg2, 'i2')
self.assertEqual(instance2.init_arg1, 'i1')
self.assertEqual(instance2.init_arg2, 'i2')
self.assertIs(instance1, instance2)
self.assertIsInstance(instance1, Example)
self.assertIsInstance(instance2, Example)
def test_call_with_init_positional_and_keyword_args_extended_syntax(self):
"""Test getting of instances with init positional and keyword args.
Extended syntax of positional and keyword arg injections.
"""
provider = providers.Singleton(Example,
injections.Arg('i1'),
injections.KwArg('init_arg2', 'i2'))
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -422,11 +371,8 @@ class SingletonTests(unittest.TestCase):
def test_call_with_attributes(self): def test_call_with_attributes(self):
"""Test getting of instances with attribute injections.""" """Test getting of instances with attribute injections."""
provider = providers.Singleton(Example, provider = providers.Singleton(Example) \
injections.Attribute('attribute1', .attributes(attribute1='a1', attribute2='a2')
'a1'),
injections.Attribute('attribute2',
'a2'))
instance1 = provider() instance1 = provider()
instance2 = provider() instance2 = provider()
@ -444,6 +390,7 @@ class SingletonTests(unittest.TestCase):
def test_call_with_context_args(self): def test_call_with_context_args(self):
"""Test getting of instances with context args.""" """Test getting of instances with context args."""
provider = providers.Singleton(Example) provider = providers.Singleton(Example)
instance = provider(11, 22) instance = provider(11, 22)
self.assertEqual(instance.init_arg1, 11) self.assertEqual(instance.init_arg1, 11)
@ -451,8 +398,8 @@ class SingletonTests(unittest.TestCase):
def test_call_with_context_kwargs(self): def test_call_with_context_kwargs(self):
"""Test getting of instances with context kwargs.""" """Test getting of instances with context kwargs."""
provider = providers.Singleton(Example, provider = providers.Singleton(Example) \
injections.KwArg('init_arg1', 1)) .kwargs(init_arg1=1)
instance1 = provider(init_arg2=22) instance1 = provider(init_arg2=22)
self.assertEqual(instance1.init_arg1, 1) self.assertEqual(instance1.init_arg1, 1)
@ -465,7 +412,8 @@ class SingletonTests(unittest.TestCase):
def test_call_with_context_args_and_kwargs(self): def test_call_with_context_args_and_kwargs(self):
"""Test getting of instances with context args and kwargs.""" """Test getting of instances with context args and kwargs."""
provider = providers.Singleton(Example, 11) provider = providers.Singleton(Example) \
.args(11)
instance = provider(22, init_arg3=33, init_arg4=44) instance = provider(22, init_arg3=33, init_arg4=44)
self.assertEqual(instance.init_arg1, 11) self.assertEqual(instance.init_arg1, 11)
@ -489,35 +437,13 @@ class SingletonTests(unittest.TestCase):
self.assertIsInstance(instance1, object) self.assertIsInstance(instance1, object)
self.assertIsInstance(instance2, object) self.assertIsInstance(instance2, object)
def test_provides_attr(self):
"""Test provides attribute."""
provider = providers.Singleton(Example)
self.assertIs(provider.provides, Example)
def test_args_attr(self):
"""Test args attribute."""
provider = providers.Singleton(Example, 1, 2)
self.assertEquals(len(provider.args), 2)
def test_kwargs_attr(self):
"""Test kwargs attribute."""
provider = providers.Singleton(Example, init_arg1=1, init_arg2=2)
self.assertEquals(len(provider.kwargs), 2)
def test_attributes_attr(self):
"""Test attributes attribute."""
provider = providers.Singleton(Example,
injections.Attribute('attribute1', 1),
injections.Attribute('attribute2', 2))
self.assertEquals(len(provider.attributes), 2)
def test_injections(self): def test_injections(self):
"""Test getting a full list of injections using injections property.""" """Test getting a full list of injections using injections property."""
provider = providers.Singleton(Example, provider = providers.Singleton(Example) \
injections.Arg(1), .args(1) \
injections.KwArg('init_arg2', 2), .kwargs(init_arg2=2) \
injections.Attribute('attribute1', 3), .attributes(attribute1=3, attribute2=4)
injections.Attribute('attribute2', 4))
self.assertEquals(len(provider.injections), 4) self.assertEquals(len(provider.injections), 4)
def test_reset(self): def test_reset(self):
@ -536,13 +462,10 @@ class SingletonTests(unittest.TestCase):
def test_repr(self): def test_repr(self):
"""Test representation of provider.""" """Test representation of provider."""
provider = providers.Singleton(Example, provider = providers.Singleton(Example) \
injections.KwArg( .kwargs(init_arg1=providers.Factory(dict),
'init_arg1', init_arg2=providers.Factory(list))
providers.Factory(dict)),
injections.KwArg(
'init_arg2',
providers.Factory(list)))
self.assertEqual(repr(provider), self.assertEqual(repr(provider),
'<dependency_injector.providers.creational.' '<dependency_injector.providers.creational.'
'Singleton({0}) at {1}>'.format( 'Singleton({0}) at {1}>'.format(

View File

@ -7,6 +7,8 @@ from dependency_injector import (
utils, utils,
) )
# TODO: move to test_base
class ObjectProviderTests(unittest.TestCase): class ObjectProviderTests(unittest.TestCase):
"""Object provider tests.""" """Object provider tests."""

View File

@ -19,12 +19,12 @@ class InjectionTests(unittest.TestCase):
def test_value_with_scalar_injectable(self): def test_value_with_scalar_injectable(self):
"""Test Injection value property with scalar value.""" """Test Injection value property with scalar value."""
injection = injections.Injection('some_value') injection = injections.Injection('some_value')
self.assertEqual(injection.value, 'some_value') self.assertEqual(injection.get_value(), 'some_value')
def test_value_with_provider_injectable(self): def test_value_with_provider_injectable(self):
"""Test Injection value property with provider.""" """Test Injection value property with provider."""
injection = injections.Injection(providers.Factory(object)) injection = injections.Injection(providers.Factory(object))
self.assertIsInstance(injection.value, object) self.assertIsInstance(injection.get_value(), object)
def test_value_with_catalog_bundle_injectable(self): def test_value_with_catalog_bundle_injectable(self):
"""Test Injection value property with catalog bundle.""" """Test Injection value property with catalog bundle."""
@ -35,7 +35,7 @@ class InjectionTests(unittest.TestCase):
injection = injections.Injection( injection = injections.Injection(
TestCatalog.Bundle(TestCatalog.provider)) TestCatalog.Bundle(TestCatalog.provider))
self.assertIsInstance(injection.value, TestCatalog.Bundle) self.assertIsInstance(injection.get_value(), TestCatalog.Bundle)
def test_repr(self): def test_repr(self):
"""Test Injection representation.""" """Test Injection representation."""