From 05d6db5664b6bad2a8dc37b83d5101ecab632be6 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Tue, 10 Nov 2015 19:38:18 +0200 Subject: [PATCH] Make some refactoring after DynamicCatalog implementation --- dependency_injector/__init__.py | 17 ++- .../{catalog.py => catalogs.py} | 106 +++++++++--------- dependency_injector/utils.py | 13 ++- tests/{test_catalog.py => test_catalogs.py} | 2 +- tests/test_utils.py | 34 +++++- 5 files changed, 109 insertions(+), 63 deletions(-) rename dependency_injector/{catalog.py => catalogs.py} (98%) rename tests/{test_catalog.py => test_catalogs.py} (99%) diff --git a/dependency_injector/__init__.py b/dependency_injector/__init__.py index 40184efd..252c6cd3 100644 --- a/dependency_injector/__init__.py +++ b/dependency_injector/__init__.py @@ -1,10 +1,10 @@ """Dependency injector.""" -from .catalog import DeclarativeCatalog -from .catalog import AbstractCatalog -from .catalog import DynamicCatalog -from .catalog import CatalogBundle -from .catalog import override +from .catalogs import DeclarativeCatalog +from .catalogs import AbstractCatalog +from .catalogs import DynamicCatalog +from .catalogs import CatalogBundle +from .catalogs import override from .providers import Provider from .providers import Delegate @@ -35,11 +35,16 @@ from .utils import is_kwarg_injection from .utils import is_attribute_injection from .utils import is_method_injection from .utils import is_catalog +from .utils import is_dynamic_catalog +from .utils import is_declarative_catalog from .utils import is_catalog_bundle from .utils import ensure_is_catalog_bundle from .errors import Error +# Backward compatimility fix for versions < 0.11.* +from . import catalogs +catalog = catalogs VERSION = '0.10.5' @@ -84,6 +89,8 @@ __all__ = ( 'is_attribute_injection', 'is_method_injection', 'is_catalog', + 'is_dynamic_catalog', + 'is_declarative_catalog', 'is_catalog_bundle', 'ensure_is_catalog_bundle', diff --git a/dependency_injector/catalog.py b/dependency_injector/catalogs.py similarity index 98% rename from dependency_injector/catalog.py rename to dependency_injector/catalogs.py index e399e7d4..2a688760 100644 --- a/dependency_injector/catalog.py +++ b/dependency_injector/catalogs.py @@ -1,4 +1,4 @@ -"""Catalog module.""" +"""Catalogs module.""" import six @@ -10,6 +10,60 @@ from .utils import ensure_is_provider from .utils import ensure_is_catalog_bundle +@six.python_2_unicode_compatible +class CatalogBundle(object): + """Bundle of catalog providers.""" + + catalog = None + """:type: DeclarativeCatalog""" + + __IS_CATALOG_BUNDLE__ = True + __slots__ = ('providers', '__dict__') + + def __init__(self, *providers): + """Initializer.""" + self.providers = dict((self.catalog.get_provider_bind_name(provider), + provider) + for provider in providers) + self.__dict__.update(self.providers) + super(CatalogBundle, self).__init__() + + @classmethod + def sub_cls_factory(cls, catalog): + """Create bundle class for catalog. + + :rtype: CatalogBundle + :return: Subclass of CatalogBundle + """ + return type('{0}Bundle'.format(catalog.name), (cls,), + dict(catalog=catalog)) + + def get(self, name): + """Return provider with specified name or raise an error.""" + try: + return self.providers[name] + except KeyError: + raise Error('Provider "{0}" is not a part of {1}'.format(name, + self)) + + def has(self, name): + """Check if there is provider with certain name.""" + return name in self.providers + + def __getattr__(self, item): + """Raise an error on every attempt to get undefined provider.""" + if item.startswith('__') and item.endswith('__'): + return super(CatalogBundle, self).__getattr__(item) + raise Error('Provider "{0}" is not a part of {1}'.format(item, self)) + + def __repr__(self): + """Return string representation of catalog bundle.""" + return '<{0}.Bundle({1})>'.format( + self.catalog.name, ', '.join(six.iterkeys(self.providers))) + + __str__ = __repr__ + + @six.python_2_unicode_compatible class DynamicCatalog(object): """Catalog of providers.""" @@ -117,56 +171,6 @@ class DynamicCatalog(object): __str__ = __repr__ -@six.python_2_unicode_compatible -class CatalogBundle(object): - """Bundle of catalog providers.""" - - catalog = None - """:type: DeclarativeCatalog""" - - __IS_CATALOG_BUNDLE__ = True - __slots__ = ('providers', '__dict__') - - def __init__(self, *providers): - """Initializer.""" - self.providers = dict((self.catalog.get_provider_bind_name(provider), - provider) - for provider in providers) - self.__dict__.update(self.providers) - super(CatalogBundle, self).__init__() - - @classmethod - def sub_cls_factory(cls, catalog): - """Create bundle class for catalog.""" - return type('{0}Bundle'.format(catalog.name), (cls,), - dict(catalog=catalog)) - - def get(self, name): - """Return provider with specified name or raise an error.""" - try: - return self.providers[name] - except KeyError: - raise Error('Provider "{0}" is not a part of {1}'.format(name, - self)) - - def has(self, name): - """Check if there is provider with certain name.""" - return name in self.providers - - def __getattr__(self, item): - """Raise an error on every attempt to get undefined provider.""" - if item.startswith('__') and item.endswith('__'): - return super(CatalogBundle, self).__getattr__(item) - raise Error('Provider "{0}" is not a part of {1}'.format(item, self)) - - def __repr__(self): - """Return string representation of catalog bundle.""" - return '<{0}.Bundle({1})>'.format( - self.catalog.name, ', '.join(six.iterkeys(self.providers))) - - __str__ = __repr__ - - @six.python_2_unicode_compatible class DeclarativeCatalogMetaClass(type): """Declarative catalog meta class.""" diff --git a/dependency_injector/utils.py b/dependency_injector/utils.py index ecf77164..cb837d87 100644 --- a/dependency_injector/utils.py +++ b/dependency_injector/utils.py @@ -73,11 +73,20 @@ def is_method_injection(instance): def is_catalog(instance): """Check if instance is catalog instance.""" - return (isinstance(instance, six.class_types) and - hasattr(instance, '__IS_CATALOG__') and + return (hasattr(instance, '__IS_CATALOG__') and getattr(instance, '__IS_CATALOG__', False) is True) +def is_dynamic_catalog(instance): + """Check if instance is dynamic catalog instance.""" + return (not isinstance(instance, six.class_types) and is_catalog(instance)) + + +def is_declarative_catalog(instance): + """Check if instance is declarative catalog instance.""" + return (isinstance(instance, six.class_types) and is_catalog(instance)) + + def is_catalog_bundle(instance): """Check if instance is catalog bundle instance.""" return (not isinstance(instance, six.class_types) and diff --git a/tests/test_catalog.py b/tests/test_catalogs.py similarity index 99% rename from tests/test_catalog.py rename to tests/test_catalogs.py index cb7453af..fb295732 100644 --- a/tests/test_catalog.py +++ b/tests/test_catalogs.py @@ -1,4 +1,4 @@ -"""Dependency injector catalog unittests.""" +"""Dependency injector catalogs unittests.""" import unittest2 as unittest import dependency_injector as di diff --git a/tests/test_utils.py b/tests/test_utils.py index 275989f0..f77298e4 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -211,13 +211,13 @@ class IsMethodInjectionTests(unittest.TestCase): class IsCatalogTests(unittest.TestCase): """`is_catalog()` test cases.""" - def test_with_cls(self): + def test_with_declarative_catalog(self): """Test with class.""" - self.assertTrue(di.is_catalog(di.AbstractCatalog)) + self.assertTrue(di.is_catalog(di.DeclarativeCatalog)) - def test_with_instance(self): + def test_with_dynamic_catalog(self): """Test with class.""" - self.assertFalse(di.is_catalog(di.AbstractCatalog())) + self.assertTrue(di.is_catalog(di.DynamicCatalog('TestCatalog'))) def test_with_child_class(self): """Test with parent class.""" @@ -235,6 +235,32 @@ class IsCatalogTests(unittest.TestCase): self.assertFalse(di.is_catalog(object())) +class IsDynamicCatalogTests(unittest.TestCase): + """`is_dynamic_catalog()` test cases.""" + + def test_with_declarative_catalog(self): + """Test with declarative catalog.""" + self.assertFalse(di.is_dynamic_catalog(di.DeclarativeCatalog)) + + def test_with_dynamic_catalog(self): + """Test with dynamic catalog.""" + self.assertTrue(di.is_dynamic_catalog(di.DynamicCatalog( + 'TestCatalog'))) + + +class IsDeclarativeCatalogTests(unittest.TestCase): + """`is_declarative_catalog()` test cases.""" + + def test_with_declarative_catalog(self): + """Test with declarative catalog.""" + self.assertTrue(di.is_declarative_catalog(di.DeclarativeCatalog)) + + def test_with_dynamic_catalog(self): + """Test with dynamic catalog.""" + self.assertFalse(di.is_declarative_catalog(di.DynamicCatalog( + 'TestCatalog'))) + + class IsCatalogBundleTests(unittest.TestCase): """`is_catalog_bundle()` test cases."""