Merge remote-tracking branch 'origin/catalog_subsets'

This commit is contained in:
Roman Mogilatov 2015-10-12 16:43:51 +03:00
commit d7462abeff
18 changed files with 425 additions and 199 deletions

View File

@ -1,6 +1,7 @@
"""Dependency injector.""" """Dependency injector."""
from .catalog import AbstractCatalog from .catalog import AbstractCatalog
from .catalog import CatalogSubset
from .catalog import override from .catalog import override
from .providers import Provider from .providers import Provider
@ -30,6 +31,7 @@ from .utils import is_kwarg_injection
from .utils import is_attribute_injection from .utils import is_attribute_injection
from .utils import is_method_injection from .utils import is_method_injection
from .utils import is_catalog from .utils import is_catalog
from .utils import is_catalog_subset
from .errors import Error from .errors import Error
@ -37,6 +39,7 @@ from .errors import Error
__all__ = ( __all__ = (
# Catalogs # Catalogs
'AbstractCatalog', 'AbstractCatalog',
'CatalogSubset',
'override', 'override',
# Providers # Providers
@ -69,6 +72,7 @@ __all__ = (
'is_attribute_injection', 'is_attribute_injection',
'is_method_injection', 'is_method_injection',
'is_catalog', 'is_catalog',
'is_catalog_subset',
# Errors # Errors
'Error', 'Error',

View File

@ -31,6 +31,10 @@ class CatalogMetaClass(type):
attributes['providers'] = providers attributes['providers'] = providers
return type.__new__(mcs, class_name, bases, attributes) return type.__new__(mcs, class_name, bases, attributes)
def __repr__(cls):
"""Return string representation of the catalog class."""
return '<Catalog "' + '.'.join((cls.__module__, cls.__name__)) + '">'
@six.add_metaclass(CatalogMetaClass) @six.add_metaclass(CatalogMetaClass)
class AbstractCatalog(object): class AbstractCatalog(object):
@ -53,22 +57,20 @@ class AbstractCatalog(object):
inherited_providers = dict() inherited_providers = dict()
__IS_CATALOG__ = True __IS_CATALOG__ = True
__slots__ = ('used_providers',)
def __init__(self, *used_providers): def __new__(cls, *providers):
"""Initializer.""" """Catalog constructor.
self.used_providers = set(used_providers)
def __getattribute__(self, item): Catalogs are declaratives entities that could not be instantiated.
"""Return providers.""" Catalog constructor is designed to produce subsets of catalog
attribute = super(AbstractCatalog, self).__getattribute__(item) providers.
if item in ('providers', 'used_providers', '__class__'): """
return attribute return CatalogSubset(catalog=cls, providers=providers)
if attribute not in self.used_providers: @classmethod
raise Error('Provider \'{0}\' '.format(item) + def is_subset_owner(cls, subset):
'is not listed in dependencies') """Check if catalog is subset owner."""
return attribute return subset.catalog is cls
@classmethod @classmethod
def filter(cls, provider_type): def filter(cls, provider_type):
@ -86,6 +88,68 @@ class AbstractCatalog(object):
for name, provider in six.iteritems(overriding.cls_providers): for name, provider in six.iteritems(overriding.cls_providers):
cls.providers[name].override(provider) cls.providers[name].override(provider)
@classmethod
def get(cls, name):
"""Return provider with specified name or raises error."""
try:
return cls.providers[name]
except KeyError:
raise Error('{0} has no provider with such name - {1}'.format(
cls, name))
@classmethod
def has(cls, name):
"""Check if there is provider with certain name."""
return name in cls.providers
class CatalogSubset(object):
"""Subset of catalog providers."""
__IS_SUBSET__ = True
__slots__ = ('catalog', 'available_providers', 'providers', '__dict__')
def __init__(self, catalog, providers):
"""Initializer."""
self.catalog = catalog
self.available_providers = set(providers)
self.providers = dict()
for provider_name in self.available_providers:
try:
provider = self.catalog.providers[provider_name]
except KeyError:
raise Error('Subset could not add "{0}" provider in scope, '
'because {1} has no provider with '
'such name'.format(provider_name, self.catalog))
else:
self.providers[provider_name] = provider
self.__dict__.update(self.providers)
super(CatalogSubset, self).__init__()
def get(self, name):
"""Return provider with specified name or raises error."""
try:
return self.providers[name]
except KeyError:
self._raise_undefined_provider_error(name)
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."""
self._raise_undefined_provider_error(item)
def __repr__(self):
"""Return string representation of subset."""
return '<Subset ({0}), {1}>'.format(
', '.join(self.available_providers), self.catalog)
def _raise_undefined_provider_error(self, name):
"""Raise error for cases when there is no such provider in subset."""
raise Error('Provider "{0}" is not a part of {1}'.format(name, self))
def override(catalog): def override(catalog):
"""Catalog overriding decorator.""" """Catalog overriding decorator."""

View File

@ -62,6 +62,12 @@ def is_catalog(instance):
getattr(instance, '__IS_CATALOG__', False) is True) getattr(instance, '__IS_CATALOG__', False) is True)
def is_catalog_subset(instance):
"""Check if instance is catalog subset instance."""
return (not isinstance(instance, six.class_types) and
getattr(instance, '__IS_SUBSET__', False) is True)
def get_injectable_kwargs(kwargs, injections): def get_injectable_kwargs(kwargs, injections):
"""Return dictionary of kwargs, patched with injections.""" """Return dictionary of kwargs, patched with injections."""
init_kwargs = dict(((injection.name, injection.value) init_kwargs = dict(((injection.name, injection.value)

View File

@ -16,76 +16,10 @@ Also, for both of these and some other cases, it might be useful to attach
some init / shutdown functionality or something else, that deals with group some init / shutdown functionality or something else, that deals with group
of providers. of providers.
Writing catalogs .. toctree::
---------------- :maxdepth: 2
Catalogs have to extend base catalog class ``di.AbstractCatalog``. writing
operating
Providers have to be defined like catalog's attributes. Every provider in subsets
catalog has name. This name should follow ``some_provider`` convention, overriding
that is standard naming convention for attribute names in Python.
.. note::
It might be useful to add such ``""":type: (di.Provider) -> Object1"""``
documentation blocks one line after provider definition for every provider.
It will help code analyzing tools and IDE's to understand that variable
above contains some callable object, that returns particular instance
in a result of call.
Example:
.. image:: /images/catalogs/simple.png
:width: 100%
:align: center
.. literalinclude:: ../../examples/catalogs/simple.py
:language: python
Operating with catalog providers
--------------------------------
``di.AbstractCatalog`` has several features that could be useful for some kind
of operations on catalog's providers:
- ``di.AbstractCatalog.providers`` is read-only attribute that contains
``dict`` of all catalog providers, including providers that are inherited
from parent catalogs, where key is the name of provider and value is
provider itself.
- ``di.AbstractCatalog.cls_providers`` is read-only attribute contains ``dict``
of current catalog providers, where key is the name of provider and value is
provider itself.
- ``di.AbstractCatalog.inherited_providers`` is read-only attribute contains
``dict`` of all providers that are inherited from parent catalogs, where key
is the name of provider and value is provider itself.
- ``di.AbstractCatalog.filter(provider_type=di.Provider)`` is a class method
that could be used for filtering catalog providers by provider types
(for example, for getting all ``di.Factory`` providers).
``di.AbstractCatalog.filter()`` method use ``di.AbstractCatalog.providers``.
Example:
.. literalinclude:: ../../examples/catalogs/operating_with_providers.py
:language: python
Overriding of catalogs
----------------------
Catalogs can be overridden by other catalogs. This, actually, means that
all of the providers from overriding catalog will override providers with the
same names in overridden catalog.
There are two ways to override catalog by another catalog:
- Use ``di.AbstractCatalog.override(AnotherCatalog)`` method.
- Use ``@di.override(AnotherCatalog)`` class decorator.
Example of overriding catalog using ``di.AbstractCatalog.override()`` method:
.. literalinclude:: ../../examples/catalogs/override.py
:language: python
Example of overriding catalog using ``@di.override()`` decorator:
.. literalinclude:: ../../examples/catalogs/override_decorator.py
:language: python

View File

@ -0,0 +1,29 @@
Operating with catalogs
-----------------------
``di.AbstractCatalog`` has several features that could be useful for some kind
of operations on catalog's providers:
- ``di.AbstractCatalog.providers`` is read-only attribute that contains
``dict`` of all catalog providers, including providers that are inherited
from parent catalogs, where key is the name of provider and value is
provider itself.
- ``di.AbstractCatalog.cls_providers`` is read-only attribute contains ``dict``
of current catalog providers, where key is the name of provider and value is
provider itself.
- ``di.AbstractCatalog.inherited_providers`` is read-only attribute contains
``dict`` of all providers that are inherited from parent catalogs, where key
is the name of provider and value is provider itself.
- ``di.AbstractCatalog.filter(provider_type=di.Provider)`` is a class method
that could be used for filtering catalog providers by provider types
(for example, for getting all ``di.Factory`` providers).
``di.AbstractCatalog.filter()`` method use ``di.AbstractCatalog.providers``.
Example:
.. image:: /images/catalogs/operating_with_providers.png
:width: 100%
:align: center
.. literalinclude:: ../../examples/catalogs/operating_with_providers.py
:language: python

View File

@ -0,0 +1,22 @@
Overriding of catalogs
----------------------
Catalogs can be overridden by other catalogs. This, actually, means that
all of the providers from overriding catalog will override providers with the
same names in overridden catalog.
There are two ways to override catalog by another catalog:
- Use ``di.AbstractCatalog.override(AnotherCatalog)`` method.
- Use ``@di.override(AnotherCatalog)`` class decorator.
Example of overriding catalog using ``di.AbstractCatalog.override()`` method:
.. literalinclude:: ../../examples/catalogs/override.py
:language: python
Example of overriding catalog using ``@di.override()`` decorator:
.. literalinclude:: ../../examples/catalogs/override_decorator.py
:language: python

19
docs/catalogs/subsets.rst Normal file
View File

@ -0,0 +1,19 @@
Creating catalog subsets
------------------------
``di.AbstractCatalog`` subset is a limited collection of catalog providers.
While catalog could be used as a centralized place for particular providers
group, such subsets of catalog providers can be used for creating several
limited scopes that could be passed to different subsystems.
``di.AbstractCatalog`` subsets could be created by instantiating of particular
catalog with passing provider names to the constructor.
Example:
.. image:: /images/catalogs/subsets.png
:width: 100%
:align: center
.. literalinclude:: ../../examples/catalogs/subsets.py
:language: python

25
docs/catalogs/writing.rst Normal file
View File

@ -0,0 +1,25 @@
Writing catalogs
----------------
Catalogs have to extend base catalog class ``di.AbstractCatalog``.
Providers have to be defined like catalog's attributes. Every provider in
catalog has name. This name should follow ``some_provider`` convention,
that is standard naming convention for attribute names in Python.
.. note::
It might be useful to add such ``""":type: (di.Provider) -> Object1"""``
docstrings just on the next line after provider's definition. It will
help code analyzing tools and IDE's to understand that variable above
contains some callable object, that returns particular instance as a
result of its call.
Here is an simple example of catalog with several factories:
.. image:: /images/catalogs/writing_catalogs.png
:width: 85%
:align: center
.. literalinclude:: ../../examples/catalogs/writing_catalogs.py
:language: python

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -12,7 +12,10 @@ Development version
------------------- -------------------
- Add functionality for decorating classes with ``@di.inject``. - Add functionality for decorating classes with ``@di.inject``.
- Add functionality for creating ``di.AbstractCatalog`` subsets.
- Add enhancement for ``di.AbstractCatalog`` inheritance. - Add enhancement for ``di.AbstractCatalog`` inheritance.
- Add images for catalog "Writing catalogs" and "Operating with catalogs"
examples.
- Add minor refactorings and code style fixes. - Add minor refactorings and code style fixes.
0.9.5 0.9.5

View File

@ -1,37 +0,0 @@
"""Catalog example."""
import collections
import dependency_injector as di
# Creating some example classes:
Object1 = collections.namedtuple('Object1', ['arg1', 'arg2'])
Object2 = collections.namedtuple('Object2', ['object1'])
class Catalog(di.AbstractCatalog):
"""Providers catalog."""
object1_factory = di.Factory(Object1,
arg1=1,
arg2=2)
""":type: (di.Provider) -> Object1"""
object2_factory = di.Factory(Object2,
object1=object1_factory)
""":type: (di.Provider) -> Object2"""
# Creating some objects:
object2_1 = Catalog.object2_factory()
object2_2 = Catalog.object2_factory()
# Making some asserts:
assert object2_1 is not object2_2
assert isinstance(object2_1, Object2)
assert object2_1.object1.arg1 == 1
assert object2_1.object1.arg2 == 2
assert isinstance(object2_2, Object2)
assert object2_2.object1.arg1 == 1
assert object2_2.object1.arg2 == 2

View File

@ -0,0 +1,59 @@
"""Catalog subsets example."""
import dependency_injector as di
# Declaring example services catalog:
class Services(di.AbstractCatalog):
"""Example catalog of service providers."""
users = di.Provider()
auth = di.Provider()
photos = di.Provider()
# Declaring example base class for some web views:
class BaseWebView(object):
"""Example base class of web view."""
def __init__(self, services):
"""Initializer.
:type services: Services
:param services: Subset of service providers
"""
self.services = services
# Declaring several example web views:
class AuthView(BaseWebView):
"""Example auth web view."""
class PhotosView(BaseWebView):
"""Example photo processing web view."""
# Creating example views with appropriate service provider subsets:
auth_view = AuthView(Services('users', 'auth'))
photos_view = PhotosView(Services('users', 'photos'))
# 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 di.Error:
# `photos` service provider is not in scope of `auth_view` services subset,
# 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 di.Error as exception:
# `auth` service provider is not in scope of `photo_processing_view`
# services subset, so `di.Error` will be raised.
pass

View File

@ -0,0 +1,22 @@
"""Catalog example."""
import dependency_injector as di
class Catalog(di.AbstractCatalog):
"""Providers catalog."""
factory1 = di.Factory(object)
""":type: (di.Provider) -> object"""
factory2 = di.Factory(object)
""":type: (di.Provider) -> object"""
# Creating some objects:
object1 = Catalog.factory1()
object2 = Catalog.factory2()
# Making some asserts:
assert object1 is not object2
assert isinstance(object1, object)
assert isinstance(object2, object)

View File

@ -4,93 +4,159 @@ import unittest2 as unittest
import dependency_injector as di import dependency_injector as di
class CatalogsInheritanceTests(unittest.TestCase): class CatalogA(di.AbstractCatalog):
"""Catalogs inheritance tests."""
class CatalogA(di.AbstractCatalog):
"""Test catalog A.""" """Test catalog A."""
p11 = di.Provider() p11 = di.Provider()
p12 = di.Provider() p12 = di.Provider()
class CatalogB(CatalogA):
class CatalogB(CatalogA):
"""Test catalog B.""" """Test catalog B."""
p21 = di.Provider() p21 = di.Provider()
p22 = di.Provider() p22 = di.Provider()
class CatalogC(CatalogB):
class CatalogC(CatalogB):
"""Test catalog C.""" """Test catalog C."""
p31 = di.Provider() p31 = di.Provider()
p32 = di.Provider() p32 = di.Provider()
class CatalogsInheritanceTests(unittest.TestCase):
"""Catalogs inheritance tests."""
def test_cls_providers(self): def test_cls_providers(self):
"""Test `di.AbstractCatalog.cls_providers` contents.""" """Test `di.AbstractCatalog.cls_providers` contents."""
self.assertDictEqual(self.CatalogA.cls_providers, self.assertDictEqual(CatalogA.cls_providers,
dict(p11=self.CatalogA.p11, dict(p11=CatalogA.p11,
p12=self.CatalogA.p12)) p12=CatalogA.p12))
self.assertDictEqual(self.CatalogB.cls_providers, self.assertDictEqual(CatalogB.cls_providers,
dict(p21=self.CatalogB.p21, dict(p21=CatalogB.p21,
p22=self.CatalogB.p22)) p22=CatalogB.p22))
self.assertDictEqual(self.CatalogC.cls_providers, self.assertDictEqual(CatalogC.cls_providers,
dict(p31=self.CatalogC.p31, dict(p31=CatalogC.p31,
p32=self.CatalogC.p32)) p32=CatalogC.p32))
def test_inherited_providers(self): def test_inherited_providers(self):
"""Test `di.AbstractCatalog.inherited_providers` contents.""" """Test `di.AbstractCatalog.inherited_providers` contents."""
self.assertDictEqual(self.CatalogA.inherited_providers, dict()) self.assertDictEqual(CatalogA.inherited_providers, dict())
self.assertDictEqual(self.CatalogB.inherited_providers, self.assertDictEqual(CatalogB.inherited_providers,
dict(p11=self.CatalogA.p11, dict(p11=CatalogA.p11,
p12=self.CatalogA.p12)) p12=CatalogA.p12))
self.assertDictEqual(self.CatalogC.inherited_providers, self.assertDictEqual(CatalogC.inherited_providers,
dict(p11=self.CatalogA.p11, dict(p11=CatalogA.p11,
p12=self.CatalogA.p12, p12=CatalogA.p12,
p21=self.CatalogB.p21, p21=CatalogB.p21,
p22=self.CatalogB.p22)) p22=CatalogB.p22))
def test_providers(self): def test_providers(self):
"""Test `di.AbstractCatalog.inherited_providers` contents.""" """Test `di.AbstractCatalog.inherited_providers` contents."""
self.assertDictEqual(self.CatalogA.providers, self.assertDictEqual(CatalogA.providers,
dict(p11=self.CatalogA.p11, dict(p11=CatalogA.p11,
p12=self.CatalogA.p12)) p12=CatalogA.p12))
self.assertDictEqual(self.CatalogB.providers, self.assertDictEqual(CatalogB.providers,
dict(p11=self.CatalogA.p11, dict(p11=CatalogA.p11,
p12=self.CatalogA.p12, p12=CatalogA.p12,
p21=self.CatalogB.p21, p21=CatalogB.p21,
p22=self.CatalogB.p22)) p22=CatalogB.p22))
self.assertDictEqual(self.CatalogC.providers, self.assertDictEqual(CatalogC.providers,
dict(p11=self.CatalogA.p11, dict(p11=CatalogA.p11,
p12=self.CatalogA.p12, p12=CatalogA.p12,
p21=self.CatalogB.p21, p21=CatalogB.p21,
p22=self.CatalogB.p22, p22=CatalogB.p22,
p31=self.CatalogC.p31, p31=CatalogC.p31,
p32=self.CatalogC.p32)) p32=CatalogC.p32))
class CatalogSubsetTests(unittest.TestCase):
"""Catalog subset test cases."""
catalog = None
def setUp(self):
"""Set test environment up."""
self.subset = CatalogC('p11', 'p12')
def test_get_attr_from_subset(self):
"""Test get providers (attribute) from subset."""
self.assertIs(self.subset.p11, CatalogC.p11)
self.assertIs(self.subset.p12, CatalogC.p12)
def test_get_attr_not_from_subset(self):
"""Test get providers (attribute) that are not in subset."""
self.assertRaises(di.Error, getattr, self.subset, 'p21')
self.assertRaises(di.Error, getattr, self.subset, 'p22')
self.assertRaises(di.Error, getattr, self.subset, 'p31')
self.assertRaises(di.Error, getattr, self.subset, 'p32')
def test_get_method_from_subset(self):
"""Test get providers (get() method) from subset."""
self.assertIs(self.subset.get('p11'), CatalogC.p11)
self.assertIs(self.subset.get('p12'), CatalogC.p12)
def test_get_method_not_from_subset(self):
"""Test get providers (get() method) that are not in subset."""
self.assertRaises(di.Error, self.subset.get, 'p21')
self.assertRaises(di.Error, self.subset.get, 'p22')
self.assertRaises(di.Error, self.subset.get, 'p31')
self.assertRaises(di.Error, self.subset.get, 'p32')
def test_has(self):
"""Test checks of providers availability in subsets."""
self.assertTrue(self.subset.has('p11'))
self.assertTrue(self.subset.has('p12'))
self.assertFalse(self.subset.has('p21'))
self.assertFalse(self.subset.has('p22'))
self.assertFalse(self.subset.has('p31'))
self.assertFalse(self.subset.has('p32'))
def test_creating_with_undefined_provider(self):
"""Test subset creation with provider that is not in catalog."""
self.assertRaises(di.Error, CatalogC, 'undefined_provider')
class CatalogTests(unittest.TestCase): class CatalogTests(unittest.TestCase):
"""Catalog test cases.""" """Catalog test cases."""
class Catalog(di.AbstractCatalog): def test_get(self):
"""Test catalog.""" """Test getting of providers using get() method."""
self.assertIs(CatalogC.get('p11'), CatalogC.p11)
self.assertIs(CatalogC.get('p12'), CatalogC.p12)
self.assertIs(CatalogC.get('p22'), CatalogC.p22)
self.assertIs(CatalogC.get('p22'), CatalogC.p22)
self.assertIs(CatalogC.get('p32'), CatalogC.p32)
self.assertIs(CatalogC.get('p32'), CatalogC.p32)
obj = di.Object(object()) def test_get_undefined(self):
another_obj = di.Object(object()) """Test getting of undefined providers using get() method."""
self.assertRaises(di.Error, CatalogC.get, 'undefined')
def test_get_used(self): def test_has(self):
"""Test retrieving used provider.""" """Test checks of providers availability in subsets."""
catalog = self.Catalog(self.Catalog.obj) self.assertTrue(CatalogC.has('p11'))
self.assertIsInstance(catalog.obj(), object) self.assertTrue(CatalogC.has('p12'))
self.assertTrue(CatalogC.has('p21'))
self.assertTrue(CatalogC.has('p22'))
self.assertTrue(CatalogC.has('p31'))
self.assertTrue(CatalogC.has('p32'))
self.assertFalse(CatalogC.has('undefined'))
def test_get_unused(self): def test_is_subset_owner(self):
"""Test retrieving unused provider.""" """Test that catalog is subset owner."""
catalog = self.Catalog() subset = CatalogA()
self.assertRaises(di.Error, getattr, catalog, 'obj')
def test_all_providers_by_type(self): self.assertTrue(CatalogA.is_subset_owner(subset))
self.assertFalse(CatalogB.is_subset_owner(subset))
self.assertFalse(CatalogC.is_subset_owner(subset))
def test_filter_all_providers_by_type(self):
"""Test getting of all catalog providers of specific type.""" """Test getting of all catalog providers of specific type."""
self.assertTrue(len(self.Catalog.filter(di.Object)) == 2) self.assertTrue(len(CatalogC.filter(di.Provider)) == 6)
self.assertTrue(len(self.Catalog.filter(di.Value)) == 0) self.assertTrue(len(CatalogC.filter(di.Value)) == 0)
class OverrideTests(unittest.TestCase): class OverrideTests(unittest.TestCase):

View File

@ -5,7 +5,6 @@ import dependency_injector as di
class IsProviderTests(unittest.TestCase): class IsProviderTests(unittest.TestCase):
"""`is_provider()` test cases.""" """`is_provider()` test cases."""
def test_with_instance(self): def test_with_instance(self):
@ -27,7 +26,6 @@ class IsProviderTests(unittest.TestCase):
def test_with_subclass_instance(self): def test_with_subclass_instance(self):
"""Test with subclass of provider instance.""" """Test with subclass of provider instance."""
class SomeProvider(di.Provider): class SomeProvider(di.Provider):
"""Some provider for test.""" """Some provider for test."""
self.assertTrue(di.is_provider(SomeProvider())) self.assertTrue(di.is_provider(SomeProvider()))
@ -35,7 +33,6 @@ class IsProviderTests(unittest.TestCase):
def test_with_class_with_getattr(self): def test_with_class_with_getattr(self):
"""Test with class that has __getattr__() method implementation.""" """Test with class that has __getattr__() method implementation."""
class SomeClass(object): class SomeClass(object):
"""Some test class with __getattr__() method implementation.""" """Some test class with __getattr__() method implementation."""
def __getattr__(self, _): def __getattr__(self, _):
@ -46,7 +43,6 @@ class IsProviderTests(unittest.TestCase):
class EnsureIsProviderTests(unittest.TestCase): class EnsureIsProviderTests(unittest.TestCase):
"""`ensure_is_provider` test cases.""" """`ensure_is_provider` test cases."""
def test_with_instance(self): def test_with_instance(self):
@ -68,7 +64,6 @@ class EnsureIsProviderTests(unittest.TestCase):
class IsInjectionTests(unittest.TestCase): class IsInjectionTests(unittest.TestCase):
"""`is_injection()` test cases.""" """`is_injection()` test cases."""
def test_with_instance(self): def test_with_instance(self):
@ -95,7 +90,6 @@ class IsInjectionTests(unittest.TestCase):
class EnsureIsInjectionTests(unittest.TestCase): class EnsureIsInjectionTests(unittest.TestCase):
"""`ensure_is_injection` test cases.""" """`ensure_is_injection` test cases."""
def test_with_instance(self): def test_with_instance(self):
@ -117,7 +111,6 @@ class EnsureIsInjectionTests(unittest.TestCase):
class IsKwArgInjectionTests(unittest.TestCase): class IsKwArgInjectionTests(unittest.TestCase):
"""`is_kwarg_injection()` test cases.""" """`is_kwarg_injection()` test cases."""
def test_with_instance(self): def test_with_instance(self):
@ -142,7 +135,6 @@ class IsKwArgInjectionTests(unittest.TestCase):
class IsAttributeInjectionTests(unittest.TestCase): class IsAttributeInjectionTests(unittest.TestCase):
"""`is_attribute_injection()` test cases.""" """`is_attribute_injection()` test cases."""
def test_with_instance(self): def test_with_instance(self):
@ -168,7 +160,6 @@ class IsAttributeInjectionTests(unittest.TestCase):
class IsMethodInjectionTests(unittest.TestCase): class IsMethodInjectionTests(unittest.TestCase):
"""`is_method_injection()` test cases.""" """`is_method_injection()` test cases."""
def test_with_instance(self): def test_with_instance(self):
@ -193,7 +184,6 @@ class IsMethodInjectionTests(unittest.TestCase):
class IsCatalogTests(unittest.TestCase): class IsCatalogTests(unittest.TestCase):
"""`is_catalog()` test cases.""" """`is_catalog()` test cases."""
def test_with_cls(self): def test_with_cls(self):
@ -207,7 +197,6 @@ class IsCatalogTests(unittest.TestCase):
def test_with_child_class(self): def test_with_child_class(self):
"""Test with parent class.""" """Test with parent class."""
class Catalog(di.AbstractCatalog): class Catalog(di.AbstractCatalog):
"""Example catalog child class.""" """Example catalog child class."""
self.assertTrue(di.is_catalog(Catalog)) self.assertTrue(di.is_catalog(Catalog))
@ -219,3 +208,24 @@ class IsCatalogTests(unittest.TestCase):
def test_with_object(self): def test_with_object(self):
"""Test with object.""" """Test with object."""
self.assertFalse(di.is_catalog(object())) self.assertFalse(di.is_catalog(object()))
class IsCatalogSubsetTests(unittest.TestCase):
"""`is_catalog_subset()` test cases."""
def test_with_cls(self):
"""Test with class."""
self.assertFalse(di.is_catalog_subset(di.CatalogSubset))
def test_with_instance(self):
"""Test with class."""
self.assertTrue(di.is_catalog_subset(
di.CatalogSubset(catalog=di.AbstractCatalog, providers=tuple())))
def test_with_string(self):
"""Test with string."""
self.assertFalse(di.is_catalog_subset('some_string'))
def test_with_object(self):
"""Test with object."""
self.assertFalse(di.is_catalog_subset(object()))