From f2a9b35c6d0d66a01270e484b7cbdac735ab22da Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 18 May 2016 00:05:10 +0300 Subject: [PATCH 01/11] Change style and get first stable run --- dependency_injector/injections.py | 14 ++- dependency_injector/providers/callable.py | 65 +++++----- dependency_injector/providers/creational.py | 35 +++--- tests/catalogs/test_declarative.py | 3 +- tests/providers/test_callable.py | 66 +++++----- tests/providers/test_creational.py | 133 +++++++++++--------- 6 files changed, 155 insertions(+), 161 deletions(-) diff --git a/dependency_injector/injections.py b/dependency_injector/injections.py index 27f6cfc6..02b1400e 100644 --- a/dependency_injector/injections.py +++ b/dependency_injector/injections.py @@ -1,13 +1,15 @@ """Injections module.""" +import itertools + import six from dependency_injector.utils import ( is_provider, - is_delegated_provider, is_injection, is_arg_injection, is_kwarg_injection, + is_delegated_provider, fetch_cls_init, ) @@ -246,18 +248,20 @@ def inject(*args, **kwargs): def _parse_args_injections(args): - """Parse positional argument injections according to current syntax.""" return tuple(Arg(arg) if not is_injection(arg) else arg for arg in args if not is_injection(arg) or is_arg_injection(arg)) def _parse_kwargs_injections(args, kwargs): - """Parse keyword argument injections according to current syntax.""" kwarg_injections = tuple(injection for injection in args if is_kwarg_injection(injection)) if kwargs: - kwarg_injections += tuple(KwArg(name, value) - for name, value in six.iteritems(kwargs)) + kwarg_injections += tuple(itertools.starmap(KwArg, + six.iteritems(kwargs))) return kwarg_injections + + +def _parse_attribute_injections(attributes): + return tuple(itertools.starmap(Attribute, six.iteritems(attributes))) diff --git a/dependency_injector/providers/callable.py b/dependency_injector/providers/callable.py index a69f70eb..3093927b 100644 --- a/dependency_injector/providers/callable.py +++ b/dependency_injector/providers/callable.py @@ -13,27 +13,18 @@ from dependency_injector.errors import Error @six.python_2_unicode_compatible 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 provider call with some predefined dependency injections. - :py:class:`Callable` syntax of passing injections is the same like - :py:class:`Factory` one: + :py:class:`Callable` supports positional and keyword argument injections: .. 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, - injections.Arg(1), - injections.Arg(2), - injections.KwArg('some_arg', 3), - injections.KwArg('other_arg', 4)) + some_function = Callable(some_function) \ + .args('arg1', 'arg2') \ + .kwargs(arg3=3, arg4=4) .. py:attribute:: provides @@ -41,32 +32,26 @@ class Callable(Provider): :type: callable - .. py:attribute:: args + .. py:attribute:: _args Tuple of positional argument injections. :type: tuple[:py:class:`dependency_injector.injections.Arg`] - .. py:attribute:: kwargs + .. 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): """Initializer. :param provides: Wrapped callable. :type provides: callable - - :param args: Tuple of injections. - :type args: tuple - - :param kwargs: Dictionary of injections. - :type kwargs: dict """ if not callable(provides): raise Error('Provider {0} expected to get callable, ' @@ -76,10 +61,8 @@ class Callable(Provider): self.provides = provides - self.args = tuple() - self.kwargs = tuple() - - self.add_injections(*args, **kwargs) + self._args = tuple() + self._kwargs = tuple() super(Callable, self).__init__() @@ -89,19 +72,29 @@ class Callable(Provider): :rtype: tuple[:py:class:`dependency_injector.injections.Injection`] """ - return self.args + self.kwargs + return self._args + self._kwargs - def add_injections(self, *args, **kwargs): - """Add provider injections. + def args(self, *args): + """Add postional argument injections. :param args: Tuple of injections. :type args: tuple + :return: Reference ``self`` + """ + self._args += _parse_args_injections(args) + return self + + def kwargs(self, **kwargs): + """Add keyword argument injections. + :param kwargs: Dictionary of injections. :type kwargs: dict + + :return: Reference ``self`` """ - self.args += _parse_args_injections(args) - self.kwargs += _parse_kwargs_injections(args, kwargs) + self._kwargs += _parse_kwargs_injections(tuple(), kwargs) + return self def _provide(self, *args, **kwargs): """Return provided instance. @@ -114,10 +107,10 @@ class Callable(Provider): :rtype: object """ - if self.args: - args = tuple(arg.value for arg in self.args) + args + if self._args: + args = tuple(arg.value for arg in self._args) + args - for kwarg in self.kwargs: + for kwarg in self._kwargs: if kwarg.name not in kwargs: kwargs[kwarg.name] = kwarg.value diff --git a/dependency_injector/providers/creational.py b/dependency_injector/providers/creational.py index cfd2dea3..3069a872 100644 --- a/dependency_injector/providers/creational.py +++ b/dependency_injector/providers/creational.py @@ -1,10 +1,8 @@ """Dependency injector creational providers.""" from dependency_injector.providers.callable import Callable -from dependency_injector.utils import ( - is_attribute_injection, - GLOBAL_LOCK, -) +from dependency_injector.injections import _parse_attribute_injections +from dependency_injector.utils import GLOBAL_LOCK from dependency_injector.errors import Error @@ -79,7 +77,7 @@ class Factory(Callable): provided_type = None - __slots__ = ('cls', 'attributes') + __slots__ = ('cls', '_attributes') def __init__(self, provides, *args, **kwargs): """Initializer. @@ -99,7 +97,7 @@ class Factory(Callable): raise Error('{0} can provide only {1} instances'.format( self.__class__, self.__class__.provided_type)) - self.attributes = tuple() + self._attributes = tuple() super(Factory, self).__init__(provides, *args, **kwargs) @@ -111,22 +109,17 @@ class Factory(Callable): :rtype: tuple[:py:class:`dependency_injector.injections.Injection`] """ - return self.args + self.kwargs + self.attributes + return self._args + self._kwargs + self._attributes - def add_injections(self, *args, **kwargs): - """Add provider injections. - - :param args: Tuple of injections. - :type args: tuple + def attributes(self, **kwargs): + """Add attribute injections. :param kwargs: Dictionary of injections. :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 += _parse_attribute_injections(kwargs) return self def _provide(self, *args, **kwargs): @@ -140,16 +133,16 @@ class Factory(Callable): :rtype: object """ - if self.args: - args = tuple(arg.value for arg in self.args) + args + if self._args: + args = tuple(arg.value for arg in self._args) + args - for kwarg in self.kwargs: + 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: + for attribute in self._attributes: setattr(instance, attribute.name, attribute.value) return instance diff --git a/tests/catalogs/test_declarative.py b/tests/catalogs/test_declarative.py index e3279c2c..0bf2a86d 100644 --- a/tests/catalogs/test_declarative.py +++ b/tests/catalogs/test_declarative.py @@ -382,7 +382,8 @@ class CopyingTests(unittest.TestCase): """Test catalog providers copying.""" class CatalogA(catalogs.DeclarativeCatalog): p11 = providers.Object(0) - p12 = providers.Factory(dict, p11=p11) + p12 = providers.Factory(dict) \ + .kwargs(p11=p11) @catalogs.copy(CatalogA) class CatalogA1(CatalogA): diff --git a/tests/providers/test_callable.py b/tests/providers/test_callable.py index cfaf83df..681599fd 100644 --- a/tests/providers/test_callable.py +++ b/tests/providers/test_callable.py @@ -4,7 +4,6 @@ import unittest2 as unittest from dependency_injector import ( providers, - injections, utils, errors, ) @@ -35,7 +34,9 @@ class CallableTests(unittest.TestCase): 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)) def test_call_with_keyword_args(self): @@ -43,11 +44,9 @@ class CallableTests(unittest.TestCase): New simplified syntax. """ - provider = providers.Callable(self.example, - arg1=1, - arg2=2, - arg3=3, - arg4=4) + provider = providers.Callable(self.example) \ + .kwargs(arg1=1, arg2=2, arg3=3, arg4=4) + self.assertTupleEqual(provider(), (1, 2, 3, 4)) def test_call_with_positional_and_keyword_args(self): @@ -55,40 +54,37 @@ class CallableTests(unittest.TestCase): 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)) + provider = providers.Callable(self.example) \ + .args(1, 2) \ + .kwargs(arg3=3, arg4=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)) def test_call_with_context_args(self): """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)) def test_call_with_context_kwargs(self): """Test call with context kwargs.""" - provider = providers.Callable(self.example, - injections.KwArg('arg1', 1)) + provider = providers.Callable(self.example) \ + .kwargs(arg1=1) + self.assertTupleEqual(provider(arg2=2, arg3=3, arg4=4), (1, 2, 3, 4)) def test_call_with_context_args_and_kwargs(self): """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)) def test_call_overridden(self): """Test creation of new instances on overridden provider.""" provider = providers.Callable(self.example) + provider.override(providers.Object((4, 3, 2, 1))) provider.override(providers.Object((1, 2, 3, 4))) @@ -96,24 +92,20 @@ class CallableTests(unittest.TestCase): def test_injections(self): """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) def test_repr(self): """Test representation of provider.""" - provider = providers.Callable(self.example, - injections.KwArg( - 'arg1', - providers.Factory(dict)), - injections.KwArg( - 'arg2', - providers.Factory(list)), - injections.KwArg( - 'arg3', - providers.Factory(set)), - injections.KwArg( - 'arg4', - providers.Factory(tuple))) + provider = providers.Callable(self.example) \ + .kwargs(arg1=providers.Factory(dict), + arg2=providers.Factory(list), + arg3=providers.Factory(set), + arg4=providers.Factory(tuple)) + self.assertEqual(repr(provider), ''.format( diff --git a/tests/providers/test_creational.py b/tests/providers/test_creational.py index 5c5f9b19..e29f13be 100644 --- a/tests/providers/test_creational.py +++ b/tests/providers/test_creational.py @@ -47,7 +47,8 @@ class FactoryTests(unittest.TestCase): provided_type = Example - example_provider = ExampleProvider(Example, 1, 2) + example_provider = ExampleProvider(Example) \ + .args(1, 2) self.assertIsInstance(example_provider(), Example) @@ -61,7 +62,8 @@ class FactoryTests(unittest.TestCase): class NewExampe(Example): """Example class subclass.""" - example_provider = ExampleProvider(NewExampe, 1, 2) + example_provider = ExampleProvider(NewExampe) \ + .args(1, 2) self.assertIsInstance(example_provider(), NewExampe) @@ -90,7 +92,8 @@ class FactoryTests(unittest.TestCase): New simplified syntax. """ - provider = providers.Factory(Example, 'i1', 'i2') + provider = providers.Factory(Example) \ + .args('i1', 'i2') instance1 = provider() instance2 = provider() @@ -110,7 +113,8 @@ class FactoryTests(unittest.TestCase): New simplified syntax. """ - provider = providers.Factory(Example, init_arg1='i1', init_arg2='i2') + provider = providers.Factory(Example) \ + .kwargs(init_arg1='i1', init_arg2='i2') instance1 = provider() instance2 = provider() @@ -130,7 +134,9 @@ class FactoryTests(unittest.TestCase): Simplified syntax of positional and keyword arg injections. """ - provider = providers.Factory(Example, 'i1', init_arg2='i2') + provider = providers.Factory(Example) \ + .args('i1') \ + .kwargs(init_arg2='i2') instance1 = provider() instance2 = provider() @@ -150,9 +156,9 @@ class FactoryTests(unittest.TestCase): Extended syntax of positional and keyword arg injections. """ - provider = providers.Factory(Example, - injections.Arg('i1'), - injections.KwArg('init_arg2', 'i2')) + provider = providers.Factory(Example) \ + .args('i1') \ + .kwargs(init_arg2='i2') instance1 = provider() instance2 = provider() @@ -169,9 +175,8 @@ class FactoryTests(unittest.TestCase): def test_call_with_attributes(self): """Test creation of new instances with attribute injections.""" - provider = providers.Factory(Example, - injections.Attribute('attribute1', 'a1'), - injections.Attribute('attribute2', 'a2')) + provider = providers.Factory(Example) \ + .attributes(attribute1='a1', attribute2='a2') instance1 = provider() instance2 = provider() @@ -188,7 +193,8 @@ class FactoryTests(unittest.TestCase): def test_call_with_context_args(self): """Test creation of new instances with context args.""" - provider = providers.Factory(Example, 11, 22) + provider = providers.Factory(Example) \ + .args(11, 22) instance = provider(33, 44) self.assertEqual(instance.init_arg1, 11) @@ -198,8 +204,8 @@ class FactoryTests(unittest.TestCase): def test_call_with_context_kwargs(self): """Test creation of new instances with context kwargs.""" - provider = providers.Factory(Example, - injections.KwArg('init_arg1', 1)) + provider = providers.Factory(Example) \ + .kwargs(init_arg1=1) instance1 = provider(init_arg2=22) self.assertEqual(instance1.init_arg1, 1) @@ -211,7 +217,8 @@ class FactoryTests(unittest.TestCase): def test_call_with_context_args_and_kwargs(self): """Test creation of new instances 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) self.assertEqual(instance.init_arg1, 11) @@ -237,20 +244,19 @@ class FactoryTests(unittest.TestCase): def test_injections(self): """Test getting a full list of injections using injections property.""" - provider = providers.Factory(Example, - injections.Arg(1), - injections.KwArg('init_arg2', 2), - injections.Attribute('attribute1', 3), - injections.Attribute('attribute2', 4)) + provider = providers.Factory(Example) \ + .args(1) \ + .kwargs(init_arg2=2) \ + .attributes(attribute1=3, attribute2=4) + self.assertEquals(len(provider.injections), 4) def test_repr(self): """Test representation of provider.""" - provider = providers.Factory(Example, - injections.KwArg('init_arg1', - providers.Factory(dict)), - injections.KwArg('init_arg2', - providers.Factory(list))) + provider = providers.Factory(Example) \ + .kwargs(init_arg1=providers.Factory(dict), + init_arg2=providers.Factory(list)) + self.assertEqual(repr(provider), ''.format( @@ -300,7 +306,8 @@ class SingletonTests(unittest.TestCase): provided_type = Example - example_provider = ExampleProvider(Example, 1, 2) + example_provider = ExampleProvider(Example) \ + .args(1, 2) self.assertIsInstance(example_provider(), Example) @@ -314,7 +321,8 @@ class SingletonTests(unittest.TestCase): class NewExampe(Example): """Example class subclass.""" - example_provider = ExampleProvider(NewExampe, 1, 2) + example_provider = ExampleProvider(NewExampe) \ + .args(1, 2) self.assertIsInstance(example_provider(), NewExampe) @@ -343,7 +351,8 @@ class SingletonTests(unittest.TestCase): New simplified syntax. """ - provider = providers.Singleton(Example, 'i1', 'i2') + provider = providers.Singleton(Example) \ + .args('i1', 'i2') instance1 = provider() instance2 = provider() @@ -363,7 +372,8 @@ class SingletonTests(unittest.TestCase): New simplified syntax. """ - provider = providers.Singleton(Example, init_arg1='i1', init_arg2='i2') + provider = providers.Singleton(Example) \ + .kwargs(init_arg1='i1', init_arg2='i2') instance1 = provider() instance2 = provider() @@ -383,7 +393,9 @@ class SingletonTests(unittest.TestCase): Simplified syntax of positional and keyword arg injections. """ - provider = providers.Singleton(Example, 'i1', init_arg2='i2') + provider = providers.Singleton(Example) \ + .args('i1') \ + .kwargs(init_arg2='i2') instance1 = provider() instance2 = provider() @@ -403,9 +415,9 @@ class SingletonTests(unittest.TestCase): Extended syntax of positional and keyword arg injections. """ - provider = providers.Singleton(Example, - injections.Arg('i1'), - injections.KwArg('init_arg2', 'i2')) + provider = providers.Singleton(Example) \ + .args('i1') \ + .kwargs(init_arg2='i2') instance1 = provider() instance2 = provider() @@ -422,11 +434,8 @@ class SingletonTests(unittest.TestCase): def test_call_with_attributes(self): """Test getting of instances with attribute injections.""" - provider = providers.Singleton(Example, - injections.Attribute('attribute1', - 'a1'), - injections.Attribute('attribute2', - 'a2')) + provider = providers.Singleton(Example) \ + .attributes(attribute1='a1', attribute2='a2') instance1 = provider() instance2 = provider() @@ -451,8 +460,8 @@ class SingletonTests(unittest.TestCase): def test_call_with_context_kwargs(self): """Test getting of instances with context kwargs.""" - provider = providers.Singleton(Example, - injections.KwArg('init_arg1', 1)) + provider = providers.Singleton(Example) \ + .kwargs(init_arg1=1) instance1 = provider(init_arg2=22) self.assertEqual(instance1.init_arg1, 1) @@ -465,7 +474,8 @@ class SingletonTests(unittest.TestCase): def test_call_with_context_args_and_kwargs(self): """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) self.assertEqual(instance.init_arg1, 11) @@ -496,28 +506,32 @@ class SingletonTests(unittest.TestCase): def test_args_attr(self): """Test args attribute.""" - provider = providers.Singleton(Example, 1, 2) - self.assertEquals(len(provider.args), 2) + provider = providers.Singleton(Example) \ + .args(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) + provider = providers.Singleton(Example) \ + .kwargs(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) + provider = providers.Singleton(Example) \ + .attributes(attribute1=1, attribute2=2) + + self.assertEquals(len(provider._attributes), 2) def test_injections(self): """Test getting a full list of injections using injections property.""" - provider = providers.Singleton(Example, - injections.Arg(1), - injections.KwArg('init_arg2', 2), - injections.Attribute('attribute1', 3), - injections.Attribute('attribute2', 4)) + provider = providers.Singleton(Example) \ + .args(1) \ + .kwargs(init_arg2=2) \ + .attributes(attribute1=3, attribute2=4) + self.assertEquals(len(provider.injections), 4) def test_reset(self): @@ -536,13 +550,10 @@ class SingletonTests(unittest.TestCase): def test_repr(self): """Test representation of provider.""" - provider = providers.Singleton(Example, - injections.KwArg( - 'init_arg1', - providers.Factory(dict)), - injections.KwArg( - 'init_arg2', - providers.Factory(list))) + provider = providers.Singleton(Example) \ + .kwargs(init_arg1=providers.Factory(dict), + init_arg2=providers.Factory(list)) + self.assertEqual(repr(provider), ''.format( From 65512366d28f28bce4998975e94825a92e1d19ca Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 18 May 2016 01:17:15 +0300 Subject: [PATCH 02/11] Refactor callable and creational providers --- dependency_injector/injections.py | 4 - dependency_injector/providers/callable.py | 55 +----- dependency_injector/providers/creational.py | 183 +++----------------- 3 files changed, 36 insertions(+), 206 deletions(-) diff --git a/dependency_injector/injections.py b/dependency_injector/injections.py index 02b1400e..fe526715 100644 --- a/dependency_injector/injections.py +++ b/dependency_injector/injections.py @@ -261,7 +261,3 @@ def _parse_kwargs_injections(args, kwargs): kwarg_injections += tuple(itertools.starmap(KwArg, six.iteritems(kwargs))) return kwarg_injections - - -def _parse_attribute_injections(attributes): - return tuple(itertools.starmap(Attribute, six.iteritems(attributes))) diff --git a/dependency_injector/providers/callable.py b/dependency_injector/providers/callable.py index 3093927b..afc29964 100644 --- a/dependency_injector/providers/callable.py +++ b/dependency_injector/providers/callable.py @@ -3,10 +3,7 @@ import six from dependency_injector.providers.base import Provider -from dependency_injector.injections import ( - _parse_args_injections, - _parse_kwargs_injections, -) +from dependency_injector.injections import Arg, KwArg from dependency_injector.utils import represent_provider from dependency_injector.errors import Error @@ -25,27 +22,9 @@ class Callable(Provider): some_function = Callable(some_function) \ .args('arg1', 'arg2') \ .kwargs(arg3=3, arg4=4) - - .. 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`] """ - __slots__ = ('provides', '_args', '_kwargs') + __slots__ = ('_provides', '_args', '_kwargs') def __init__(self, provides): """Initializer. @@ -59,8 +38,7 @@ class Callable(Provider): self.__class__.__name__)), provides)) - self.provides = provides - + self._provides = provides self._args = tuple() self._kwargs = tuple() @@ -82,7 +60,7 @@ class Callable(Provider): :return: Reference ``self`` """ - self._args += _parse_args_injections(args) + self._args += tuple(Arg(value) for value in args) return self def kwargs(self, **kwargs): @@ -93,7 +71,8 @@ class Callable(Provider): :return: Reference ``self`` """ - self._kwargs += _parse_kwargs_injections(tuple(), kwargs) + self._kwargs += tuple(KwArg(name, value) + for name, value in six.iteritems(kwargs)) return self def _provide(self, *args, **kwargs): @@ -114,14 +93,14 @@ class Callable(Provider): if kwarg.name not in kwargs: kwargs[kwarg.name] = kwarg.value - return self.provides(*args, **kwargs) + return self._provides(*args, **kwargs) def __str__(self): """Return string representation of provider. :rtype: str """ - return represent_provider(provider=self, provides=self.provides) + return represent_provider(provider=self, provides=self._provides) __repr__ = __str__ @@ -131,24 +110,6 @@ class DelegatedCallable(Callable): :py:class:`DelegatedCallable` is a :py:class:`Callable`, that is injected "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 diff --git a/dependency_injector/providers/creational.py b/dependency_injector/providers/creational.py index 3069a872..d554361f 100644 --- a/dependency_injector/providers/creational.py +++ b/dependency_injector/providers/creational.py @@ -1,38 +1,32 @@ """Dependency injector creational providers.""" +import six + from dependency_injector.providers.callable import Callable -from dependency_injector.injections import _parse_attribute_injections +from dependency_injector.injections import Attribute from dependency_injector.utils import GLOBAL_LOCK from dependency_injector.errors import Error 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: .. 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, - injections.Arg(1), - injections.Arg(2), - injections.KwArg('some_arg', 3), - injections.KwArg('other_arg', 4), - injections.Attribute('some_attribute', 5)) + factory = Factory(SomeClass) \ + .args('arg1', 'arg2') \ + .kwargs(arg3=3, arg4=4) \ + .attributes(attribute1=5, attribute2=6) Retrieving of provided instance can be performed via calling :py:class:`Factory` object: .. code-block:: python - factory = Factory(SomeClass, - some_arg1=1, - some_arg2=2) + factory = Factory(SomeClass) some_object = factory() .. py:attribute:: provided_type @@ -43,54 +37,24 @@ class Factory(Callable): :type: type | None - .. py:attribute:: provides - - Class or other callable that provides object. - - :type: type | callable - .. py:attribute:: cls Class that provides object. Alias for :py:attr:`provides`. :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 __slots__ = ('cls', '_attributes') - def __init__(self, provides, *args, **kwargs): + def __init__(self, provides): """Initializer. :param provides: Class or other callable that provides object for creation. :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 not issubclass(provides, self.__class__.provided_type)): @@ -99,9 +63,9 @@ class Factory(Callable): self._attributes = tuple() - super(Factory, self).__init__(provides, *args, **kwargs) + super(Factory, self).__init__(provides) - self.cls = self.provides + self.cls = self._provides @property def injections(self): @@ -109,7 +73,7 @@ class Factory(Callable): :rtype: tuple[:py:class:`dependency_injector.injections.Injection`] """ - return self._args + self._kwargs + self._attributes + return super(Factory, self).injections + self._attributes def attributes(self, **kwargs): """Add attribute injections. @@ -119,7 +83,8 @@ class Factory(Callable): :return: Reference ``self`` """ - self._attributes += _parse_attribute_injections(kwargs) + self._attributes += tuple(Attribute(name, value) + for name, value in six.iteritems(kwargs)) return self def _provide(self, *args, **kwargs): @@ -140,7 +105,7 @@ class Factory(Callable): if kwarg.name not in kwargs: kwargs[kwarg.name] = kwarg.value - instance = self.provides(*args, **kwargs) + instance = self._provides(*args, **kwargs) for attribute in self._attributes: setattr(instance, attribute.name, attribute.value) @@ -162,36 +127,12 @@ class DelegatedFactory(Factory): :type: type | None - .. py:attribute:: provides - - Class or other callable that provides object. - - :type: type | callable - .. py:attribute:: cls Class that provides object. Alias for :py:attr:`provides`. :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 @@ -212,9 +153,7 @@ class Singleton(Factory): .. code-block:: python - singleton = Singleton(SomeClass, - some_arg1=1, - some_arg2=2) + singleton = Singleton(SomeClass) some_object = singleton() .. py:attribute:: provided_type @@ -225,68 +164,32 @@ class Singleton(Factory): :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 Class that provides object. Alias for :py:attr:`provides`. :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): """Initializer. :param provides: Class or other callable that provides object for creation. :type provides: type | callable - - :param args: Tuple of injections. - :type args: tuple - - :param kwargs: Dictionary of injections. - :type kwargs: dict """ - self.instance = None - super(Singleton, self).__init__(provides, *args, **kwargs) + self._instance = None + super(Singleton, self).__init__(provides) def reset(self): """Reset cached instance, if any. :rtype: None """ - self.instance = None + self._instance = None def _provide(self, *args, **kwargs): """Return provided instance. @@ -299,13 +202,13 @@ class Singleton(Factory): :rtype: object """ - if self.instance: - return self.instance + if self._instance: + return self._instance 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): @@ -322,42 +225,12 @@ class DelegatedSingleton(Singleton): :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 Class that provides object. Alias for :py:attr:`provides`. :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 From a0b8b11a91ccb8f20c9c3a7a49cd5676d1536976 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 18 May 2016 01:17:39 +0300 Subject: [PATCH 03/11] Sanitize callable and creational provider tests --- tests/providers/test_callable.py | 16 +--- tests/providers/test_creational.py | 124 +++++------------------------ tests/providers/test_static.py | 2 + 3 files changed, 23 insertions(+), 119 deletions(-) diff --git a/tests/providers/test_callable.py b/tests/providers/test_callable.py index 681599fd..2f526470 100644 --- a/tests/providers/test_callable.py +++ b/tests/providers/test_callable.py @@ -2,11 +2,7 @@ import unittest2 as unittest -from dependency_injector import ( - providers, - utils, - errors, -) +from dependency_injector import providers, utils, errors class CallableTests(unittest.TestCase): @@ -40,20 +36,14 @@ class CallableTests(unittest.TestCase): self.assertTupleEqual(provider(), (1, 2, 3, 4)) def test_call_with_keyword_args(self): - """Test call with keyword args. - - New simplified syntax. - """ + """Test call with keyword args.""" provider = providers.Callable(self.example) \ .kwargs(arg1=1, arg2=2, arg3=3, arg4=4) self.assertTupleEqual(provider(), (1, 2, 3, 4)) def test_call_with_positional_and_keyword_args(self): - """Test call with positional and keyword args. - - Simplified syntax of positional and keyword arg injections. - """ + """Test call with positional and keyword args.""" provider = providers.Callable(self.example) \ .args(1, 2) \ .kwargs(arg3=3, arg4=4) diff --git a/tests/providers/test_creational.py b/tests/providers/test_creational.py index e29f13be..215f557d 100644 --- a/tests/providers/test_creational.py +++ b/tests/providers/test_creational.py @@ -2,12 +2,7 @@ import unittest2 as unittest -from dependency_injector import ( - providers, - injections, - utils, - errors, -) +from dependency_injector import providers, injections, utils, errors class Example(object): @@ -78,8 +73,9 @@ class FactoryTests(unittest.TestCase): ExampleProvider(list) def test_call(self): - """Test creation of new instances.""" + """Test call.""" provider = providers.Factory(Example) + instance1 = provider() instance2 = provider() @@ -88,10 +84,7 @@ class FactoryTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_init_positional_args(self): - """Test creation of new instances with init positional args. - - New simplified syntax. - """ + """Test call with init positional args.""" provider = providers.Factory(Example) \ .args('i1', 'i2') @@ -109,10 +102,7 @@ class FactoryTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_init_keyword_args(self): - """Test creation of new instances with init keyword args. - - New simplified syntax. - """ + """Test call with init keyword args.""" provider = providers.Factory(Example) \ .kwargs(init_arg1='i1', init_arg2='i2') @@ -130,32 +120,7 @@ class FactoryTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_init_positional_and_keyword_args(self): - """Test creation of new instances with init positional and keyword args. - - Simplified syntax of positional and keyword arg injections. - """ - provider = providers.Factory(Example) \ - .args('i1') \ - .kwargs(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. - """ + """Test call with init positional and keyword args.""" provider = providers.Factory(Example) \ .args('i1') \ .kwargs(init_arg2='i2') @@ -174,7 +139,7 @@ class FactoryTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_attributes(self): - """Test creation of new instances with attribute injections.""" + """Test call with attribute injections.""" provider = providers.Factory(Example) \ .attributes(attribute1='a1', attribute2='a2') @@ -192,9 +157,10 @@ class FactoryTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_context_args(self): - """Test creation of new instances with context args.""" + """Test call with context args.""" provider = providers.Factory(Example) \ .args(11, 22) + instance = provider(33, 44) self.assertEqual(instance.init_arg1, 11) @@ -203,7 +169,7 @@ class FactoryTests(unittest.TestCase): self.assertEqual(instance.init_arg4, 44) def test_call_with_context_kwargs(self): - """Test creation of new instances with context kwargs.""" + """Test call with context kwargs.""" provider = providers.Factory(Example) \ .kwargs(init_arg1=1) @@ -216,9 +182,10 @@ class FactoryTests(unittest.TestCase): self.assertEqual(instance2.init_arg2, 22) 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) \ .args(11) + instance = provider(22, init_arg3=33, init_arg4=44) self.assertEqual(instance.init_arg1, 11) @@ -227,7 +194,7 @@ class FactoryTests(unittest.TestCase): self.assertEqual(instance.init_arg4, 44) def test_call_overridden(self): - """Test creation of new instances on overridden provider.""" + """Test call on overridden provider.""" provider = providers.Factory(Example) overriding_provider1 = providers.Factory(dict) overriding_provider2 = providers.Factory(list) @@ -339,6 +306,7 @@ class SingletonTests(unittest.TestCase): def test_call(self): """Test getting of instances.""" provider = providers.Singleton(Example) + instance1 = provider() instance2 = provider() @@ -347,10 +315,7 @@ class SingletonTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_init_positional_args(self): - """Test getting of instances with init positional args. - - New simplified syntax. - """ + """Test getting of instances with init positional args.""" provider = providers.Singleton(Example) \ .args('i1', 'i2') @@ -368,10 +333,7 @@ class SingletonTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_init_keyword_args(self): - """Test getting of instances with init keyword args. - - New simplified syntax. - """ + """Test getting of instances with init keyword args.""" provider = providers.Singleton(Example) \ .kwargs(init_arg1='i1', init_arg2='i2') @@ -389,32 +351,7 @@ class SingletonTests(unittest.TestCase): self.assertIsInstance(instance2, Example) def test_call_with_init_positional_and_keyword_args(self): - """Test getting of instances with init positional and keyword args. - - Simplified syntax of positional and keyword arg injections. - """ - provider = providers.Singleton(Example) \ - .args('i1') \ - .kwargs(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. - """ + """Test getting of instances with init positional and keyword args.""" provider = providers.Singleton(Example) \ .args('i1') \ .kwargs(init_arg2='i2') @@ -453,6 +390,7 @@ class SingletonTests(unittest.TestCase): def test_call_with_context_args(self): """Test getting of instances with context args.""" provider = providers.Singleton(Example) + instance = provider(11, 22) self.assertEqual(instance.init_arg1, 11) @@ -499,32 +437,6 @@ class SingletonTests(unittest.TestCase): self.assertIsInstance(instance1, 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) \ - .args(1, 2) - - self.assertEquals(len(provider._args), 2) - - def test_kwargs_attr(self): - """Test kwargs attribute.""" - provider = providers.Singleton(Example) \ - .kwargs(init_arg1=1, init_arg2=2) - - self.assertEquals(len(provider._kwargs), 2) - - def test_attributes_attr(self): - """Test attributes attribute.""" - provider = providers.Singleton(Example) \ - .attributes(attribute1=1, attribute2=2) - - self.assertEquals(len(provider._attributes), 2) - def test_injections(self): """Test getting a full list of injections using injections property.""" provider = providers.Singleton(Example) \ diff --git a/tests/providers/test_static.py b/tests/providers/test_static.py index 02bc72ec..0c1ed66e 100644 --- a/tests/providers/test_static.py +++ b/tests/providers/test_static.py @@ -7,6 +7,8 @@ from dependency_injector import ( utils, ) +# TODO: move to test_base + class ObjectProviderTests(unittest.TestCase): """Object provider tests.""" From 44d0555778ed1d417604ccdb2a7fc98f82b4fdb5 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 18 May 2016 15:07:48 +0300 Subject: [PATCH 04/11] Restore Callable positional & keyword argument injections via __init__(*args, **kwargs) --- dependency_injector/providers/callable.py | 5 ++++- dependency_injector/providers/creational.py | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dependency_injector/providers/callable.py b/dependency_injector/providers/callable.py index afc29964..a26f10c6 100644 --- a/dependency_injector/providers/callable.py +++ b/dependency_injector/providers/callable.py @@ -26,7 +26,7 @@ class Callable(Provider): __slots__ = ('_provides', '_args', '_kwargs') - def __init__(self, provides): + def __init__(self, provides, *args, **kwargs): """Initializer. :param provides: Wrapped callable. @@ -42,6 +42,9 @@ class Callable(Provider): self._args = tuple() self._kwargs = tuple() + self.args(*args) + self.kwargs(**kwargs) + super(Callable, self).__init__() @property diff --git a/dependency_injector/providers/creational.py b/dependency_injector/providers/creational.py index d554361f..b5ba7c76 100644 --- a/dependency_injector/providers/creational.py +++ b/dependency_injector/providers/creational.py @@ -49,7 +49,7 @@ class Factory(Callable): __slots__ = ('cls', '_attributes') - def __init__(self, provides): + def __init__(self, provides, *args, **kwargs): """Initializer. :param provides: Class or other callable that provides object @@ -63,7 +63,7 @@ class Factory(Callable): self._attributes = tuple() - super(Factory, self).__init__(provides) + super(Factory, self).__init__(provides, *args, **kwargs) self.cls = self._provides @@ -174,7 +174,7 @@ class Singleton(Factory): __slots__ = ('_instance',) - def __init__(self, provides): + def __init__(self, provides, *args, **kwargs): """Initializer. :param provides: Class or other callable that provides object @@ -182,7 +182,7 @@ class Singleton(Factory): :type provides: type | callable """ self._instance = None - super(Singleton, self).__init__(provides) + super(Singleton, self).__init__(provides, *args, **kwargs) def reset(self): """Reset cached instance, if any. From 3247e79af4340aebad9b6a86913e8516b5ce0354 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 18 May 2016 15:08:26 +0300 Subject: [PATCH 05/11] Add 2 examples of services miniapp catalog styles --- examples/miniapps/services/main2.py | 54 +++++++++++++++++++++++++++++ examples/miniapps/services/main3.py | 54 +++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 examples/miniapps/services/main2.py create mode 100644 examples/miniapps/services/main3.py diff --git a/examples/miniapps/services/main2.py b/examples/miniapps/services/main2.py new file mode 100644 index 00000000..517f5d38 --- /dev/null +++ b/examples/miniapps/services/main2.py @@ -0,0 +1,54 @@ +"""Dependency Injector example.""" + +import sys +import sqlite3 + +from boto.s3.connection import S3Connection + +from dependency_injector import catalogs +from dependency_injector import providers +from dependency_injector import injections + +from example import services + + +class Platform(catalogs.DeclarativeCatalog): + """Catalog of platform service providers.""" + + database = providers.Singleton(sqlite3.connect) + database.args(':memory:') + + s3 = providers.Singleton(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(services.Users) + users.kwargs(db=Platform.database) + + photos = providers.Factory(services.Photos) + photos.kwargs(db=Platform.database, + s3=Platform.s3) + + auth = providers.Factory(services.Auth) + auth.kwargs(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.""" + login, password, photo_path = argv[1:] + + user = users_service.get_user(login) + auth_service.authenticate(user, password) + photos_service.upload_photo(user['id'], photo_path) + + +if __name__ == '__main__': + main(sys.argv) diff --git a/examples/miniapps/services/main3.py b/examples/miniapps/services/main3.py new file mode 100644 index 00000000..54fea3d3 --- /dev/null +++ b/examples/miniapps/services/main3.py @@ -0,0 +1,54 @@ +"""Dependency Injector example.""" + +import sys +import sqlite3 + +from boto.s3.connection import S3Connection + +from dependency_injector import catalogs +from dependency_injector import providers +from dependency_injector import injections + +from example import services + + +class Platform(catalogs.DeclarativeCatalog): + """Catalog of platform service providers.""" + + database = providers.Singleton(sqlite3.connect) \ + .args(':memory:') + + s3 = providers.Singleton(S3Connection) \ + .kwargs(aws_access_key_id='KEY', + aws_secret_access_key='SECRET') + + +class Services(catalogs.DeclarativeCatalog): + """Catalog of business service providers.""" + + users = providers.Factory(services.Users) \ + .kwargs(db=Platform.database) + + photos = providers.Factory(services.Photos) \ + .kwargs(db=Platform.database, + s3=Platform.s3) + + auth = providers.Factory(services.Auth) \ + .kwargs(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.""" + login, password, photo_path = argv[1:] + + user = users_service.get_user(login) + auth_service.authenticate(user, password) + photos_service.upload_photo(user['id'], photo_path) + + +if __name__ == '__main__': + main(sys.argv) From 075e1bcf4fa090f203cc71b619812e578e68f659 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 18 May 2016 23:18:29 +0300 Subject: [PATCH 06/11] Update services miniapp --- README.rst | 75 ++++++++++++++----- examples/miniapps/services/README.rst | 8 +- examples/miniapps/services/catalogs.py | 33 ++++++++ .../services/catalogs_alt_syntax_1.py | 37 +++++++++ .../services/catalogs_alt_syntax_2.py | 37 +++++++++ examples/miniapps/services/main.py | 50 ++----------- examples/miniapps/services/main2.py | 54 ------------- examples/miniapps/services/main3.py | 54 ------------- 8 files changed, 178 insertions(+), 170 deletions(-) create mode 100644 examples/miniapps/services/catalogs.py create mode 100644 examples/miniapps/services/catalogs_alt_syntax_1.py create mode 100644 examples/miniapps/services/catalogs_alt_syntax_2.py delete mode 100644 examples/miniapps/services/main2.py delete mode 100644 examples/miniapps/services/main3.py diff --git a/README.rst b/README.rst index 05fe1412..b1770d23 100644 --- a/README.rst +++ b/README.rst @@ -55,20 +55,20 @@ Installation 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 - """Dependency Injector example.""" + """Example of several Dependency Injector catalogs.""" - import sys import sqlite3 - - from boto.s3.connection import S3Connection + import boto.s3.connection + import example.services from dependency_injector import catalogs from dependency_injector import providers - from dependency_injector import injections - - from example import services class Platform(catalogs.DeclarativeCatalog): @@ -76,7 +76,7 @@ Example database = providers.Singleton(sqlite3.connect, ':memory:') - s3 = providers.Singleton(S3Connection, + s3 = providers.Singleton(boto.s3.connection.S3Connection, aws_access_key_id='KEY', aws_secret_access_key='SECRET') @@ -84,32 +84,69 @@ Example class Services(catalogs.DeclarativeCatalog): """Catalog of business service providers.""" - users = providers.Factory(services.Users, + users = providers.Factory(example.services.Users, db=Platform.database) - photos = providers.Factory(services.Photos, + photos = providers.Factory(example.services.Photos, db=Platform.database, s3=Platform.s3) - auth = providers.Factory(services.Auth, + auth = providers.Factory(example.services.Auth, db=Platform.database, token_ttl=3600) +Next example demonstrates usage of these IoC containers with the help of +``@inject`` decorator: - @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): +.. code-block:: python + + """Dependency Injector example.""" + + 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(login, password, photo, users_service, auth_service, photos_service): """Main function.""" - login, password, photo_path = argv[1:] - user = users_service.get_user(login) auth_service.authenticate(user, password) - photos_service.upload_photo(user['id'], photo_path) + photos_service.upload_photo(user['id'], photo) if __name__ == '__main__': - main(sys.argv) + main(login='user', password='secret', photo='photo.jpg') + +Also some alternative definition styles could be used. Like this one: + +.. 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') + +or like this one: + +.. 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') You can get more *Dependency Injector* examples in ``/examples`` directory on GitHub: diff --git a/examples/miniapps/services/README.rst b/examples/miniapps/services/README.rst index ccf3947b..00c11981 100644 --- a/examples/miniapps/services/README.rst +++ b/examples/miniapps/services/README.rst @@ -5,4 +5,10 @@ Instructions for running: .. code-block:: bash - python main.py dependency-injector secret myself.jpg + python main.py + + +.. note:: + + ``catalogs_alt_style_1.py`` and ``catalogs_alt_style_2.py`` contain + examples of atlernative catalogs definition styles. diff --git a/examples/miniapps/services/catalogs.py b/examples/miniapps/services/catalogs.py new file mode 100644 index 00000000..3ff6ca2c --- /dev/null +++ b/examples/miniapps/services/catalogs.py @@ -0,0 +1,33 @@ +"""Example of several Dependency Injector catalogs.""" + +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) diff --git a/examples/miniapps/services/catalogs_alt_syntax_1.py b/examples/miniapps/services/catalogs_alt_syntax_1.py new file mode 100644 index 00000000..40863bfa --- /dev/null +++ b/examples/miniapps/services/catalogs_alt_syntax_1.py @@ -0,0 +1,37 @@ +"""Example of several Dependency Injector catalogs. + +Alternative 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) diff --git a/examples/miniapps/services/catalogs_alt_syntax_2.py b/examples/miniapps/services/catalogs_alt_syntax_2.py new file mode 100644 index 00000000..588b726e --- /dev/null +++ b/examples/miniapps/services/catalogs_alt_syntax_2.py @@ -0,0 +1,37 @@ +"""Example of several Dependency Injector catalogs. + +Alternative 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) diff --git a/examples/miniapps/services/main.py b/examples/miniapps/services/main.py index 30ebdb76..b0da2297 100644 --- a/examples/miniapps/services/main.py +++ b/examples/miniapps/services/main.py @@ -1,53 +1,19 @@ """Dependency Injector example.""" -import sys -import sqlite3 +from dependency_injector.injections import inject -from boto.s3.connection import S3Connection - -from dependency_injector import catalogs -from dependency_injector import providers -from dependency_injector import injections - -from example import services +from catalogs import Services -class Platform(catalogs.DeclarativeCatalog): - """Catalog of platform service providers.""" - - database = providers.Singleton(sqlite3.connect, ':memory:') - - 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): +@inject(users_service=Services.users) +@inject(auth_service=Services.auth) +@inject(photos_service=Services.photos) +def main(login, password, photo, users_service, auth_service, photos_service): """Main function.""" - login, password, photo_path = argv[1:] - user = users_service.get_user(login) auth_service.authenticate(user, password) - photos_service.upload_photo(user['id'], photo_path) + photos_service.upload_photo(user['id'], photo) if __name__ == '__main__': - main(sys.argv) + main(login='user', password='secret', photo='photo.jpg') diff --git a/examples/miniapps/services/main2.py b/examples/miniapps/services/main2.py deleted file mode 100644 index 517f5d38..00000000 --- a/examples/miniapps/services/main2.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Dependency Injector example.""" - -import sys -import sqlite3 - -from boto.s3.connection import S3Connection - -from dependency_injector import catalogs -from dependency_injector import providers -from dependency_injector import injections - -from example import services - - -class Platform(catalogs.DeclarativeCatalog): - """Catalog of platform service providers.""" - - database = providers.Singleton(sqlite3.connect) - database.args(':memory:') - - s3 = providers.Singleton(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(services.Users) - users.kwargs(db=Platform.database) - - photos = providers.Factory(services.Photos) - photos.kwargs(db=Platform.database, - s3=Platform.s3) - - auth = providers.Factory(services.Auth) - auth.kwargs(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.""" - login, password, photo_path = argv[1:] - - user = users_service.get_user(login) - auth_service.authenticate(user, password) - photos_service.upload_photo(user['id'], photo_path) - - -if __name__ == '__main__': - main(sys.argv) diff --git a/examples/miniapps/services/main3.py b/examples/miniapps/services/main3.py deleted file mode 100644 index 54fea3d3..00000000 --- a/examples/miniapps/services/main3.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Dependency Injector example.""" - -import sys -import sqlite3 - -from boto.s3.connection import S3Connection - -from dependency_injector import catalogs -from dependency_injector import providers -from dependency_injector import injections - -from example import services - - -class Platform(catalogs.DeclarativeCatalog): - """Catalog of platform service providers.""" - - database = providers.Singleton(sqlite3.connect) \ - .args(':memory:') - - s3 = providers.Singleton(S3Connection) \ - .kwargs(aws_access_key_id='KEY', - aws_secret_access_key='SECRET') - - -class Services(catalogs.DeclarativeCatalog): - """Catalog of business service providers.""" - - users = providers.Factory(services.Users) \ - .kwargs(db=Platform.database) - - photos = providers.Factory(services.Photos) \ - .kwargs(db=Platform.database, - s3=Platform.s3) - - auth = providers.Factory(services.Auth) \ - .kwargs(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.""" - login, password, photo_path = argv[1:] - - user = users_service.get_user(login) - auth_service.authenticate(user, password) - photos_service.upload_photo(user['id'], photo_path) - - -if __name__ == '__main__': - main(sys.argv) From d9aac553c5a48b1c6505511ed65b83e4e3ce393b Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Sun, 22 May 2016 14:57:25 +0300 Subject: [PATCH 07/11] Update factory and callable provider doc blocks --- dependency_injector/providers/callable.py | 16 ++++++++++-- dependency_injector/providers/creational.py | 29 ++++++++++++++++++--- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/dependency_injector/providers/callable.py b/dependency_injector/providers/callable.py index a26f10c6..7caffda5 100644 --- a/dependency_injector/providers/callable.py +++ b/dependency_injector/providers/callable.py @@ -19,9 +19,21 @@ class Callable(Provider): .. code-block:: python + some_function = Callable(some_function, + 'positional_arg1', 'positional_arg2', + keyword_argument1=3, keyword_argument=4) + + # or + some_function = Callable(some_function) \ - .args('arg1', 'arg2') \ - .kwargs(arg3=3, arg4=4) + .args('positional_arg1', 'positional_arg2') \ + .kwargs(keyword_argument1=3, keyword_argument=4) + + # or + + some_function = Callable(some_function) + some_function.args('positional_arg1', 'positional_arg2') + some_function.kwargs(keyword_argument1=3, keyword_argument=4) """ __slots__ = ('_provides', '_args', '_kwargs') diff --git a/dependency_injector/providers/creational.py b/dependency_injector/providers/creational.py index b5ba7c76..785c3471 100644 --- a/dependency_injector/providers/creational.py +++ b/dependency_injector/providers/creational.py @@ -12,14 +12,35 @@ class Factory(Callable): r""":py:class:`Factory` provider creates new instance on every call. :py:class:`Factory` supports positional & keyword argument injections, - as well as attribute injections: + as well as attribute injections. + + Positional and keyword argument injections could be defined like this: + + .. code-block:: python + + factory = Factory(SomeClass, + 'positional_arg1', 'positional_arg2', + keyword_argument1=3, keyword_argument=4) + + # or + + 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) \ - .args('arg1', 'arg2') \ - .kwargs(arg3=3, arg4=4) \ - .attributes(attribute1=5, attribute2=6) + .attributes(attribute1=1, attribute2=2) Retrieving of provided instance can be performed via calling :py:class:`Factory` object: From 7729d97a418c37db8eab6e9b022e5d3d1379368c Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Sun, 22 May 2016 15:37:39 +0300 Subject: [PATCH 08/11] Make injections 2 times faster --- dependency_injector/injections.py | 28 +++++++-------------- dependency_injector/providers/callable.py | 4 +-- dependency_injector/providers/creational.py | 6 ++--- tests/test_injections.py | 6 ++--- 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/dependency_injector/injections.py b/dependency_injector/injections.py index fe526715..2387c63c 100644 --- a/dependency_injector/injections.py +++ b/dependency_injector/injections.py @@ -38,7 +38,7 @@ class Injection(object): """ __IS_INJECTION__ = True - __slots__ = ('injectable', 'call_injectable') + __slots__ = ('injectable', 'get_value') def __init__(self, injectable): """Initializer. @@ -49,24 +49,14 @@ class Injection(object): :py:class:`dependency_injector.providers.Provider` """ 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__() - @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): """Return string representation of provider. @@ -229,11 +219,11 @@ def inject(*args, **kwargs): def decorated(*args, **kwargs): """Decorated with dependency injection callback.""" 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: if kwarg.name not in kwargs: - kwargs[kwarg.name] = kwarg.value + kwargs[kwarg.name] = kwarg.get_value() return callback(*args, **kwargs) diff --git a/dependency_injector/providers/callable.py b/dependency_injector/providers/callable.py index 7caffda5..f2714b3c 100644 --- a/dependency_injector/providers/callable.py +++ b/dependency_injector/providers/callable.py @@ -102,11 +102,11 @@ class Callable(Provider): :rtype: object """ 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: if kwarg.name not in kwargs: - kwargs[kwarg.name] = kwarg.value + kwargs[kwarg.name] = kwarg.get_value() return self._provides(*args, **kwargs) diff --git a/dependency_injector/providers/creational.py b/dependency_injector/providers/creational.py index 785c3471..4a307ed1 100644 --- a/dependency_injector/providers/creational.py +++ b/dependency_injector/providers/creational.py @@ -120,16 +120,16 @@ class Factory(Callable): :rtype: object """ 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: if kwarg.name not in kwargs: - kwargs[kwarg.name] = kwarg.value + kwargs[kwarg.name] = kwarg.get_value() instance = self._provides(*args, **kwargs) for attribute in self._attributes: - setattr(instance, attribute.name, attribute.value) + setattr(instance, attribute.name, attribute.get_value()) return instance diff --git a/tests/test_injections.py b/tests/test_injections.py index 9fca174f..c9385e18 100644 --- a/tests/test_injections.py +++ b/tests/test_injections.py @@ -19,12 +19,12 @@ class InjectionTests(unittest.TestCase): def test_value_with_scalar_injectable(self): """Test Injection value property with scalar 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): """Test Injection value property with provider.""" 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): """Test Injection value property with catalog bundle.""" @@ -35,7 +35,7 @@ class InjectionTests(unittest.TestCase): injection = injections.Injection( TestCatalog.Bundle(TestCatalog.provider)) - self.assertIsInstance(injection.value, TestCatalog.Bundle) + self.assertIsInstance(injection.get_value(), TestCatalog.Bundle) def test_repr(self): """Test Injection representation.""" From d8d6ba44e4a4e92bd056256f6e1933811d38401f Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Sun, 22 May 2016 16:02:10 +0300 Subject: [PATCH 09/11] Make some small fixes for services example --- README.rst | 26 ++++++++++++------- examples/miniapps/services/README.rst | 12 +++------ examples/miniapps/services/catalogs.py | 2 +- .../services/catalogs_alt_syntax_1.py | 4 +-- .../services/catalogs_alt_syntax_2.py | 4 +-- examples/miniapps/services/main.py | 12 ++++----- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/README.rst b/README.rst index b1770d23..0f1c2435 100644 --- a/README.rst +++ b/README.rst @@ -61,7 +61,7 @@ system that consists from several business and platform services: .. code-block:: python - """Example of several Dependency Injector catalogs.""" + """Example of several Dependency Injector IoC containers.""" import sqlite3 import boto.s3.connection @@ -95,12 +95,12 @@ system that consists from several business and platform services: db=Platform.database, token_ttl=3600) -Next example demonstrates usage of these IoC containers with the help of -``@inject`` decorator: +Next example demonstrates usage of ``@inject`` decorator with IoC containers +defined above: .. code-block:: python - """Dependency Injector example.""" + """Dependency Injector @inject decorator example.""" from dependency_injector.injections import inject @@ -110,17 +110,23 @@ Next example demonstrates usage of these IoC containers with the help of @inject(users_service=Services.users) @inject(auth_service=Services.auth) @inject(photos_service=Services.photos) - def main(login, password, photo, users_service, auth_service, photos_service): + def main(users_service, auth_service, photos_service): """Main function.""" - user = users_service.get_user(login) - auth_service.authenticate(user, password) - photos_service.upload_photo(user['id'], photo) + user = users_service.get_user('user') + auth_service.authenticate(user, 'secret') + photos_service.upload_photo(user['id'], 'photo.jpg') if __name__ == '__main__': - main(login='user', password='secret', photo='photo.jpg') + main() + +Alternative definition styles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Also some alternative definition styles could be used. Like this one: +*Dependecy Injector* supports few other styles of dependency injections +definition. + +Ioc containers could look like this one: .. code-block:: python diff --git a/examples/miniapps/services/README.rst b/examples/miniapps/services/README.rst index 00c11981..833bd44e 100644 --- a/examples/miniapps/services/README.rst +++ b/examples/miniapps/services/README.rst @@ -1,14 +1,8 @@ -Dependency Injector example -=========================== +Dependency Injector IoC containers example +========================================== -Instructions for running: +Instructions for running .. code-block:: bash python main.py - - -.. note:: - - ``catalogs_alt_style_1.py`` and ``catalogs_alt_style_2.py`` contain - examples of atlernative catalogs definition styles. diff --git a/examples/miniapps/services/catalogs.py b/examples/miniapps/services/catalogs.py index 3ff6ca2c..37a5bdf7 100644 --- a/examples/miniapps/services/catalogs.py +++ b/examples/miniapps/services/catalogs.py @@ -1,4 +1,4 @@ -"""Example of several Dependency Injector catalogs.""" +"""Example of several Dependency Injector IoC containers.""" import sqlite3 import boto.s3.connection diff --git a/examples/miniapps/services/catalogs_alt_syntax_1.py b/examples/miniapps/services/catalogs_alt_syntax_1.py index 40863bfa..8cc97603 100644 --- a/examples/miniapps/services/catalogs_alt_syntax_1.py +++ b/examples/miniapps/services/catalogs_alt_syntax_1.py @@ -1,6 +1,6 @@ -"""Example of several Dependency Injector catalogs. +"""Example of several Dependency Injector IoC containers. -Alternative definition style #1. +Alternative injections definition style #1. """ import sqlite3 diff --git a/examples/miniapps/services/catalogs_alt_syntax_2.py b/examples/miniapps/services/catalogs_alt_syntax_2.py index 588b726e..1d5746b9 100644 --- a/examples/miniapps/services/catalogs_alt_syntax_2.py +++ b/examples/miniapps/services/catalogs_alt_syntax_2.py @@ -1,6 +1,6 @@ -"""Example of several Dependency Injector catalogs. +"""Example of several Dependency Injector IoC containers. -Alternative definition style #2. +Alternative injections definition style #2. """ import sqlite3 diff --git a/examples/miniapps/services/main.py b/examples/miniapps/services/main.py index b0da2297..9398c8b3 100644 --- a/examples/miniapps/services/main.py +++ b/examples/miniapps/services/main.py @@ -1,4 +1,4 @@ -"""Dependency Injector example.""" +"""Dependency Injector @inject decorator example.""" from dependency_injector.injections import inject @@ -8,12 +8,12 @@ from catalogs import Services @inject(users_service=Services.users) @inject(auth_service=Services.auth) @inject(photos_service=Services.photos) -def main(login, password, photo, users_service, auth_service, photos_service): +def main(users_service, auth_service, photos_service): """Main function.""" - user = users_service.get_user(login) - auth_service.authenticate(user, password) - photos_service.upload_photo(user['id'], photo) + user = users_service.get_user('user') + auth_service.authenticate(user, 'secret') + photos_service.upload_photo(user['id'], 'photo.jpg') if __name__ == '__main__': - main(login='user', password='secret', photo='photo.jpg') + main() From 635c95380135bebb1d6e3246c093e4e3626773d0 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Sun, 22 May 2016 16:19:43 +0300 Subject: [PATCH 10/11] Update README with more extensive examples --- README.rst | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 0f1c2435..bb9f09c4 100644 --- a/README.rst +++ b/README.rst @@ -126,7 +126,7 @@ Alternative definition styles *Dependecy Injector* supports few other styles of dependency injections definition. -Ioc containers could look like this one: +IoC containers from previous example could look like these: .. code-block:: python @@ -140,7 +140,22 @@ Ioc containers could look like this one: .kwargs(aws_access_key_id='KEY', aws_secret_access_key='SECRET') -or like this one: + + 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 @@ -154,6 +169,21 @@ or like this one: 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 GitHub: From dffed4b56133f5e7ae742838bad20bcb6eec993f Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Sun, 22 May 2016 16:25:17 +0300 Subject: [PATCH 11/11] Update changelog --- docs/main/changelog.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/main/changelog.rst b/docs/main/changelog.rst index 1ea8f9fc..dc8f0d66 100644 --- a/docs/main/changelog.rst +++ b/docs/main/changelog.rst @@ -13,7 +13,9 @@ Development version 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: - ``Static`` - ``Value`` @@ -21,6 +23,7 @@ Development version - ``Class`` - ``Config`` - Drop ``Method`` injections. +- Drop backward compatibilities of 1.x. 1.17.0 ------