mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-25 11:04:01 +03:00
0.9.5 release
This commit is contained in:
parent
1bfa0be26b
commit
6cbd0ce7fc
|
@ -8,6 +8,7 @@ from .providers import Delegate
|
||||||
from .providers import Factory
|
from .providers import Factory
|
||||||
from .providers import Singleton
|
from .providers import Singleton
|
||||||
from .providers import ExternalDependency
|
from .providers import ExternalDependency
|
||||||
|
from .providers import StaticProvider
|
||||||
from .providers import Class
|
from .providers import Class
|
||||||
from .providers import Object
|
from .providers import Object
|
||||||
from .providers import Function
|
from .providers import Function
|
||||||
|
@ -43,6 +44,7 @@ __all__ = (
|
||||||
'Factory',
|
'Factory',
|
||||||
'Singleton',
|
'Singleton',
|
||||||
'ExternalDependency',
|
'ExternalDependency',
|
||||||
|
'StaticProvider',
|
||||||
'Class',
|
'Class',
|
||||||
'Object',
|
'Object',
|
||||||
'Function',
|
'Function',
|
||||||
|
|
|
@ -32,19 +32,19 @@ class AbstractCatalog(object):
|
||||||
|
|
||||||
providers = dict()
|
providers = dict()
|
||||||
|
|
||||||
__slots__ = ('_used_providers',)
|
__slots__ = ('used_providers',)
|
||||||
|
|
||||||
def __init__(self, *used_providers):
|
def __init__(self, *used_providers):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
self._used_providers = set(used_providers)
|
self.used_providers = set(used_providers)
|
||||||
|
|
||||||
def __getattribute__(self, item):
|
def __getattribute__(self, item):
|
||||||
"""Return providers."""
|
"""Return providers."""
|
||||||
attribute = super(AbstractCatalog, self).__getattribute__(item)
|
attribute = super(AbstractCatalog, self).__getattribute__(item)
|
||||||
if item in ('providers', '_used_providers',):
|
if item in ('providers', 'used_providers',):
|
||||||
return attribute
|
return attribute
|
||||||
|
|
||||||
if attribute not in self._used_providers:
|
if attribute not in self.used_providers:
|
||||||
raise Error('Provider \'{0}\' '.format(item) +
|
raise Error('Provider \'{0}\' '.format(item) +
|
||||||
'is not listed in dependencies')
|
'is not listed in dependencies')
|
||||||
return attribute
|
return attribute
|
||||||
|
|
|
@ -62,8 +62,8 @@ def inject(*args, **kwargs):
|
||||||
|
|
||||||
def decorator(callback):
|
def decorator(callback):
|
||||||
"""Dependency injection decorator."""
|
"""Dependency injection decorator."""
|
||||||
if hasattr(callback, '_injections'):
|
if hasattr(callback, 'injections'):
|
||||||
callback._injections += injections
|
callback.injections += injections
|
||||||
return callback
|
return callback
|
||||||
|
|
||||||
@six.wraps(callback)
|
@six.wraps(callback)
|
||||||
|
@ -71,9 +71,9 @@ def inject(*args, **kwargs):
|
||||||
"""Decorated with dependency injection callback."""
|
"""Decorated with dependency injection callback."""
|
||||||
return callback(*args,
|
return callback(*args,
|
||||||
**get_injectable_kwargs(kwargs,
|
**get_injectable_kwargs(kwargs,
|
||||||
decorated._injections))
|
decorated.injections))
|
||||||
|
|
||||||
decorated._injections = injections
|
decorated.injections = injections
|
||||||
|
|
||||||
return decorated
|
return decorated
|
||||||
return decorator
|
return decorator
|
||||||
|
|
|
@ -19,15 +19,15 @@ class Provider(object):
|
||||||
"""Base provider class."""
|
"""Base provider class."""
|
||||||
|
|
||||||
__IS_PROVIDER__ = True
|
__IS_PROVIDER__ = True
|
||||||
__slots__ = ('_overridden',)
|
__slots__ = ('overridden_by',)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
self._overridden = None
|
self.overridden_by = None
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
if self._overridden:
|
if self.overridden_by:
|
||||||
return self.last_overriding(*args, **kwargs)
|
return self.last_overriding(*args, **kwargs)
|
||||||
return self._provide(*args, **kwargs)
|
return self._provide(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -46,52 +46,52 @@ class Provider(object):
|
||||||
|
|
||||||
def override(self, provider):
|
def override(self, provider):
|
||||||
"""Override provider with another provider."""
|
"""Override provider with another provider."""
|
||||||
if not self._overridden:
|
if not self.is_overridden:
|
||||||
self._overridden = (ensure_is_provider(provider),)
|
self.overridden_by = (ensure_is_provider(provider),)
|
||||||
else:
|
else:
|
||||||
self._overridden += (ensure_is_provider(provider),)
|
self.overridden_by += (ensure_is_provider(provider),)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_overridden(self):
|
def is_overridden(self):
|
||||||
"""Check if provider is overridden by another provider."""
|
"""Check if provider is overridden by another provider."""
|
||||||
return bool(self._overridden)
|
return bool(self.overridden_by)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def last_overriding(self):
|
def last_overriding(self):
|
||||||
"""Return last overriding provider."""
|
"""Return last overriding provider."""
|
||||||
try:
|
try:
|
||||||
return self._overridden[-1]
|
return self.overridden_by[-1]
|
||||||
except (TypeError, IndexError):
|
except (TypeError, IndexError):
|
||||||
raise Error('Provider {0} is not overridden'.format(str(self)))
|
raise Error('Provider {0} is not overridden'.format(str(self)))
|
||||||
|
|
||||||
def reset_last_overriding(self):
|
def reset_last_overriding(self):
|
||||||
"""Reset last overriding provider."""
|
"""Reset last overriding provider."""
|
||||||
if not self._overridden:
|
if not self.is_overridden:
|
||||||
raise Error('Provider {0} is not overridden'.format(str(self)))
|
raise Error('Provider {0} is not overridden'.format(str(self)))
|
||||||
self._overridden = self._overridden[:-1]
|
self.overridden_by = self.overridden_by[:-1]
|
||||||
|
|
||||||
def reset_override(self):
|
def reset_override(self):
|
||||||
"""Reset all overriding providers."""
|
"""Reset all overriding providers."""
|
||||||
self._overridden = None
|
self.overridden_by = None
|
||||||
|
|
||||||
|
|
||||||
class Delegate(Provider):
|
class Delegate(Provider):
|
||||||
|
|
||||||
"""Provider's delegate."""
|
"""Provider's delegate."""
|
||||||
|
|
||||||
__slots__ = ('_delegated',)
|
__slots__ = ('delegated',)
|
||||||
|
|
||||||
def __init__(self, delegated):
|
def __init__(self, delegated):
|
||||||
"""Initializer.
|
"""Initializer.
|
||||||
|
|
||||||
:type delegated: Provider
|
:type delegated: Provider
|
||||||
"""
|
"""
|
||||||
self._delegated = ensure_is_provider(delegated)
|
self.delegated = ensure_is_provider(delegated)
|
||||||
super(Delegate, self).__init__()
|
super(Delegate, self).__init__()
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
return self._delegated
|
return self.delegated
|
||||||
|
|
||||||
|
|
||||||
class Factory(Provider):
|
class Factory(Provider):
|
||||||
|
@ -101,49 +101,44 @@ class Factory(Provider):
|
||||||
Factory provider creates new instance of specified class on every call.
|
Factory provider creates new instance of specified class on every call.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('_provides', '_kwargs', '_attributes', '_methods')
|
__slots__ = ('provides', 'kwargs', 'attributes', 'methods')
|
||||||
|
|
||||||
def __init__(self, provides, *injections, **kwargs):
|
def __init__(self, provides, *injections, **kwargs):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
if not callable(provides):
|
if not callable(provides):
|
||||||
raise Error('Factory provider expects to get callable, ' +
|
raise Error('Factory provider expects to get callable, ' +
|
||||||
'got {0} instead'.format(str(provides)))
|
'got {0} instead'.format(str(provides)))
|
||||||
self._provides = provides
|
self.provides = provides
|
||||||
self._kwargs = tuple(injection
|
self.kwargs = tuple(injection
|
||||||
for injection in injections
|
for injection in injections
|
||||||
if is_kwarg_injection(injection))
|
if is_kwarg_injection(injection))
|
||||||
if kwargs:
|
if kwargs:
|
||||||
self._kwargs += tuple(KwArg(name, value)
|
self.kwargs += tuple(KwArg(name, value)
|
||||||
for name, value in six.iteritems(kwargs))
|
for name, value in six.iteritems(kwargs))
|
||||||
self._attributes = tuple(injection
|
self.attributes = tuple(injection
|
||||||
for injection in injections
|
for injection in injections
|
||||||
if is_attribute_injection(injection))
|
if is_attribute_injection(injection))
|
||||||
self._methods = tuple(injection
|
self.methods = tuple(injection
|
||||||
for injection in injections
|
for injection in injections
|
||||||
if is_method_injection(injection))
|
if is_method_injection(injection))
|
||||||
super(Factory, self).__init__()
|
super(Factory, self).__init__()
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
instance = self._provides(*args,
|
instance = self.provides(*args,
|
||||||
**get_injectable_kwargs(kwargs,
|
**get_injectable_kwargs(kwargs,
|
||||||
self._kwargs))
|
self.kwargs))
|
||||||
for attribute in self._attributes:
|
for attribute in self.attributes:
|
||||||
setattr(instance, attribute.name, attribute.value)
|
setattr(instance, attribute.name, attribute.value)
|
||||||
for method in self._methods:
|
for method in self.methods:
|
||||||
getattr(instance, method.name)(method.value)
|
getattr(instance, method.name)(method.value)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
@property
|
||||||
class NewInstance(Factory):
|
def injections(self):
|
||||||
|
"""Return tuple of all injections."""
|
||||||
"""NewInstance provider.
|
return self.kwargs + self.attributes + self.methods
|
||||||
|
|
||||||
It is synonym of Factory provider. NewInstance provider is considered to
|
|
||||||
be deprecated, but will be able to use for further backward
|
|
||||||
compatibility.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class Singleton(Provider):
|
class Singleton(Provider):
|
||||||
|
@ -153,24 +148,24 @@ class Singleton(Provider):
|
||||||
Singleton provider will create instance once and return it on every call.
|
Singleton provider will create instance once and return it on every call.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('_instance', '_factory')
|
__slots__ = ('instance', 'factory')
|
||||||
|
|
||||||
def __init__(self, provides, *injections, **kwargs):
|
def __init__(self, provides, *injections, **kwargs):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
self._instance = None
|
self.instance = None
|
||||||
self._factory = Factory(provides, *injections, **kwargs)
|
self.factory = Factory(provides, *injections, **kwargs)
|
||||||
super(Singleton, self).__init__()
|
super(Singleton, self).__init__()
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
with GLOBAL_LOCK:
|
with GLOBAL_LOCK:
|
||||||
if not self._instance:
|
if not self.instance:
|
||||||
self._instance = self._factory(*args, **kwargs)
|
self.instance = self.factory(*args, **kwargs)
|
||||||
return self._instance
|
return self.instance
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""Reset instance."""
|
"""Reset instance."""
|
||||||
self._instance = None
|
self.instance = None
|
||||||
|
|
||||||
|
|
||||||
class ExternalDependency(Provider):
|
class ExternalDependency(Provider):
|
||||||
|
@ -181,26 +176,26 @@ class ExternalDependency(Provider):
|
||||||
the client's code, but it's interface is known.
|
the client's code, but it's interface is known.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('_instance_of',)
|
__slots__ = ('instance_of',)
|
||||||
|
|
||||||
def __init__(self, instance_of):
|
def __init__(self, instance_of):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
if not isinstance(instance_of, six.class_types):
|
if not isinstance(instance_of, six.class_types):
|
||||||
raise Error('ExternalDependency provider expects to get class, ' +
|
raise Error('ExternalDependency provider expects to get class, ' +
|
||||||
'got {0} instead'.format(str(instance_of)))
|
'got {0} instead'.format(str(instance_of)))
|
||||||
self._instance_of = instance_of
|
self.instance_of = instance_of
|
||||||
super(ExternalDependency, self).__init__()
|
super(ExternalDependency, self).__init__()
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
if not self._overridden:
|
if not self.is_overridden:
|
||||||
raise Error('Dependency is not defined')
|
raise Error('Dependency is not defined')
|
||||||
|
|
||||||
instance = self.last_overriding(*args, **kwargs)
|
instance = self.last_overriding(*args, **kwargs)
|
||||||
|
|
||||||
if not isinstance(instance, self._instance_of):
|
if not isinstance(instance, self.instance_of):
|
||||||
raise Error('{0} is not an '.format(instance) +
|
raise Error('{0} is not an '.format(instance) +
|
||||||
'instance of {0}'.format(self._instance_of))
|
'instance of {0}'.format(self.instance_of))
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
@ -209,7 +204,7 @@ class ExternalDependency(Provider):
|
||||||
return self.override(provider)
|
return self.override(provider)
|
||||||
|
|
||||||
|
|
||||||
class _StaticProvider(Provider):
|
class StaticProvider(Provider):
|
||||||
|
|
||||||
"""Static provider.
|
"""Static provider.
|
||||||
|
|
||||||
|
@ -217,34 +212,34 @@ class _StaticProvider(Provider):
|
||||||
it got on input.
|
it got on input.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('_provides',)
|
__slots__ = ('provides',)
|
||||||
|
|
||||||
def __init__(self, provides):
|
def __init__(self, provides):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
self._provides = provides
|
self.provides = provides
|
||||||
super(_StaticProvider, self).__init__()
|
super(StaticProvider, self).__init__()
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
return self._provides
|
return self.provides
|
||||||
|
|
||||||
|
|
||||||
class Class(_StaticProvider):
|
class Class(StaticProvider):
|
||||||
|
|
||||||
"""Class provider provides class."""
|
"""Class provider provides class."""
|
||||||
|
|
||||||
|
|
||||||
class Object(_StaticProvider):
|
class Object(StaticProvider):
|
||||||
|
|
||||||
"""Object provider provides object."""
|
"""Object provider provides object."""
|
||||||
|
|
||||||
|
|
||||||
class Function(_StaticProvider):
|
class Function(StaticProvider):
|
||||||
|
|
||||||
"""Function provider provides function."""
|
"""Function provider provides function."""
|
||||||
|
|
||||||
|
|
||||||
class Value(_StaticProvider):
|
class Value(StaticProvider):
|
||||||
|
|
||||||
"""Value provider provides value."""
|
"""Value provider provides value."""
|
||||||
|
|
||||||
|
@ -257,21 +252,21 @@ class Callable(Provider):
|
||||||
with some predefined dependency injections.
|
with some predefined dependency injections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('_callback', '_kwargs')
|
__slots__ = ('callback', 'kwargs')
|
||||||
|
|
||||||
def __init__(self, callback, **kwargs):
|
def __init__(self, callback, **kwargs):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
if not callable(callback):
|
if not callable(callback):
|
||||||
raise Error('Callable expected, got {0}'.format(str(callback)))
|
raise Error('Callable expected, got {0}'.format(str(callback)))
|
||||||
self._callback = callback
|
self.callback = callback
|
||||||
self._kwargs = tuple(KwArg(name, value)
|
self.kwargs = tuple(KwArg(name, value)
|
||||||
for name, value in six.iteritems(kwargs))
|
for name, value in six.iteritems(kwargs))
|
||||||
super(Callable, self).__init__()
|
super(Callable, self).__init__()
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
return self._callback(*args, **get_injectable_kwargs(kwargs,
|
return self.callback(*args, **get_injectable_kwargs(kwargs,
|
||||||
self._kwargs))
|
self.kwargs))
|
||||||
|
|
||||||
|
|
||||||
class Config(Provider):
|
class Config(Provider):
|
||||||
|
@ -283,22 +278,22 @@ class Config(Provider):
|
||||||
to create deferred config value provider.
|
to create deferred config value provider.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('_value',)
|
__slots__ = ('value',)
|
||||||
|
|
||||||
def __init__(self, value=None):
|
def __init__(self, value=None):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
if not value:
|
if not value:
|
||||||
value = dict()
|
value = dict()
|
||||||
self._value = value
|
self.value = value
|
||||||
super(Config, self).__init__()
|
super(Config, self).__init__()
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
"""Return instance of deferred config."""
|
"""Return instance of deferred config."""
|
||||||
return _ChildConfig(parents=(item,), root_config=self)
|
return ChildConfig(parents=(item,), root_config=self)
|
||||||
|
|
||||||
def _provide(self, paths=None):
|
def _provide(self, paths=None):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
value = self._value
|
value = self.value
|
||||||
if paths:
|
if paths:
|
||||||
for path in paths:
|
for path in paths:
|
||||||
try:
|
try:
|
||||||
|
@ -310,10 +305,10 @@ class Config(Provider):
|
||||||
|
|
||||||
def update_from(self, value):
|
def update_from(self, value):
|
||||||
"""Update current value from another one."""
|
"""Update current value from another one."""
|
||||||
self._value.update(value)
|
self.value.update(value)
|
||||||
|
|
||||||
|
|
||||||
class _ChildConfig(Provider):
|
class ChildConfig(Provider):
|
||||||
|
|
||||||
"""Child config provider.
|
"""Child config provider.
|
||||||
|
|
||||||
|
@ -321,19 +316,19 @@ class _ChildConfig(Provider):
|
||||||
the current path in the config tree.
|
the current path in the config tree.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('_parents', '_root_config')
|
__slots__ = ('parents', 'root_config')
|
||||||
|
|
||||||
def __init__(self, parents, root_config):
|
def __init__(self, parents, root_config):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
self._parents = parents
|
self.parents = parents
|
||||||
self._root_config = root_config
|
self.root_config = root_config
|
||||||
super(_ChildConfig, self).__init__()
|
super(ChildConfig, self).__init__()
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
"""Return instance of deferred config."""
|
"""Return instance of deferred config."""
|
||||||
return _ChildConfig(parents=self._parents + (item,),
|
return ChildConfig(parents=self.parents + (item,),
|
||||||
root_config=self._root_config)
|
root_config=self.root_config)
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
"""Return provided instance."""
|
"""Return provided instance."""
|
||||||
return self._root_config(self._parents)
|
return self.root_config(self.parents)
|
||||||
|
|
|
@ -13,6 +13,12 @@ Development version
|
||||||
|
|
||||||
- No featues.
|
- No featues.
|
||||||
|
|
||||||
|
0.9.5
|
||||||
|
-----
|
||||||
|
- Change provider attributes scope to public.
|
||||||
|
- Add ``di.Factory.injections`` attribute that represents a tuple of all
|
||||||
|
``di.Factory`` injections (including kwargs, attributes and methods).
|
||||||
|
|
||||||
0.9.4
|
0.9.4
|
||||||
-----
|
-----
|
||||||
- Add minor documentation fixes.
|
- Add minor documentation fixes.
|
||||||
|
|
|
@ -301,6 +301,20 @@ class FactoryTests(unittest.TestCase):
|
||||||
self.assertIsInstance(instance1, list)
|
self.assertIsInstance(instance1, list)
|
||||||
self.assertIsInstance(instance2, list)
|
self.assertIsInstance(instance2, list)
|
||||||
|
|
||||||
|
def test_injections(self):
|
||||||
|
"""Test getting a full list of injections using Factory.injections."""
|
||||||
|
provider = di.Factory(self.Example,
|
||||||
|
di.KwArg('init_arg1', 1),
|
||||||
|
di.KwArg('init_arg2', 2),
|
||||||
|
di.Attribute('attribute1', 3),
|
||||||
|
di.Attribute('attribute2', 4),
|
||||||
|
di.Method('method1', 5),
|
||||||
|
di.Method('method2', 6))
|
||||||
|
|
||||||
|
injections = provider.injections
|
||||||
|
|
||||||
|
self.assertEquals(len(injections), 6)
|
||||||
|
|
||||||
|
|
||||||
class SingletonTests(unittest.TestCase):
|
class SingletonTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user