mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 01:47:36 +03:00 
			
		
		
		
	Optimize provider calls
This commit is contained in:
		
							parent
							
								
									f0f5822d14
								
							
						
					
					
						commit
						0e5ec6956e
					
				| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
"""Injections module."""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import itertools
 | 
			
		||||
 | 
			
		||||
import six
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -247,8 +246,14 @@ def inject(*args, **kwargs):
 | 
			
		|||
        @six.wraps(callback)
 | 
			
		||||
        def decorated(*args, **kwargs):
 | 
			
		||||
            """Decorated with dependency injection callback."""
 | 
			
		||||
            return callback(*_get_injectable_args(args, decorated.args),
 | 
			
		||||
                            **_get_injectable_kwargs(kwargs, decorated.kwargs))
 | 
			
		||||
            if decorated.args:
 | 
			
		||||
                args = tuple(arg.value for arg in decorated.args) + args
 | 
			
		||||
 | 
			
		||||
            for kwarg in decorated.kwargs:
 | 
			
		||||
                if kwarg.name not in kwargs:
 | 
			
		||||
                    kwargs[kwarg.name] = kwarg.value
 | 
			
		||||
 | 
			
		||||
            return callback(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
        decorated.args = arg_injections
 | 
			
		||||
        decorated.kwargs = kwarg_injections
 | 
			
		||||
| 
						 | 
				
			
			@ -274,16 +279,3 @@ def _parse_kwargs_injections(args, kwargs):
 | 
			
		|||
        kwarg_injections += tuple(KwArg(name, value)
 | 
			
		||||
                                  for name, value in six.iteritems(kwargs))
 | 
			
		||||
    return kwarg_injections
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_injectable_args(context_args, arg_injections):
 | 
			
		||||
    """Return tuple of positional arguments, patched with injections."""
 | 
			
		||||
    return itertools.chain((arg.value for arg in arg_injections), context_args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_injectable_kwargs(context_kwargs, kwarg_injections):
 | 
			
		||||
    """Return dictionary of keyword arguments, patched with injections."""
 | 
			
		||||
    injectable_kwargs = dict((kwarg.name, kwarg.value)
 | 
			
		||||
                             for kwarg in kwarg_injections)
 | 
			
		||||
    injectable_kwargs.update(context_kwargs)
 | 
			
		||||
    return injectable_kwargs
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,6 @@ import six
 | 
			
		|||
 | 
			
		||||
from .injections import _parse_args_injections
 | 
			
		||||
from .injections import _parse_kwargs_injections
 | 
			
		||||
from .injections import _get_injectable_args
 | 
			
		||||
from .injections import _get_injectable_kwargs
 | 
			
		||||
 | 
			
		||||
from .utils import ensure_is_provider
 | 
			
		||||
from .utils import is_attribute_injection
 | 
			
		||||
| 
						 | 
				
			
			@ -62,18 +60,10 @@ class Provider(object):
 | 
			
		|||
        Tuple of overriding providers, if any.
 | 
			
		||||
 | 
			
		||||
        :type: tuple[:py:class:`Provider`] | None
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    __IS_PROVIDER__ = True
 | 
			
		||||
    __slots__ = ('overridden_by',)
 | 
			
		||||
    .. py:method:: __call__
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        """Initializer."""
 | 
			
		||||
        self.overridden_by = None
 | 
			
		||||
        super(Provider, self).__init__()
 | 
			
		||||
 | 
			
		||||
    def __call__(self, *args, **kwargs):
 | 
			
		||||
        """Return provided instance.
 | 
			
		||||
        Return provided instance.
 | 
			
		||||
 | 
			
		||||
        Implementation of current method adds ``callable`` functionality for
 | 
			
		||||
        providers API and it should be common for all provider's subclasses.
 | 
			
		||||
| 
						 | 
				
			
			@ -81,10 +71,22 @@ class Provider(object):
 | 
			
		|||
        common for all providers. Implementation of particular providing
 | 
			
		||||
        strategy should be done in :py:meth:`Provider._provide` of
 | 
			
		||||
        :py:class:`Provider` subclass.
 | 
			
		||||
        """
 | 
			
		||||
        if self.overridden_by:
 | 
			
		||||
            return self.last_overriding(*args, **kwargs)
 | 
			
		||||
        return self._provide(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
        :return: Provided instance
 | 
			
		||||
        :rtype: object
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    __IS_PROVIDER__ = True
 | 
			
		||||
    __OPTIMIZED_CALLS__ = True
 | 
			
		||||
    __slots__ = ('overridden_by', '__call__')
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        """Initializer."""
 | 
			
		||||
        self.overridden_by = None
 | 
			
		||||
        super(Provider, self).__init__()
 | 
			
		||||
        # Enable __call__() / _provide() optimization
 | 
			
		||||
        if self.__class__.__OPTIMIZED_CALLS__:
 | 
			
		||||
            self.__call__ = self._provide
 | 
			
		||||
 | 
			
		||||
    def _provide(self, *args, **kwargs):
 | 
			
		||||
        """Providing strategy implementation.
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +97,10 @@ class Provider(object):
 | 
			
		|||
        """
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
    def _call_last_overriding(self, *args, **kwargs):
 | 
			
		||||
        """Call last overriding provider and return result."""
 | 
			
		||||
        return self.last_overriding(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_overridden(self):
 | 
			
		||||
        """Read-only property that is set to ``True`` if provider is overridden.
 | 
			
		||||
| 
						 | 
				
			
			@ -127,6 +133,10 @@ class Provider(object):
 | 
			
		|||
        else:
 | 
			
		||||
            self.overridden_by += (ensure_is_provider(provider),)
 | 
			
		||||
 | 
			
		||||
        # Disable __call__() / _provide() optimization
 | 
			
		||||
        if self.__class__.__OPTIMIZED_CALLS__:
 | 
			
		||||
            self.__call__ = self._call_last_overriding
 | 
			
		||||
 | 
			
		||||
    def reset_last_overriding(self):
 | 
			
		||||
        """Reset last overriding provider.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -139,6 +149,11 @@ class Provider(object):
 | 
			
		|||
            raise Error('Provider {0} is not overridden'.format(str(self)))
 | 
			
		||||
        self.overridden_by = self.overridden_by[:-1]
 | 
			
		||||
 | 
			
		||||
        if not self.is_overridden:
 | 
			
		||||
            # Enable __call__() / _provide() optimization
 | 
			
		||||
            if self.__class__.__OPTIMIZED_CALLS__:
 | 
			
		||||
                self.__call__ = self._provide
 | 
			
		||||
 | 
			
		||||
    def reset_override(self):
 | 
			
		||||
        """Reset all overriding providers.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +161,10 @@ class Provider(object):
 | 
			
		|||
        """
 | 
			
		||||
        self.overridden_by = None
 | 
			
		||||
 | 
			
		||||
        # Enable __call__() / _provide() optimization
 | 
			
		||||
        if self.__class__.__OPTIMIZED_CALLS__:
 | 
			
		||||
            self.__call__ = self._provide
 | 
			
		||||
 | 
			
		||||
    def delegate(self):
 | 
			
		||||
        """Return provider's delegate.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -306,8 +325,14 @@ class Callable(Provider):
 | 
			
		|||
 | 
			
		||||
        :rtype: object
 | 
			
		||||
        """
 | 
			
		||||
        return self.provides(*_get_injectable_args(args, self.args),
 | 
			
		||||
                             **_get_injectable_kwargs(kwargs, self.kwargs))
 | 
			
		||||
        if self.args:
 | 
			
		||||
            args = tuple(arg.value for arg in self.args) + args
 | 
			
		||||
 | 
			
		||||
        for kwarg in self.kwargs:
 | 
			
		||||
            if kwarg.name not in kwargs:
 | 
			
		||||
                kwargs[kwarg.name] = kwarg.value
 | 
			
		||||
 | 
			
		||||
        return self.provides(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        """Return string representation of provider.
 | 
			
		||||
| 
						 | 
				
			
			@ -466,7 +491,14 @@ class Factory(Callable):
 | 
			
		|||
 | 
			
		||||
        :rtype: object
 | 
			
		||||
        """
 | 
			
		||||
        instance = super(Factory, self)._provide(*args, **kwargs)
 | 
			
		||||
        if self.args:
 | 
			
		||||
            args = tuple(arg.value for arg in self.args) + args
 | 
			
		||||
 | 
			
		||||
        for kwarg in self.kwargs:
 | 
			
		||||
            if kwarg.name not in kwargs:
 | 
			
		||||
                kwargs[kwarg.name] = kwarg.value
 | 
			
		||||
 | 
			
		||||
        instance = self.provides(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
        for attribute in self.attributes:
 | 
			
		||||
            setattr(instance, attribute.name, attribute.value)
 | 
			
		||||
| 
						 | 
				
			
			@ -625,10 +657,12 @@ class Singleton(Factory):
 | 
			
		|||
 | 
			
		||||
        :rtype: object
 | 
			
		||||
        """
 | 
			
		||||
        if self.instance:
 | 
			
		||||
            return self.instance
 | 
			
		||||
 | 
			
		||||
        with GLOBAL_LOCK:
 | 
			
		||||
            if not self.instance:
 | 
			
		||||
                self.instance = super(Singleton, self)._provide(*args,
 | 
			
		||||
                                                                **kwargs)
 | 
			
		||||
            self.instance = super(Singleton, self)._provide(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
        return self.instance
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -709,6 +743,7 @@ class ExternalDependency(Provider):
 | 
			
		|||
        :type: type
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    __OPTIMIZED_CALLS__ = False
 | 
			
		||||
    __slots__ = ('instance_of',)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, instance_of):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tox.ini
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -20,8 +20,8 @@ commands=
 | 
			
		|||
    coverage run --rcfile=./.coveragerc -m unittest2 discover tests []
 | 
			
		||||
    coverage html --rcfile=./.coveragerc
 | 
			
		||||
 | 
			
		||||
    flake8 --max-complexity=8 dependency_injector/
 | 
			
		||||
    flake8 --max-complexity=8 examples/
 | 
			
		||||
    flake8 --max-complexity=10 dependency_injector/
 | 
			
		||||
    flake8 --max-complexity=10 examples/
 | 
			
		||||
 | 
			
		||||
    pep257 dependency_injector/
 | 
			
		||||
    pep257 examples/
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +50,8 @@ basepython=python2.7
 | 
			
		|||
deps=
 | 
			
		||||
    flake8
 | 
			
		||||
commands=
 | 
			
		||||
    flake8 --max-complexity=8 dependency_injector/
 | 
			
		||||
    flake8 --max-complexity=8 examples/
 | 
			
		||||
    flake8 --max-complexity=10 dependency_injector/
 | 
			
		||||
    flake8 --max-complexity=10 examples/
 | 
			
		||||
 | 
			
		||||
[testenv:pep257]
 | 
			
		||||
basepython=python2.7
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user