Moving @override decorator into catalogs module and @inject decorator into injections module

This commit is contained in:
Roman Mogilatov 2015-08-03 12:57:42 +03:00
parent 90455beb4c
commit 498465b705
7 changed files with 146 additions and 160 deletions

View File

@ -4,6 +4,7 @@ Dependency management tool for Python projects.
""" """
from .catalog import AbstractCatalog from .catalog import AbstractCatalog
from .catalog import override
from .providers import Provider from .providers import Provider
from .providers import Delegate from .providers import Delegate
@ -20,9 +21,7 @@ from .providers import Config
from .injections import KwArg from .injections import KwArg
from .injections import Attribute from .injections import Attribute
from .injections import Method from .injections import Method
from .injections import inject
from .decorators import override
from .decorators import inject
from .errors import Error from .errors import Error

View File

@ -65,3 +65,12 @@ class AbstractCatalog(object):
""" """
for name, provider in iteritems(overriding.providers): for name, provider in iteritems(overriding.providers):
cls.providers[name].override(provider) cls.providers[name].override(provider)
def override(catalog):
"""Catalog overriding decorator."""
def decorator(overriding_catalog):
"""Overriding decorator."""
catalog.override(overriding_catalog)
return overriding_catalog
return decorator

View File

@ -1,42 +0,0 @@
"""Decorators module."""
from six import wraps
from .utils import ensure_is_injection
from .utils import get_injectable_kwargs
def override(catalog):
"""Catalog overriding decorator."""
def decorator(overriding_catalog):
"""Overriding decorator."""
catalog.override(overriding_catalog)
return overriding_catalog
return decorator
def inject(injection):
"""Dependency injection decorator.
:type injection: Injection
:return: (callable) -> (callable)
"""
injection = ensure_is_injection(injection)
def decorator(callback):
"""Dependency injection decorator."""
if hasattr(callback, '_injections'):
callback._injections += (injection,)
@wraps(callback)
def decorated(*args, **kwargs):
"""Decorated with dependency injection callback."""
return callback(*args,
**get_injectable_kwargs(kwargs,
getattr(decorated,
'_injections')))
setattr(decorated, '_injections', (injection,))
return decorated
return decorator

View File

@ -1,6 +1,10 @@
"""Injections module.""" """Injections module."""
from six import wraps
from .utils import is_provider from .utils import is_provider
from .utils import ensure_is_injection
from .utils import get_injectable_kwargs
class Injection(object): class Injection(object):
@ -42,3 +46,30 @@ class Method(Injection):
"""Method injection.""" """Method injection."""
__IS_METHOD_INJECTION__ = True __IS_METHOD_INJECTION__ = True
def inject(injection):
"""Dependency injection decorator.
:type injection: Injection
:return: (callable) -> (callable)
"""
injection = ensure_is_injection(injection)
def decorator(callback):
"""Dependency injection decorator."""
if hasattr(callback, '_injections'):
callback._injections += (injection,)
@wraps(callback)
def decorated(*args, **kwargs):
"""Decorated with dependency injection callback."""
return callback(*args,
**get_injectable_kwargs(kwargs,
getattr(decorated,
'_injections')))
setattr(decorated, '_injections', (injection,))
return decorated
return decorator

View File

@ -3,6 +3,7 @@
import unittest2 as unittest import unittest2 as unittest
from objects.catalog import AbstractCatalog from objects.catalog import AbstractCatalog
from objects.catalog import override
from objects.providers import Object from objects.providers import Object
from objects.providers import Value from objects.providers import Value
@ -68,3 +69,29 @@ class CatalogTests(unittest.TestCase):
self.assertIs(Catalog2.provider, Catalog2.providers['provider']) self.assertIs(Catalog2.provider, Catalog2.providers['provider'])
self.assertIsNot(Catalog1.provider, Catalog2.provider) self.assertIsNot(Catalog1.provider, Catalog2.provider)
class OverrideTests(unittest.TestCase):
"""Override decorator test cases."""
class Catalog(AbstractCatalog):
"""Test catalog."""
obj = Object(object())
another_obj = Object(object())
def test_overriding(self):
"""Test catalog overriding with another catalog."""
@override(self.Catalog)
class OverridingCatalog(self.Catalog):
"""Overriding catalog."""
obj = Value(1)
another_obj = Value(2)
self.assertEqual(self.Catalog.obj(), 1)
self.assertEqual(self.Catalog.another_obj(), 2)

View File

@ -1,115 +0,0 @@
"""Objects decorators unittests."""
import unittest2 as unittest
from objects.decorators import override
from objects.decorators import inject
from objects.catalog import AbstractCatalog
from objects.providers import Factory
from objects.providers import Object
from objects.providers import Value
from objects.injections import KwArg
from objects.errors import Error
class OverrideTests(unittest.TestCase):
"""Override decorator test cases."""
class Catalog(AbstractCatalog):
"""Test catalog."""
obj = Object(object())
another_obj = Object(object())
def test_overriding(self):
"""Test catalog overriding with another catalog."""
@override(self.Catalog)
class OverridingCatalog(self.Catalog):
"""Overriding catalog."""
obj = Value(1)
another_obj = Value(2)
self.assertEqual(self.Catalog.obj(), 1)
self.assertEqual(self.Catalog.another_obj(), 2)
class InjectTests(unittest.TestCase):
"""Inject decorator test cases."""
def test_decorated(self):
"""Test `inject()` decorated callback."""
provider1 = Factory(object)
provider2 = Factory(list)
@inject(KwArg('a', provider1))
@inject(KwArg('b', provider2))
def test(a, b):
return a, b
a1, b1 = test()
a2, b2 = test()
self.assertIsInstance(a1, object)
self.assertIsInstance(a2, object)
self.assertIsNot(a1, a2)
self.assertIsInstance(b1, list)
self.assertIsInstance(b2, list)
self.assertIsNot(b1, b2)
def test_decorated_kwargs_priority(self):
"""Test `inject()` decorated callback kwargs priority."""
provider1 = Factory(object)
provider2 = Factory(list)
object_a = object()
@inject(KwArg('a', provider1))
@inject(KwArg('b', provider2))
def test(a, b):
return a, b
a1, b1 = test(a=object_a)
a2, b2 = test(a=object_a)
self.assertIsInstance(a1, object)
self.assertIsInstance(a2, object)
self.assertIs(a1, object_a)
self.assertIs(a2, object_a)
self.assertIsInstance(b1, list)
self.assertIsInstance(b2, list)
self.assertIsNot(b1, b2)
def test_decorated_with_args(self):
"""Test `inject()` decorated callback with args."""
provider = Factory(list)
object_a = object()
@inject(KwArg('b', provider))
def test(a, b):
return a, b
a1, b1 = test(object_a)
a2, b2 = test(object_a)
self.assertIsInstance(a1, object)
self.assertIsInstance(a2, object)
self.assertIs(a1, object_a)
self.assertIs(a2, object_a)
self.assertIsInstance(b1, list)
self.assertIsInstance(b2, list)
self.assertIsNot(b1, b2)
def test_decorate_with_not_injection(self):
"""Test `inject()` decorator with not an injection instance."""
self.assertRaises(Error, inject, object)

View File

@ -6,9 +6,12 @@ from objects.injections import Injection
from objects.injections import KwArg from objects.injections import KwArg
from objects.injections import Attribute from objects.injections import Attribute
from objects.injections import Method from objects.injections import Method
from objects.injections import inject
from objects.providers import Factory from objects.providers import Factory
from objects.errors import Error
class InjectionTests(unittest.TestCase): class InjectionTests(unittest.TestCase):
@ -62,3 +65,77 @@ class MethodTests(unittest.TestCase):
injection = Method('some_arg_name', 'some_value') injection = Method('some_arg_name', 'some_value')
self.assertEqual(injection.name, 'some_arg_name') self.assertEqual(injection.name, 'some_arg_name')
self.assertEqual(injection.injectable, 'some_value') self.assertEqual(injection.injectable, 'some_value')
class InjectTests(unittest.TestCase):
"""Inject decorator test cases."""
def test_decorated(self):
"""Test `inject()` decorated callback."""
provider1 = Factory(object)
provider2 = Factory(list)
@inject(KwArg('a', provider1))
@inject(KwArg('b', provider2))
def test(a, b):
return a, b
a1, b1 = test()
a2, b2 = test()
self.assertIsInstance(a1, object)
self.assertIsInstance(a2, object)
self.assertIsNot(a1, a2)
self.assertIsInstance(b1, list)
self.assertIsInstance(b2, list)
self.assertIsNot(b1, b2)
def test_decorated_kwargs_priority(self):
"""Test `inject()` decorated callback kwargs priority."""
provider1 = Factory(object)
provider2 = Factory(list)
object_a = object()
@inject(KwArg('a', provider1))
@inject(KwArg('b', provider2))
def test(a, b):
return a, b
a1, b1 = test(a=object_a)
a2, b2 = test(a=object_a)
self.assertIsInstance(a1, object)
self.assertIsInstance(a2, object)
self.assertIs(a1, object_a)
self.assertIs(a2, object_a)
self.assertIsInstance(b1, list)
self.assertIsInstance(b2, list)
self.assertIsNot(b1, b2)
def test_decorated_with_args(self):
"""Test `inject()` decorated callback with args."""
provider = Factory(list)
object_a = object()
@inject(KwArg('b', provider))
def test(a, b):
return a, b
a1, b1 = test(object_a)
a2, b2 = test(object_a)
self.assertIsInstance(a1, object)
self.assertIsInstance(a2, object)
self.assertIs(a1, object_a)
self.assertIs(a2, object_a)
self.assertIsInstance(b1, list)
self.assertIsInstance(b2, list)
self.assertIsNot(b1, b2)
def test_decorate_with_not_injection(self):
"""Test `inject()` decorator with not an injection instance."""
self.assertRaises(Error, inject, object)