From 918335e0e45c6def13baf999fae4de13e0263a59 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Sun, 22 May 2016 16:49:08 +0300 Subject: [PATCH] Remove catalog bundles --- dependency_injector/catalogs/__init__.py | 2 - dependency_injector/catalogs/bundle.py | 118 -------------------- dependency_injector/catalogs/declarative.py | 22 ---- dependency_injector/catalogs/dynamic.py | 22 +--- dependency_injector/utils.py | 30 ----- docs/catalogs/bundles.rst | 63 ----------- docs/catalogs/index.rst | 1 - docs/main/changelog.rst | 1 + examples/catalogs/bundles/catalogs.py | 59 ---------- examples/catalogs/bundles/services.py | 17 --- examples/catalogs/bundles/views.py | 21 ---- tests/catalogs/test_bundle.py | 101 ----------------- tests/test_injections.py | 12 -- tests/test_utils.py | 47 -------- 14 files changed, 2 insertions(+), 514 deletions(-) delete mode 100644 dependency_injector/catalogs/bundle.py delete mode 100644 docs/catalogs/bundles.rst delete mode 100644 examples/catalogs/bundles/catalogs.py delete mode 100644 examples/catalogs/bundles/services.py delete mode 100644 examples/catalogs/bundles/views.py delete mode 100644 tests/catalogs/test_bundle.py diff --git a/dependency_injector/catalogs/__init__.py b/dependency_injector/catalogs/__init__.py index a6a5b9c4..c6e139fd 100644 --- a/dependency_injector/catalogs/__init__.py +++ b/dependency_injector/catalogs/__init__.py @@ -1,6 +1,5 @@ """Dependency injector catalogs package.""" -from dependency_injector.catalogs.bundle import CatalogBundle from dependency_injector.catalogs.dynamic import DynamicCatalog from dependency_injector.catalogs.declarative import ( DeclarativeCatalogMetaClass, @@ -13,7 +12,6 @@ from dependency_injector.catalogs.utils import ( __all__ = ( - 'CatalogBundle', 'DynamicCatalog', 'DeclarativeCatalogMetaClass', 'DeclarativeCatalog', diff --git a/dependency_injector/catalogs/bundle.py b/dependency_injector/catalogs/bundle.py deleted file mode 100644 index 6da2dcf7..00000000 --- a/dependency_injector/catalogs/bundle.py +++ /dev/null @@ -1,118 +0,0 @@ -"""Dependency injector catalogs bundle module.""" - -import six - -from dependency_injector.errors import ( - Error, - UndefinedProviderError, -) - - -@six.python_2_unicode_compatible -class CatalogBundle(object): - """Bundle of catalog providers. - - :py:class:`CatalogBundle` is a frozen, limited collection of catalog - providers. While catalog could be used as a centralized place for - particular providers group, such bundles of catalog providers can be used - for creating several frozen, limited scopes that could be passed to - different subsystems. - - :py:class:`CatalogBundle` has API's parity with catalogs - (:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) in terms of - retrieving the providers, but it is "frozen" in terms of modification - provider's list. - - :py:class:`CatalogBundle` is considered to be dependable on catalogs - (:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) entity by - its design. - - .. py:attribute:: catalog - - Bundle's catalog. - - :type: :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog` - - .. py:attribute:: providers - - Dictionary of all providers. - - :type: dict[str, :py:class:`dependency_injector.providers.Provider`] - """ - - catalog = None - - __IS_CATALOG_BUNDLE__ = True - __slots__ = ('providers', '__dict__') - - @classmethod - def sub_cls_factory(cls, catalog): - """Create bundle subclass for catalog. - - :return: Subclass of :py:class:`CatalogBundle`. - :rtype: :py:class:`CatalogBundle` - """ - return type('BundleSubclass', (cls,), dict(catalog=catalog)) - - def __init__(self, *providers): - """Initializer. - - :param providers: Tuple of catalog's bundle providers. - :type providers: tuple[ - :py:class:`dependency_injector.providers.Provider`] - """ - self.providers = dict((self.catalog.get_provider_bind_name(provider), - provider) - for provider in providers) - self.__dict__.update(self.providers) - super(CatalogBundle, self).__init__() - - def get_provider(self, name): - """Return provider with specified name or raise an error. - - :param name: Provider's name. - :type name: str - - :raise: :py:exc:`dependency_injector.errors.UndefinedProviderError` - - :return: Provider with specified name. - :rtype: :py:class:`dependency_injector.providers.Provider` - """ - try: - return self.providers[name] - except KeyError: - raise Error('Provider "{0}" is not a part of {1}'.format(name, - self)) - - def has_provider(self, name): - """Check if there is provider with certain name. - - :param name: Provider's name. - :type name: str - - :rtype: bool - """ - return name in self.providers - - def __getattr__(self, item): - """Return provider with specified name or raise en error. - - :param name: Attribute's name. - :type name: str - - :raise: :py:exc:`dependency_injector.errors.UndefinedProviderError` - """ - if item.startswith('__') and item.endswith('__'): - return super(CatalogBundle, self).__getattr__(item) - raise UndefinedProviderError('Provider "{0}" is not a part ' - 'of {1}'.format(item, self)) - - def __repr__(self): - """Return string representation of catalog's bundle. - - :rtype: str - """ - return '<{0}.Bundle({1})>'.format( - self.catalog.name, ', '.join(six.iterkeys(self.providers))) - - __str__ = __repr__ diff --git a/dependency_injector/catalogs/declarative.py b/dependency_injector/catalogs/declarative.py index 777ad9e8..a6fc84a2 100644 --- a/dependency_injector/catalogs/declarative.py +++ b/dependency_injector/catalogs/declarative.py @@ -3,7 +3,6 @@ import six from dependency_injector.catalogs.dynamic import DynamicCatalog -from dependency_injector.catalogs.bundle import CatalogBundle from dependency_injector.utils import ( is_provider, is_catalog, @@ -47,8 +46,6 @@ class DeclarativeCatalogMetaClass(type): cls._cls_providers = dict(cls_providers) cls._inherited_providers = dict(inherited_providers) - cls.Bundle = cls._catalog.Bundle - return cls @property @@ -187,12 +184,6 @@ class DeclarativeCatalog(object): users_service = Services.users() - .. py:attribute:: Bundle - - Catalog's bundle class. - - :type: :py:class:`CatalogBundle` - .. py:attribute:: provider_type If provider type is defined, :py:class:`DeclarativeCatalog` checks that @@ -202,8 +193,6 @@ class DeclarativeCatalog(object): :type: type | None """ - Bundle = CatalogBundle - provider_type = None _catalog = DynamicCatalog @@ -273,17 +262,6 @@ class DeclarativeCatalog(object): """ return self.__class__.last_overriding - @classmethod - def is_bundle_owner(cls, bundle): - """Check if catalog is bundle owner. - - :param bundle: Catalog's bundle instance. - :type bundle: :py:class:`CatalogBundle` - - :rtype: bool - """ - return cls._catalog.is_bundle_owner(bundle) - @classmethod def get_provider_bind_name(cls, provider): """Return provider's name in catalog. diff --git a/dependency_injector/catalogs/dynamic.py b/dependency_injector/catalogs/dynamic.py index 607b8124..7269e4e1 100644 --- a/dependency_injector/catalogs/dynamic.py +++ b/dependency_injector/catalogs/dynamic.py @@ -2,11 +2,9 @@ import six -from dependency_injector.catalogs.bundle import CatalogBundle from dependency_injector.utils import ( is_provider, ensure_is_provider, - ensure_is_catalog_bundle, ) from dependency_injector.errors import ( Error, @@ -32,12 +30,6 @@ class DynamicCatalog(object): users_service = services.users() - .. py:attribute:: Bundle - - Catalog's bundle class. - - :type: :py:class:`CatalogBundle` - .. py:attribute:: name Catalog's name. @@ -71,8 +63,7 @@ class DynamicCatalog(object): provider_type = None __IS_CATALOG__ = True - __slots__ = ('name', 'providers', 'provider_names', 'overridden_by', - 'Bundle') + __slots__ = ('name', 'providers', 'provider_names', 'overridden_by') def __init__(self, **providers): """Initializer. @@ -81,7 +72,6 @@ class DynamicCatalog(object): :type providers: dict[str, :py:class:`dependency_injector.providers.Provider`] """ - self.Bundle = CatalogBundle.sub_cls_factory(self) self.name = '.'.join((self.__class__.__module__, self.__class__.__name__)) self.providers = dict() @@ -90,16 +80,6 @@ class DynamicCatalog(object): self.bind_providers(providers) super(DynamicCatalog, self).__init__() - def is_bundle_owner(self, bundle): - """Check if catalog is bundle owner. - - :param bundle: Catalog's bundle instance. - :type bundle: :py:class:`CatalogBundle` - - :rtype: bool - """ - return ensure_is_catalog_bundle(bundle) and bundle.catalog is self - def get_provider_bind_name(self, provider): """Return provider's name in catalog. diff --git a/dependency_injector/utils.py b/dependency_injector/utils.py index 13a35325..fb6bedeb 100644 --- a/dependency_injector/utils.py +++ b/dependency_injector/utils.py @@ -175,36 +175,6 @@ def 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. - - :param instance: Instance to be checked. - :type instance: object - - :rtype: bool - """ - return (not isinstance(instance, six.class_types) and - hasattr(instance, '__IS_CATALOG_BUNDLE__') and - getattr(instance, '__IS_CATALOG_BUNDLE__', False) is True) - - -def ensure_is_catalog_bundle(instance): - """Check if instance is catalog bundle instance and return it. - - :param instance: Instance to be checked. - :type instance: object - - :raise: :py:exc:`dependency_injector.errors.Error` if provided instance - is not catalog bundle. - - :rtype: :py:class:`dependency_injector.catalogs.CatalogBundle` - """ - if not is_catalog_bundle(instance): - raise Error('Expected catalog bundle instance, ' - 'got {0}'.format(str(instance))) - return instance - - def represent_provider(provider, provides): """Return string representation of provider. diff --git a/docs/catalogs/bundles.rst b/docs/catalogs/bundles.rst deleted file mode 100644 index 7ecaa3d3..00000000 --- a/docs/catalogs/bundles.rst +++ /dev/null @@ -1,63 +0,0 @@ -Catalog provider bundles ------------------------- - -.. currentmodule:: dependency_injector.catalogs - -:py:class:`CatalogBundle` is a frozen, limited collection of catalog -providers. While catalog could be used as a centralized place for -particular providers group, such bundles of catalog providers can be used -for creating several frozen, limited scopes that could be passed to different -subsystems. - -:py:class:`CatalogBundle` has API's parity with catalogs -(:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) in terms of -retrieving the providers, but it is "frozen" in terms of modification -provider's list. - -:py:class:`CatalogBundle` is considered to be dependable on catalogs -(:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) entity by -its design. - -Each catalog (:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) -has a reference to its bundle class - :py:attr:`DeclarativeCatalog.Bundle` -(or :py:attr:`DynamicCatalog.Bundle` consequently). For example, subclass of -:py:class:`CatalogBundle` for some concrete declarative catalog -``SomeCatalog`` could be reached as ``SomeCatalog.Bundle``. - -:py:class:`CatalogBundle` expects to get the list of its catalog providers -as positional arguments and will limit the scope of created bundle to this -list. - -.. note:: - - Some notes about :py:class:`CatalogBundle` design. - - Design and syntax of :py:class:`CatalogBundle` was developed with the idea - of keeping full functionalities of type-hinting and introspection of - modern IDE's. This design came from some practical experience of using - :py:class:`CatalogBundle` and considered to be the most comfortable for - developer. - -Example: - -.. image:: /images/catalogs/bundles.png - :width: 100% - :align: center - -Listing of `services.py`: - -.. literalinclude:: ../../examples/catalogs/bundles/services.py - :language: python - :linenos: - -Listing of `views.py`: - -.. literalinclude:: ../../examples/catalogs/bundles/views.py - :language: python - :linenos: - -Listing of `catalogs.py`: - -.. literalinclude:: ../../examples/catalogs/bundles/catalogs.py - :language: python - :linenos: diff --git a/docs/catalogs/index.rst b/docs/catalogs/index.rst index e1888cab..fa4e4ca8 100644 --- a/docs/catalogs/index.rst +++ b/docs/catalogs/index.rst @@ -23,6 +23,5 @@ Catalogs module API docs - :py:mod:`dependency_injector.catalogs`. declarative dynamic - bundles specialization overriding diff --git a/docs/main/changelog.rst b/docs/main/changelog.rst index dc8f0d66..03246ede 100644 --- a/docs/main/changelog.rst +++ b/docs/main/changelog.rst @@ -23,6 +23,7 @@ Development version - ``Class`` - ``Config`` - Drop ``Method`` injections. +- Drop catalog bundles. - Drop backward compatibilities of 1.x. 1.17.0 diff --git a/examples/catalogs/bundles/catalogs.py b/examples/catalogs/bundles/catalogs.py deleted file mode 100644 index e5a9b397..00000000 --- a/examples/catalogs/bundles/catalogs.py +++ /dev/null @@ -1,59 +0,0 @@ -"""Catalog bundles example.""" - -from dependency_injector import catalogs -from dependency_injector import providers -from dependency_injector import errors - -import services -import views - - -# Declaring services catalog: -class Services(catalogs.DeclarativeCatalog): - """Example catalog of service providers.""" - - users = providers.Factory(services.Users) - - auth = providers.Factory(services.Auth) - - photos = providers.Factory(services.Photos) - - -# Declaring views catalog: -class Views(catalogs.DeclarativeCatalog): - """Example catalog of web views.""" - - auth = providers.Factory(views.Auth, - services=Services.Bundle(Services.users, - Services.auth)) - - photos = providers.Factory(views.Photos, - services=Services.Bundle(Services.users, - Services.photos)) - - -# Creating example views: -auth_view = Views.auth() -photos_view = Views.photos() - -print auth_view.services # prints: <__main__.Services.Bundle(users, auth)> -print photos_view.services # prints <__main__.Services.Bundle(photos, users)> - -# Making some asserts: -assert auth_view.services.users is Services.users -assert auth_view.services.auth is Services.auth -try: - auth_view.services.photos -except errors.Error: - # `photos` service provider is not in scope of `auth_view` services bundle, - # so `di.Error` will be raised. - pass - -assert photos_view.services.users is Services.users -assert photos_view.services.photos is Services.photos -try: - photos_view.services.auth -except errors.Error as exception: - # `auth` service provider is not in scope of `photo_processing_view` - # services bundle, so `di.Error` will be raised. - pass diff --git a/examples/catalogs/bundles/services.py b/examples/catalogs/bundles/services.py deleted file mode 100644 index 95f48b65..00000000 --- a/examples/catalogs/bundles/services.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Example services.""" - - -class BaseService(object): - """Example base class of service.""" - - -class Users(BaseService): - """Example users service.""" - - -class Auth(BaseService): - """Example auth service.""" - - -class Photos(BaseService): - """Example photo service.""" diff --git a/examples/catalogs/bundles/views.py b/examples/catalogs/bundles/views.py deleted file mode 100644 index 2be4dd03..00000000 --- a/examples/catalogs/bundles/views.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Example web views.""" - - -class BaseWebView(object): - """Example base class of web view.""" - - def __init__(self, services): - """Initializer. - - :param services: Bundle of service providers - :type services: catalogs.Services - """ - self.services = services - - -class Auth(BaseWebView): - """Example auth web view.""" - - -class Photos(BaseWebView): - """Example photo processing web view.""" diff --git a/tests/catalogs/test_bundle.py b/tests/catalogs/test_bundle.py deleted file mode 100644 index d6a17ba6..00000000 --- a/tests/catalogs/test_bundle.py +++ /dev/null @@ -1,101 +0,0 @@ -"""Dependency injector catalog bundles unittests.""" - -import unittest2 as unittest - -from dependency_injector import ( - catalogs, - providers, - errors, -) - - -class CatalogA(catalogs.DeclarativeCatalog): - """Test catalog A.""" - - p11 = providers.Provider() - p12 = providers.Provider() - - -class CatalogB(CatalogA): - """Test catalog B.""" - - p21 = providers.Provider() - p22 = providers.Provider() - - -class CatalogBundleTests(unittest.TestCase): - """Catalog bundle test cases.""" - - def setUp(self): - """Set test environment up.""" - self.bundle = CatalogB.Bundle(CatalogB.p11, - CatalogB.p12) - - def test_get_attr_from_bundle(self): - """Test get providers (attribute) from catalog bundle.""" - self.assertIs(self.bundle.p11, CatalogA.p11) - self.assertIs(self.bundle.p12, CatalogA.p12) - - def test_get_attr_not_from_bundle(self): - """Test get providers (attribute) that are not in bundle.""" - self.assertRaises(errors.Error, getattr, self.bundle, 'p21') - self.assertRaises(errors.Error, getattr, self.bundle, 'p22') - - def test_get_method_from_bundle(self): - """Test get providers (get() method) from bundle.""" - self.assertIs(self.bundle.get_provider('p11'), CatalogB.p11) - self.assertIs(self.bundle.get_provider('p12'), CatalogB.p12) - - def test_get_method_not_from_bundle(self): - """Test get providers (get() method) that are not in bundle.""" - self.assertRaises(errors.Error, self.bundle.get_provider, 'p21') - self.assertRaises(errors.Error, self.bundle.get_provider, 'p22') - - def test_has(self): - """Test checks of providers availability in bundle.""" - self.assertTrue(self.bundle.has_provider('p11')) - self.assertTrue(self.bundle.has_provider('p12')) - - self.assertFalse(self.bundle.has_provider('p21')) - self.assertFalse(self.bundle.has_provider('p22')) - - def test_hasattr(self): - """Test checks of providers availability in bundle.""" - self.assertTrue(hasattr(self.bundle, 'p11')) - self.assertTrue(hasattr(self.bundle, 'p12')) - - self.assertFalse(hasattr(self.bundle, 'p21')) - self.assertFalse(hasattr(self.bundle, 'p22')) - - def test_create_bundle_with_unbound_provider(self): - """Test that bundle is not created with unbound provider.""" - self.assertRaises(errors.Error, CatalogB.Bundle, providers.Provider()) - - def test_create_bundle_with_another_catalog_provider(self): - """Test that bundle can not contain another catalog's provider.""" - class TestCatalog(catalogs.DeclarativeCatalog): - """Test catalog.""" - - provider = providers.Provider() - - self.assertRaises(errors.Error, - CatalogB.Bundle, CatalogB.p21, TestCatalog.provider) - - def test_create_bundle_with_another_catalog_provider_with_same_name(self): - """Test that bundle can not contain another catalog's provider.""" - class TestCatalog(catalogs.DeclarativeCatalog): - """Test catalog.""" - - p21 = providers.Provider() - - self.assertRaises(errors.Error, - CatalogB.Bundle, CatalogB.p21, TestCatalog.p21) - - def test_is_bundle_owner(self): - """Test that catalog bundle is owned by catalog.""" - self.assertTrue(CatalogB.is_bundle_owner(self.bundle)) - self.assertFalse(CatalogA.is_bundle_owner(self.bundle)) - - def test_is_bundle_owner_with_not_bundle_instance(self): - """Test that check of bundle ownership raises error with not bundle.""" - self.assertRaises(errors.Error, CatalogB.is_bundle_owner, object()) diff --git a/tests/test_injections.py b/tests/test_injections.py index c9385e18..de3b16a2 100644 --- a/tests/test_injections.py +++ b/tests/test_injections.py @@ -3,7 +3,6 @@ import unittest2 as unittest from dependency_injector import injections -from dependency_injector import catalogs from dependency_injector import providers from dependency_injector import errors @@ -26,17 +25,6 @@ class InjectionTests(unittest.TestCase): injection = injections.Injection(providers.Factory(object)) self.assertIsInstance(injection.get_value(), object) - def test_value_with_catalog_bundle_injectable(self): - """Test Injection value property with catalog bundle.""" - class TestCatalog(catalogs.DeclarativeCatalog): - """Test catalog.""" - - provider = providers.Provider() - injection = injections.Injection( - TestCatalog.Bundle(TestCatalog.provider)) - - self.assertIsInstance(injection.get_value(), TestCatalog.Bundle) - def test_repr(self): """Test Injection representation.""" provider = providers.Factory(object) diff --git a/tests/test_utils.py b/tests/test_utils.py index 2e6fe234..353f5b12 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -252,50 +252,3 @@ class IsDeclarativeCatalogTests(unittest.TestCase): """Test with dynamic catalog.""" self.assertFalse(utils.is_declarative_catalog( catalogs.DynamicCatalog())) - - -class IsCatalogBundleTests(unittest.TestCase): - """`is_catalog_bundle()` test cases.""" - - def test_with_instance(self): - """Test with instance.""" - self.assertTrue(utils.is_catalog_bundle(catalogs.CatalogBundle())) - - def test_with_cls(self): - """Test with class.""" - self.assertFalse(utils.is_catalog_bundle(catalogs.CatalogBundle)) - - def test_with_string(self): - """Test with string.""" - self.assertFalse(utils.is_catalog_bundle('some_string')) - - def test_with_object(self): - """Test with object.""" - self.assertFalse(utils.is_catalog_bundle(object())) - - -class EnsureIsCatalogBundleTests(unittest.TestCase): - """`ensure_is_catalog_bundle` test cases.""" - - def test_with_instance(self): - """Test with instance.""" - bundle = catalogs.CatalogBundle() - self.assertIs(utils.ensure_is_catalog_bundle(bundle), bundle) - - def test_with_class(self): - """Test with class.""" - self.assertRaises(errors.Error, - utils.ensure_is_catalog_bundle, - catalogs.CatalogBundle) - - def test_with_string(self): - """Test with string.""" - self.assertRaises(errors.Error, - utils.ensure_is_catalog_bundle, - 'some_string') - - def test_with_object(self): - """Test with object.""" - self.assertRaises(errors.Error, - utils.ensure_is_catalog_bundle, - object())