mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 07:57:43 +03:00 
			
		
		
		
	Add dynamic containers
+ Drop catalogs
This commit is contained in:
		
							parent
							
								
									be94a1badc
								
							
						
					
					
						commit
						3416728309
					
				|  | @ -1,20 +0,0 @@ | ||||||
| """Dependency injector catalogs package.""" |  | ||||||
| 
 |  | ||||||
| from dependency_injector.catalogs.dynamic import DynamicCatalog |  | ||||||
| from dependency_injector.catalogs.declarative import ( |  | ||||||
|     DeclarativeCatalogMetaClass, |  | ||||||
|     DeclarativeCatalog, |  | ||||||
| ) |  | ||||||
| from dependency_injector.catalogs.utils import ( |  | ||||||
|     copy, |  | ||||||
|     override |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| __all__ = ( |  | ||||||
|     'DynamicCatalog', |  | ||||||
|     'DeclarativeCatalogMetaClass', |  | ||||||
|     'DeclarativeCatalog', |  | ||||||
|     'copy', |  | ||||||
|     'override', |  | ||||||
| ) |  | ||||||
|  | @ -1,440 +0,0 @@ | ||||||
| """Dependency injector declarative catalog module.""" |  | ||||||
| 
 |  | ||||||
| import six |  | ||||||
| 
 |  | ||||||
| from dependency_injector.catalogs.dynamic import DynamicCatalog |  | ||||||
| from dependency_injector.utils import ( |  | ||||||
|     is_provider, |  | ||||||
|     is_catalog, |  | ||||||
|     is_declarative_catalog, |  | ||||||
| ) |  | ||||||
| from dependency_injector.errors import ( |  | ||||||
|     Error, |  | ||||||
|     UndefinedProviderError, |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @six.python_2_unicode_compatible |  | ||||||
| class DeclarativeCatalogMetaClass(type): |  | ||||||
|     """Declarative catalog meta class.""" |  | ||||||
| 
 |  | ||||||
|     def __new__(mcs, class_name, bases, attributes): |  | ||||||
|         """Declarative catalog class factory.""" |  | ||||||
|         cls_providers = tuple((name, provider) |  | ||||||
|                               for name, provider in six.iteritems(attributes) |  | ||||||
|                               if is_provider(provider)) |  | ||||||
| 
 |  | ||||||
|         inherited_providers = tuple((name, provider) |  | ||||||
|                                     for base in bases if is_catalog(base) |  | ||||||
|                                     for name, provider in six.iteritems( |  | ||||||
|                                         base.providers)) |  | ||||||
| 
 |  | ||||||
|         providers = cls_providers + inherited_providers |  | ||||||
| 
 |  | ||||||
|         cls = type.__new__(mcs, class_name, bases, attributes) |  | ||||||
| 
 |  | ||||||
|         if cls.provider_type: |  | ||||||
|             cls._catalog = type('DynamicCatalog', |  | ||||||
|                                 (DynamicCatalog,), |  | ||||||
|                                 dict(provider_type=cls.provider_type))() |  | ||||||
|         else: |  | ||||||
|             cls._catalog = DynamicCatalog() |  | ||||||
| 
 |  | ||||||
|         cls._catalog.bind_providers(dict(providers)) |  | ||||||
| 
 |  | ||||||
|         cls._cls_providers = dict(cls_providers) |  | ||||||
|         cls._inherited_providers = dict(inherited_providers) |  | ||||||
| 
 |  | ||||||
|         return cls |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def providers(cls): |  | ||||||
|         """Read-only dictionary of all providers. |  | ||||||
| 
 |  | ||||||
|         :type: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.providers |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def cls_providers(cls): |  | ||||||
|         """Read-only dictionary of current catalog providers. |  | ||||||
| 
 |  | ||||||
|         :rtype: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return cls._cls_providers |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def inherited_providers(cls): |  | ||||||
|         """Read-only dictionary of inherited providers. |  | ||||||
| 
 |  | ||||||
|         :rtype: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return cls._inherited_providers |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def overridden_by(cls): |  | ||||||
|         """Tuple of overriding catalogs. |  | ||||||
| 
 |  | ||||||
|         :type: tuple[ |  | ||||||
|             :py:class:`DeclarativeCatalog` | |  | ||||||
|             :py:class:`DynamicCatalog`] |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.overridden_by |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def is_overridden(cls): |  | ||||||
|         """Read-only property that is set to ``True`` if catalog is overridden. |  | ||||||
| 
 |  | ||||||
|         :rtype: bool |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.is_overridden |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def last_overriding(cls): |  | ||||||
|         """Read-only reference to the last overriding catalog, if any. |  | ||||||
| 
 |  | ||||||
|         :type: :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog` | |  | ||||||
|                None |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.last_overriding |  | ||||||
| 
 |  | ||||||
|     def __getattr__(cls, name): |  | ||||||
|         """Return provider with specified name or raise en error. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.UndefinedProviderError` |  | ||||||
|         """ |  | ||||||
|         raise UndefinedProviderError('There is no provider "{0}" in ' |  | ||||||
|                                      'catalog {1}'.format(name, cls)) |  | ||||||
| 
 |  | ||||||
|     def __setattr__(cls, name, value): |  | ||||||
|         """Handle setting of catalog attributes. |  | ||||||
| 
 |  | ||||||
|         Setting of attributes works as usual, but if value of attribute is |  | ||||||
|         provider, this provider will be bound to catalog. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :param value: Attribute's value. |  | ||||||
|         :type value: :py:class:`dependency_injector.providers.Provider` | |  | ||||||
|                      object |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         if is_provider(value): |  | ||||||
|             cls.bind_provider(name, value, _set_as_attribute=False) |  | ||||||
|         return super(DeclarativeCatalogMetaClass, cls).__setattr__(name, value) |  | ||||||
| 
 |  | ||||||
|     def __delattr__(cls, name): |  | ||||||
|         """Handle deleting of catalog attibute. |  | ||||||
| 
 |  | ||||||
|         Deleting of attributes works as usual, but if value of attribute is |  | ||||||
|         provider, this provider will be unbound from catalog. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         if is_provider(getattr(cls, name)): |  | ||||||
|             delattr(cls._catalog, name) |  | ||||||
|         return super(DeclarativeCatalogMetaClass, cls).__delattr__(name) |  | ||||||
| 
 |  | ||||||
|     def __repr__(cls): |  | ||||||
|         """Return string representation of the catalog. |  | ||||||
| 
 |  | ||||||
|         :rtype: str |  | ||||||
|         """ |  | ||||||
|         return '<{0}({1})>'.format('.'.join((cls.__module__, cls.__name__)), |  | ||||||
|                                    ', '.join(six.iterkeys(cls.providers))) |  | ||||||
| 
 |  | ||||||
|     __str__ = __repr__ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @six.add_metaclass(DeclarativeCatalogMetaClass) |  | ||||||
| class DeclarativeCatalog(object): |  | ||||||
|     """Declarative catalog of providers. |  | ||||||
| 
 |  | ||||||
|     :py:class:`DeclarativeCatalog` is a catalog of providers that could be |  | ||||||
|     defined in declarative manner. It should cover most of the cases when list |  | ||||||
|     of providers that would be included in catalog is deterministic (catalog |  | ||||||
|     will not change its structure in runtime). |  | ||||||
| 
 |  | ||||||
|     .. code-block:: python |  | ||||||
| 
 |  | ||||||
|         class Services(DeclarativeCatalog): |  | ||||||
| 
 |  | ||||||
|             auth = providers.Factory(AuthService) |  | ||||||
| 
 |  | ||||||
|             users = providers.Factory(UsersService) |  | ||||||
| 
 |  | ||||||
|         users_service = Services.users() |  | ||||||
| 
 |  | ||||||
|     .. py:attribute:: provider_type |  | ||||||
| 
 |  | ||||||
|         If provider type is defined, :py:class:`DeclarativeCatalog` checks that |  | ||||||
|         all of its providers are instances of |  | ||||||
|         :py:attr:`DeclarativeCatalog.provider_type`. |  | ||||||
| 
 |  | ||||||
|         :type: type | None |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     provider_type = None |  | ||||||
| 
 |  | ||||||
|     _catalog = DynamicCatalog |  | ||||||
| 
 |  | ||||||
|     _cls_providers = dict() |  | ||||||
|     _inherited_providers = dict() |  | ||||||
| 
 |  | ||||||
|     __IS_CATALOG__ = True |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def providers(self): |  | ||||||
|         """Read-only dictionary of all providers. |  | ||||||
| 
 |  | ||||||
|         :rtype: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return self.__class__.providers |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def cls_providers(self): |  | ||||||
|         """Read-only dictionary of current catalog providers. |  | ||||||
| 
 |  | ||||||
|         :rtype: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return self.__class__.cls_providers |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def inherited_providers(self): |  | ||||||
|         """Read-only dictionary of inherited providers. |  | ||||||
| 
 |  | ||||||
|         :rtype: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return self.__class__.inherited_providers |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def overridden_by(self): |  | ||||||
|         """Tuple of overriding catalogs. |  | ||||||
| 
 |  | ||||||
|         :rtype: tuple[:py:class:`DeclarativeCatalog` | |  | ||||||
|                       :py:class:`DynamicCatalog`] |  | ||||||
|         """ |  | ||||||
|         return self.__class__.overridden_by |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def is_overridden(self): |  | ||||||
|         """Read-only property that is set to ``True`` if catalog is overridden. |  | ||||||
| 
 |  | ||||||
|         :rtype: bool |  | ||||||
|         """ |  | ||||||
|         return self.__class__.is_overridden |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def last_overriding(self): |  | ||||||
|         """Read-only reference to the last overriding catalog, if any. |  | ||||||
| 
 |  | ||||||
|         :rtype: :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog` | |  | ||||||
|                None |  | ||||||
|         """ |  | ||||||
|         return self.__class__.last_overriding |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def get_provider_bind_name(cls, provider): |  | ||||||
|         """Return provider's name in catalog. |  | ||||||
| 
 |  | ||||||
|         :param provider: Provider instance. |  | ||||||
|         :type provider: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.UndefinedProviderError` |  | ||||||
| 
 |  | ||||||
|         :return: Provider's name. |  | ||||||
|         :rtype: str |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.get_provider_bind_name(provider) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def is_provider_bound(cls, provider): |  | ||||||
|         """Check if provider is bound to the catalog. |  | ||||||
| 
 |  | ||||||
|         :param provider: Provider instance. |  | ||||||
|         :type provider: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :rtype: bool |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.is_provider_bound(provider) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def filter(cls, provider_type): |  | ||||||
|         """Return dictionary of providers, that are instance of provided type. |  | ||||||
| 
 |  | ||||||
|         :param provider_type: Provider's type. |  | ||||||
|         :type provider_type: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :rtype: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.filter(provider_type) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def override(cls, overriding): |  | ||||||
|         """Override current catalog providers by overriding catalog providers. |  | ||||||
| 
 |  | ||||||
|         :param overriding: Overriding catalog. |  | ||||||
|         :type overriding: :py:class:`DeclarativeCatalog` | |  | ||||||
|                           :py:class:`DynamicCatalog` |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.Error` if trying to |  | ||||||
|                 override catalog by itself or its subclasses |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         if is_declarative_catalog(overriding) and issubclass(cls, overriding): |  | ||||||
|             raise Error('Catalog {0} could not be overridden ' |  | ||||||
|                         'with itself or its subclasses'.format(cls)) |  | ||||||
|         return cls._catalog.override(overriding) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def reset_last_overriding(cls): |  | ||||||
|         """Reset last overriding catalog. |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         cls._catalog.reset_last_overriding() |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def reset_override(cls): |  | ||||||
|         """Reset all overridings for all catalog providers. |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         cls._catalog.reset_override() |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def get_provider(cls, 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` |  | ||||||
|         """ |  | ||||||
|         return cls._catalog.get_provider(name) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def bind_provider(cls, name, provider, force=False, |  | ||||||
|                       _set_as_attribute=True): |  | ||||||
|         """Bind provider to catalog with specified name. |  | ||||||
| 
 |  | ||||||
|         :param name: Name of the provider. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :param provider: Provider instance. |  | ||||||
|         :type provider: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :param force: Force binding of provider. |  | ||||||
|         :type force: bool |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.Error` |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         if cls._catalog.is_provider_bound(provider): |  | ||||||
|             bindind_name = cls._catalog.get_provider_bind_name(provider) |  | ||||||
|             if bindind_name == name and not force: |  | ||||||
|                 return |  | ||||||
| 
 |  | ||||||
|         cls._catalog.bind_provider(name, provider, force) |  | ||||||
|         cls.cls_providers[name] = provider |  | ||||||
| 
 |  | ||||||
|         if _set_as_attribute: |  | ||||||
|             setattr(cls, name, provider) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def bind_providers(cls, providers, force=False): |  | ||||||
|         """Bind providers dictionary to catalog. |  | ||||||
| 
 |  | ||||||
|         :param providers: Dictionary of providers, where key is a name |  | ||||||
|             and value is a provider. |  | ||||||
|         :type providers: |  | ||||||
|             dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
| 
 |  | ||||||
|         :param force: Force binding of providers. |  | ||||||
|         :type force: bool |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.Error` |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         for name, provider in six.iteritems(providers): |  | ||||||
|             cls.bind_provider(name, provider, force=force) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def has_provider(cls, name): |  | ||||||
|         """Check if there is provider with certain name. |  | ||||||
| 
 |  | ||||||
|         :param name: Provider's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :rtype: bool |  | ||||||
|         """ |  | ||||||
|         return hasattr(cls, name) |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def unbind_provider(cls, name): |  | ||||||
|         """Remove provider binding. |  | ||||||
| 
 |  | ||||||
|         :param name: Provider's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         delattr(cls, name) |  | ||||||
|         del cls.cls_providers[name] |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def __getattr__(cls, name):  # pragma: no cover |  | ||||||
|         """Return provider with specified name or raise en error. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.UndefinedProviderError` |  | ||||||
|         """ |  | ||||||
|         raise NotImplementedError('Implementated in metaclass') |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def __setattr__(cls, name, value):  # pragma: no cover |  | ||||||
|         """Handle setting of catalog attributes. |  | ||||||
| 
 |  | ||||||
|         Setting of attributes works as usual, but if value of attribute is |  | ||||||
|         provider, this provider will be bound to catalog. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :param value: Attribute's value. |  | ||||||
|         :type value: :py:class:`dependency_injector.providers.Provider` | |  | ||||||
|                      object |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         raise NotImplementedError('Implementated in metaclass') |  | ||||||
| 
 |  | ||||||
|     @classmethod |  | ||||||
|     def __delattr__(cls, name):  # pragma: no cover |  | ||||||
|         """Handle deleting of catalog attibute. |  | ||||||
| 
 |  | ||||||
|         Deleting of attributes works as usual, but if value of attribute is |  | ||||||
|         provider, this provider will be unbound from catalog. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         raise NotImplementedError('Implementated in metaclass') |  | ||||||
|  | @ -1,309 +0,0 @@ | ||||||
| """Dependency injector dynamic catalog module.""" |  | ||||||
| 
 |  | ||||||
| import six |  | ||||||
| 
 |  | ||||||
| from dependency_injector.utils import ( |  | ||||||
|     is_provider, |  | ||||||
|     ensure_is_provider, |  | ||||||
| ) |  | ||||||
| from dependency_injector.errors import ( |  | ||||||
|     Error, |  | ||||||
|     UndefinedProviderError, |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @six.python_2_unicode_compatible |  | ||||||
| class DynamicCatalog(object): |  | ||||||
|     """Dynamic catalog of providers. |  | ||||||
| 
 |  | ||||||
|     :py:class:`DynamicCatalog` is a catalog of providers that could be created |  | ||||||
|     in application's runtime. It should cover most of the cases when list of |  | ||||||
|     providers that would be included in catalog is non-deterministic in terms |  | ||||||
|     of apllication code (catalog's structure could be determined just after |  | ||||||
|     application will be started and will do some initial work, like parsing |  | ||||||
|     list of catalog's providers from the configuration). |  | ||||||
| 
 |  | ||||||
|     .. code-block:: python |  | ||||||
| 
 |  | ||||||
|         services = DynamicCatalog(auth=providers.Factory(AuthService), |  | ||||||
|                                   users=providers.Factory(UsersService)) |  | ||||||
| 
 |  | ||||||
|         users_service = services.users() |  | ||||||
| 
 |  | ||||||
|     .. py:attribute:: providers |  | ||||||
| 
 |  | ||||||
|         Dictionary of all providers. |  | ||||||
| 
 |  | ||||||
|         :type: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
| 
 |  | ||||||
|     .. py:attribute:: overridden_by |  | ||||||
| 
 |  | ||||||
|         Tuple of overriding catalogs. |  | ||||||
| 
 |  | ||||||
|         :type: tuple[ |  | ||||||
|             :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog`] |  | ||||||
| 
 |  | ||||||
|     .. py:attribute:: provider_type |  | ||||||
| 
 |  | ||||||
|         If provider type is defined, :py:class:`DynamicCatalog` checks that |  | ||||||
|         all of its providers are instances of |  | ||||||
|         :py:attr:`DynamicCatalog.provider_type`. |  | ||||||
| 
 |  | ||||||
|         :type: type | None |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     provider_type = None |  | ||||||
| 
 |  | ||||||
|     __IS_CATALOG__ = True |  | ||||||
|     __slots__ = ('providers', 'provider_names', 'overridden_by') |  | ||||||
| 
 |  | ||||||
|     def __init__(self, **providers): |  | ||||||
|         """Initializer. |  | ||||||
| 
 |  | ||||||
|         :param providers: Dictionary of catalog providers. |  | ||||||
|         :type providers: |  | ||||||
|             dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         self.providers = dict() |  | ||||||
|         self.provider_names = dict() |  | ||||||
|         self.overridden_by = tuple() |  | ||||||
|         self.bind_providers(providers) |  | ||||||
|         super(DynamicCatalog, self).__init__() |  | ||||||
| 
 |  | ||||||
|     def get_provider_bind_name(self, provider): |  | ||||||
|         """Return provider's name in catalog. |  | ||||||
| 
 |  | ||||||
|         :param provider: Provider instance. |  | ||||||
|         :type provider: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.UndefinedProviderError` |  | ||||||
| 
 |  | ||||||
|         :return: Provider's name. |  | ||||||
|         :rtype: str |  | ||||||
|         """ |  | ||||||
|         if not self.is_provider_bound(provider): |  | ||||||
|             raise Error('Can not find bind name for {0} in catalog {1}'.format( |  | ||||||
|                 provider, self)) |  | ||||||
|         return self.provider_names[provider] |  | ||||||
| 
 |  | ||||||
|     def is_provider_bound(self, provider): |  | ||||||
|         """Check if provider is bound to the catalog. |  | ||||||
| 
 |  | ||||||
|         :param provider: Provider instance. |  | ||||||
|         :type provider: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :rtype: bool |  | ||||||
|         """ |  | ||||||
|         return provider in self.provider_names |  | ||||||
| 
 |  | ||||||
|     def filter(self, provider_type): |  | ||||||
|         """Return dictionary of providers, that are instance of provided type. |  | ||||||
| 
 |  | ||||||
|         :param provider_type: Provider's type. |  | ||||||
|         :type provider_type: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :rtype: dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
|         """ |  | ||||||
|         return dict((name, provider) |  | ||||||
|                     for name, provider in six.iteritems(self.providers) |  | ||||||
|                     if isinstance(provider, provider_type)) |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def is_overridden(self): |  | ||||||
|         """Read-only property that is set to ``True`` if catalog is overridden. |  | ||||||
| 
 |  | ||||||
|         :rtype: bool |  | ||||||
|         """ |  | ||||||
|         return bool(self.overridden_by) |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def last_overriding(self): |  | ||||||
|         """Read-only reference to the last overriding catalog, if any. |  | ||||||
| 
 |  | ||||||
|         :type: :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog` | |  | ||||||
|                None |  | ||||||
|         """ |  | ||||||
|         return self.overridden_by[-1] if self.overridden_by else None |  | ||||||
| 
 |  | ||||||
|     def override(self, overriding): |  | ||||||
|         """Override current catalog providers by overriding catalog providers. |  | ||||||
| 
 |  | ||||||
|         :param overriding: Overriding catalog. |  | ||||||
|         :type overriding: :py:class:`DeclarativeCatalog` | |  | ||||||
|                           :py:class:`DynamicCatalog` |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.Error` if trying to |  | ||||||
|                 override catalog by itself |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         if overriding is self: |  | ||||||
|             raise Error('Catalog {0} could not be overridden ' |  | ||||||
|                         'with itself'.format(self)) |  | ||||||
|         self.overridden_by += (overriding,) |  | ||||||
|         for name, provider in six.iteritems(overriding.providers): |  | ||||||
|             self.get_provider(name).override(provider) |  | ||||||
| 
 |  | ||||||
|     def reset_last_overriding(self): |  | ||||||
|         """Reset last overriding catalog. |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         if not self.is_overridden: |  | ||||||
|             raise Error('Catalog {0} is not overridden'.format(self)) |  | ||||||
|         self.overridden_by = self.overridden_by[:-1] |  | ||||||
|         for provider in six.itervalues(self.providers): |  | ||||||
|             provider.reset_last_overriding() |  | ||||||
| 
 |  | ||||||
|     def reset_override(self): |  | ||||||
|         """Reset all overridings for all catalog providers. |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         self.overridden_by = tuple() |  | ||||||
|         for provider in six.itervalues(self.providers): |  | ||||||
|             provider.reset_override() |  | ||||||
| 
 |  | ||||||
|     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 UndefinedProviderError('{0} has no provider with such ' |  | ||||||
|                                          'name - {1}'.format(self, name)) |  | ||||||
| 
 |  | ||||||
|     def bind_provider(self, name, provider, force=False): |  | ||||||
|         """Bind provider to catalog with specified name. |  | ||||||
| 
 |  | ||||||
|         :param name: Name of the provider. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :param provider: Provider instance. |  | ||||||
|         :type provider: :py:class:`dependency_injector.providers.Provider` |  | ||||||
| 
 |  | ||||||
|         :param force: Force binding of provider. |  | ||||||
|         :type force: bool |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.Error` |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         provider = ensure_is_provider(provider) |  | ||||||
| 
 |  | ||||||
|         if (self.__class__.provider_type and |  | ||||||
|                 not isinstance(provider, self.__class__.provider_type)): |  | ||||||
|             raise Error('{0} can contain only {1} instances'.format( |  | ||||||
|                 self, self.__class__.provider_type)) |  | ||||||
| 
 |  | ||||||
|         if not force: |  | ||||||
|             if name in self.providers: |  | ||||||
|                 raise Error('Catalog {0} already has provider with ' |  | ||||||
|                             'such name - {1}'.format(self, name)) |  | ||||||
|             if provider in self.provider_names: |  | ||||||
|                 raise Error('Catalog {0} already has such provider ' |  | ||||||
|                             'instance - {1}'.format(self, provider)) |  | ||||||
| 
 |  | ||||||
|         self.providers[name] = provider |  | ||||||
|         self.provider_names[provider] = name |  | ||||||
| 
 |  | ||||||
|     def bind_providers(self, providers, force=False): |  | ||||||
|         """Bind providers dictionary to catalog. |  | ||||||
| 
 |  | ||||||
|         :param providers: Dictionary of providers, where key is a name |  | ||||||
|             and value is a provider. |  | ||||||
|         :type providers: |  | ||||||
|             dict[str, :py:class:`dependency_injector.providers.Provider`] |  | ||||||
| 
 |  | ||||||
|         :param force: Force binding of providers. |  | ||||||
|         :type force: bool |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.Error` |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         for name, provider in six.iteritems(providers): |  | ||||||
|             self.bind_provider(name, provider, force) |  | ||||||
| 
 |  | ||||||
|     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 unbind_provider(self, name): |  | ||||||
|         """Remove provider binding. |  | ||||||
| 
 |  | ||||||
|         :param name: Provider's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         provider = self.get_provider(name) |  | ||||||
|         del self.providers[name] |  | ||||||
|         del self.provider_names[provider] |  | ||||||
| 
 |  | ||||||
|     def __getattr__(self, name): |  | ||||||
|         """Return provider with specified name or raise en error. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :raise: :py:exc:`dependency_injector.errors.UndefinedProviderError` |  | ||||||
|         """ |  | ||||||
|         return self.get_provider(name) |  | ||||||
| 
 |  | ||||||
|     def __setattr__(self, name, value): |  | ||||||
|         """Handle setting of catalog attributes. |  | ||||||
| 
 |  | ||||||
|         Setting of attributes works as usual, but if value of attribute is |  | ||||||
|         provider, this provider will be bound to catalog. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :param value: Attribute's value. |  | ||||||
|         :type value: :py:class:`dependency_injector.providers.Provider` | |  | ||||||
|                      object |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         if is_provider(value): |  | ||||||
|             return self.bind_provider(name, value) |  | ||||||
|         return super(DynamicCatalog, self).__setattr__(name, value) |  | ||||||
| 
 |  | ||||||
|     def __delattr__(self, name): |  | ||||||
|         """Handle deleting of catalog attibute. |  | ||||||
| 
 |  | ||||||
|         Deleting of attributes works as usual, but if value of attribute is |  | ||||||
|         provider, this provider will be unbound from catalog. |  | ||||||
| 
 |  | ||||||
|         :param name: Attribute's name. |  | ||||||
|         :type name: str |  | ||||||
| 
 |  | ||||||
|         :rtype: None |  | ||||||
|         """ |  | ||||||
|         self.unbind_provider(name) |  | ||||||
| 
 |  | ||||||
|     def __repr__(self): |  | ||||||
|         """Return Python representation of catalog. |  | ||||||
| 
 |  | ||||||
|         :rtype: str |  | ||||||
|         """ |  | ||||||
|         return '<{0}({1})>'.format('.'.join((self.__class__.__module__, |  | ||||||
|                                              self.__class__.__name__)), |  | ||||||
|                                    ', '.join(six.iterkeys(self.providers))) |  | ||||||
| 
 |  | ||||||
|     __str__ = __repr__ |  | ||||||
|  | @ -1,62 +0,0 @@ | ||||||
| """Dependency injector catalog utils.""" |  | ||||||
| 
 |  | ||||||
| import six |  | ||||||
| 
 |  | ||||||
| from dependency_injector.utils import _copy_providers |  | ||||||
| from dependency_injector.errors import UndefinedProviderError |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def copy(catalog): |  | ||||||
|     """:py:class:`DeclarativeCatalog` copying decorator. |  | ||||||
| 
 |  | ||||||
|     This decorator copy all providers from provided catalog to decorated one. |  | ||||||
|     If one of the decorated catalog providers matches to source catalog |  | ||||||
|     providers by name, it would be replaced by reference. |  | ||||||
| 
 |  | ||||||
|     :param catalog: Catalog that should be copied by decorated catalog. |  | ||||||
|     :type catalog: :py:class:`DeclarativeCatalog` |  | ||||||
| 
 |  | ||||||
|     :return: Declarative catalog's copying decorator. |  | ||||||
|     :rtype: |  | ||||||
|         callable(:py:class:`DeclarativeCatalog`) |  | ||||||
|     """ |  | ||||||
|     def decorator(copied_catalog): |  | ||||||
|         """Copying decorator. |  | ||||||
| 
 |  | ||||||
|         :param copied_catalog: Decorated catalog. |  | ||||||
|         :type copied_catalog: :py:class:`DeclarativeCatalog` |  | ||||||
| 
 |  | ||||||
|         :return: Decorated catalog. |  | ||||||
|         :rtype: |  | ||||||
|             :py:class:`DeclarativeCatalog` |  | ||||||
|         """ |  | ||||||
|         memo = dict() |  | ||||||
|         for name, provider in six.iteritems(copied_catalog.cls_providers): |  | ||||||
|             try: |  | ||||||
|                 source_provider = catalog.get_provider(name) |  | ||||||
|             except UndefinedProviderError: |  | ||||||
|                 pass |  | ||||||
|             else: |  | ||||||
|                 memo[id(source_provider)] = provider |  | ||||||
| 
 |  | ||||||
|         copied_catalog.bind_providers(_copy_providers(catalog.providers, memo), |  | ||||||
|                                       force=True) |  | ||||||
| 
 |  | ||||||
|         return copied_catalog |  | ||||||
|     return decorator |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def override(catalog): |  | ||||||
|     """:py:class:`DeclarativeCatalog` overriding decorator. |  | ||||||
| 
 |  | ||||||
|     :param catalog: Catalog that should be overridden by decorated catalog. |  | ||||||
|     :type catalog: :py:class:`DeclarativeCatalog` |  | ||||||
| 
 |  | ||||||
|     :return: Declarative catalog's overriding decorator. |  | ||||||
|     :rtype: callable(:py:class:`DeclarativeCatalog`) |  | ||||||
|     """ |  | ||||||
|     def decorator(overriding_catalog): |  | ||||||
|         """Overriding decorator.""" |  | ||||||
|         catalog.override(overriding_catalog) |  | ||||||
|         return overriding_catalog |  | ||||||
|     return decorator |  | ||||||
|  | @ -9,6 +9,86 @@ from dependency_injector import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class DynamicContainer(object): | ||||||
|  |     """Dynamic inversion of control container.""" | ||||||
|  | 
 | ||||||
|  |     __IS_CONTAINER__ = True | ||||||
|  | 
 | ||||||
|  |     def __init__(self): | ||||||
|  |         """Initializer.""" | ||||||
|  |         self.provider_type = providers.Provider | ||||||
|  |         self.providers = dict() | ||||||
|  |         self.overridden_by = tuple() | ||||||
|  |         super(DynamicContainer, self).__init__() | ||||||
|  | 
 | ||||||
|  |     def __setattr__(self, name, value): | ||||||
|  |         """Set instance attribute. | ||||||
|  | 
 | ||||||
|  |         If value of attribute is provider, it will be added into providers | ||||||
|  |         dictionary. | ||||||
|  |         """ | ||||||
|  |         if utils.is_provider(value): | ||||||
|  |             _check_provider_type(self, value) | ||||||
|  |             self.providers[name] = value | ||||||
|  |         super(DynamicContainer, self).__setattr__(name, value) | ||||||
|  | 
 | ||||||
|  |     def __delattr__(self, name): | ||||||
|  |         """Delete instance attribute. | ||||||
|  | 
 | ||||||
|  |         If value of attribute is provider, it will be deleted from providers | ||||||
|  |         dictionary. | ||||||
|  |         """ | ||||||
|  |         if name in self.providers: | ||||||
|  |             del self.providers[name] | ||||||
|  |         super(DynamicContainer, self).__delattr__(name) | ||||||
|  | 
 | ||||||
|  |     def override(self, overriding): | ||||||
|  |         """Override current container by overriding container. | ||||||
|  | 
 | ||||||
|  |         :param overriding: Overriding container. | ||||||
|  |         :type overriding: :py:class:`DeclarativeContainer` | ||||||
|  | 
 | ||||||
|  |         :raise: :py:exc:`dependency_injector.errors.Error` if trying to | ||||||
|  |                 override container by itself or its subclasses | ||||||
|  | 
 | ||||||
|  |         :rtype: None | ||||||
|  |         """ | ||||||
|  |         if overriding is self: | ||||||
|  |             raise errors.Error('Container {0} could not be overridden ' | ||||||
|  |                                'with itself'.format(self)) | ||||||
|  | 
 | ||||||
|  |         self.overridden_by += (overriding,) | ||||||
|  | 
 | ||||||
|  |         for name, provider in six.iteritems(overriding.providers): | ||||||
|  |             try: | ||||||
|  |                 getattr(self, name).override(provider) | ||||||
|  |             except AttributeError: | ||||||
|  |                 pass | ||||||
|  | 
 | ||||||
|  |     def reset_last_overriding(self): | ||||||
|  |         """Reset last overriding provider for each container providers. | ||||||
|  | 
 | ||||||
|  |         :rtype: None | ||||||
|  |         """ | ||||||
|  |         if not self.overridden_by: | ||||||
|  |             raise errors.Error('Container {0} is not overridden'.format(self)) | ||||||
|  | 
 | ||||||
|  |         self.overridden_by = self.overridden_by[:-1] | ||||||
|  | 
 | ||||||
|  |         for provider in six.itervalues(self.providers): | ||||||
|  |             provider.reset_last_overriding() | ||||||
|  | 
 | ||||||
|  |     def reset_override(self): | ||||||
|  |         """Reset all overridings for each container providers. | ||||||
|  | 
 | ||||||
|  |         :rtype: None | ||||||
|  |         """ | ||||||
|  |         self.overridden_by = tuple() | ||||||
|  | 
 | ||||||
|  |         for provider in six.itervalues(self.providers): | ||||||
|  |             provider.reset_override() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class DeclarativeContainerMetaClass(type): | class DeclarativeContainerMetaClass(type): | ||||||
|     """Declarative inversion of control container meta class.""" |     """Declarative inversion of control container meta class.""" | ||||||
| 
 | 
 | ||||||
|  | @ -20,7 +100,7 @@ class DeclarativeContainerMetaClass(type): | ||||||
| 
 | 
 | ||||||
|         inherited_providers = tuple((name, provider) |         inherited_providers = tuple((name, provider) | ||||||
|                                     for base in bases if utils.is_container( |                                     for base in bases if utils.is_container( | ||||||
|                                         base) |                                         base) and base is not DynamicContainer | ||||||
|                                     for name, provider in six.iteritems( |                                     for name, provider in six.iteritems( | ||||||
|                                         base.cls_providers)) |                                         base.cls_providers)) | ||||||
| 
 | 
 | ||||||
|  | @ -70,9 +150,20 @@ class DeclarativeContainer(object): | ||||||
|     providers = dict() |     providers = dict() | ||||||
|     cls_providers = dict() |     cls_providers = dict() | ||||||
|     inherited_providers = dict() |     inherited_providers = dict() | ||||||
| 
 |  | ||||||
|     overridden_by = tuple() |     overridden_by = tuple() | ||||||
| 
 | 
 | ||||||
|  |     instance_type = DynamicContainer | ||||||
|  | 
 | ||||||
|  |     def __new__(cls, *args, **kwargs): | ||||||
|  |         """Constructor.""" | ||||||
|  |         container = cls.instance_type(*args, **kwargs) | ||||||
|  |         container.provider_type = cls.provider_type | ||||||
|  | 
 | ||||||
|  |         for name, provider in six.iteritems(utils.deepcopy(cls.providers)): | ||||||
|  |             setattr(container, name, provider) | ||||||
|  | 
 | ||||||
|  |         return container | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def override(cls, overriding): |     def override(cls, overriding): | ||||||
|         """Override current container by overriding container. |         """Override current container by overriding container. | ||||||
|  | @ -163,7 +254,7 @@ def copy(container): | ||||||
|             else: |             else: | ||||||
|                 memo[id(source_provider)] = provider |                 memo[id(source_provider)] = provider | ||||||
| 
 | 
 | ||||||
|         providers_copy = utils._copy_providers(container.providers, memo) |         providers_copy = utils.deepcopy(container.providers, memo) | ||||||
|         for name, provider in six.iteritems(providers_copy): |         for name, provider in six.iteritems(providers_copy): | ||||||
|             setattr(copied_container, name, provider) |             setattr(copied_container, name, provider) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| """Utils module.""" | """Utils module.""" | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import copy | import copy as _copy | ||||||
| import types | import types | ||||||
| import threading | import threading | ||||||
| 
 | 
 | ||||||
|  | @ -23,9 +23,9 @@ else:  # pragma: no cover | ||||||
|     _OBJECT_INIT = None |     _OBJECT_INIT = None | ||||||
| 
 | 
 | ||||||
| if six.PY2:  # pragma: no cover | if six.PY2:  # pragma: no cover | ||||||
|     copy._deepcopy_dispatch[types.MethodType] = \ |     _copy._deepcopy_dispatch[types.MethodType] = \ | ||||||
|         lambda obj, memo: type(obj)(obj.im_func, |         lambda obj, memo: type(obj)(obj.im_func, | ||||||
|                                     copy.deepcopy(obj.im_self, memo), |                                     _copy.deepcopy(obj.im_self, memo), | ||||||
|                                     obj.im_class) |                                     obj.im_class) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -71,40 +71,6 @@ def is_container(instance): | ||||||
|             getattr(instance, '__IS_CONTAINER__', False) is True) |             getattr(instance, '__IS_CONTAINER__', False) is True) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def is_catalog(instance): |  | ||||||
|     """Check if instance is catalog instance. |  | ||||||
| 
 |  | ||||||
|     :param instance: Instance to be checked. |  | ||||||
|     :type instance: object |  | ||||||
| 
 |  | ||||||
|     :rtype: bool |  | ||||||
|     """ |  | ||||||
|     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. |  | ||||||
| 
 |  | ||||||
|     :param instance: Instance to be checked. |  | ||||||
|     :type instance: object |  | ||||||
| 
 |  | ||||||
|     :rtype: bool |  | ||||||
|     """ |  | ||||||
|     return (not isinstance(instance, six.class_types) and is_catalog(instance)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def is_declarative_catalog(instance): |  | ||||||
|     """Check if instance is declarative catalog instance. |  | ||||||
| 
 |  | ||||||
|     :param instance: Instance to be checked. |  | ||||||
|     :type instance: object |  | ||||||
| 
 |  | ||||||
|     :rtype: bool |  | ||||||
|     """ |  | ||||||
|     return (isinstance(instance, six.class_types) and is_catalog(instance)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def represent_provider(provider, provides): | def represent_provider(provider, provides): | ||||||
|     """Return string representation of provider. |     """Return string representation of provider. | ||||||
| 
 | 
 | ||||||
|  | @ -142,6 +108,6 @@ def fetch_cls_init(cls): | ||||||
|         return cls_init |         return cls_init | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _copy_providers(providers, memo=None): | def deepcopy(instance, memo=None): | ||||||
|     """Make full copy of providers dictionary.""" |     """Make full copy of instance.""" | ||||||
|     return copy.deepcopy(providers, memo) |     return _copy.deepcopy(instance, memo) | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -54,7 +54,6 @@ setup(name='dependency_injector', | ||||||
|       download_url='https://pypi.python.org/pypi/dependency_injector', |       download_url='https://pypi.python.org/pypi/dependency_injector', | ||||||
|       license='BSD New', |       license='BSD New', | ||||||
|       packages=['dependency_injector', |       packages=['dependency_injector', | ||||||
|                 'dependency_injector.catalogs', |  | ||||||
|                 'dependency_injector.providers'], |                 'dependency_injector.providers'], | ||||||
|       platforms=['any'], |       platforms=['any'], | ||||||
|       zip_safe=True, |       zip_safe=True, | ||||||
|  |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| """Dependency injector catalogs unittests.""" |  | ||||||
|  | @ -1,443 +0,0 @@ | ||||||
| """Dependency injector declarative catalog unittests.""" |  | ||||||
| 
 |  | ||||||
| import unittest2 as unittest |  | ||||||
| 
 |  | ||||||
| from dependency_injector import ( |  | ||||||
|     catalogs, |  | ||||||
|     providers, |  | ||||||
|     injections, |  | ||||||
|     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 DeclarativeCatalogTests(unittest.TestCase): |  | ||||||
|     """Declarative catalog tests.""" |  | ||||||
| 
 |  | ||||||
|     def test_cls_providers(self): |  | ||||||
|         """Test `di.DeclarativeCatalog.cls_providers` contents.""" |  | ||||||
|         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() |  | ||||||
|         self.assertDictEqual(CatalogA.cls_providers, |  | ||||||
|                              dict(p11=CatalogA.p11, |  | ||||||
|                                   p12=CatalogA.p12)) |  | ||||||
|         self.assertDictEqual(CatalogB.cls_providers, |  | ||||||
|                              dict(p21=CatalogB.p21, |  | ||||||
|                                   p22=CatalogB.p22)) |  | ||||||
| 
 |  | ||||||
|     def test_inherited_providers(self): |  | ||||||
|         """Test `di.DeclarativeCatalog.inherited_providers` contents.""" |  | ||||||
|         self.assertDictEqual(CatalogA.inherited_providers, dict()) |  | ||||||
|         self.assertDictEqual(CatalogB.inherited_providers, |  | ||||||
|                              dict(p11=CatalogA.p11, |  | ||||||
|                                   p12=CatalogA.p12)) |  | ||||||
| 
 |  | ||||||
|     def test_providers(self): |  | ||||||
|         """Test `di.DeclarativeCatalog.inherited_providers` contents.""" |  | ||||||
|         self.assertDictEqual(CatalogA.providers, |  | ||||||
|                              dict(p11=CatalogA.p11, |  | ||||||
|                                   p12=CatalogA.p12)) |  | ||||||
|         self.assertDictEqual(CatalogB.providers, |  | ||||||
|                              dict(p11=CatalogA.p11, |  | ||||||
|                                   p12=CatalogA.p12, |  | ||||||
|                                   p21=CatalogB.p21, |  | ||||||
|                                   p22=CatalogB.p22)) |  | ||||||
| 
 |  | ||||||
|     def test_bind_provider(self): |  | ||||||
|         """Test setting of provider via bind_provider() to catalog.""" |  | ||||||
|         px = providers.Provider() |  | ||||||
|         py = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         CatalogA.bind_provider('px', px) |  | ||||||
|         CatalogA.bind_provider('py', py) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogA.px, px) |  | ||||||
|         self.assertIs(CatalogA.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogA.py, py) |  | ||||||
|         self.assertIs(CatalogA.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|         del CatalogA.px |  | ||||||
|         del CatalogA.py |  | ||||||
| 
 |  | ||||||
|     def test_bind_existing_provider(self): |  | ||||||
|         """Test setting of provider via bind_provider() to catalog.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             CatalogA.p11 = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             CatalogA.bind_provider('p11', providers.Provider()) |  | ||||||
| 
 |  | ||||||
|     def test_bind_provider_with_valid_provided_type(self): |  | ||||||
|         """Test setting of provider with provider type restriction.""" |  | ||||||
|         class SomeProvider(providers.Provider): |  | ||||||
|             """Some provider.""" |  | ||||||
| 
 |  | ||||||
|         class SomeCatalog(catalogs.DeclarativeCatalog): |  | ||||||
|             """Some catalog with provider type restriction.""" |  | ||||||
| 
 |  | ||||||
|             provider_type = SomeProvider |  | ||||||
| 
 |  | ||||||
|         px = SomeProvider() |  | ||||||
|         py = SomeProvider() |  | ||||||
| 
 |  | ||||||
|         SomeCatalog.bind_provider('px', px) |  | ||||||
|         SomeCatalog.py = py |  | ||||||
| 
 |  | ||||||
|         self.assertIs(SomeCatalog.px, px) |  | ||||||
|         self.assertIs(SomeCatalog.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(SomeCatalog.py, py) |  | ||||||
|         self.assertIs(SomeCatalog.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|     def test_bind_provider_with_invalid_provided_type(self): |  | ||||||
|         """Test setting of provider with provider type restriction.""" |  | ||||||
|         class SomeProvider(providers.Provider): |  | ||||||
|             """Some provider.""" |  | ||||||
| 
 |  | ||||||
|         class SomeCatalog(catalogs.DeclarativeCatalog): |  | ||||||
|             """Some catalog with provider type restriction.""" |  | ||||||
| 
 |  | ||||||
|             provider_type = SomeProvider |  | ||||||
| 
 |  | ||||||
|         px = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             SomeCatalog.bind_provider('px', px) |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             SomeCatalog.px = px |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             SomeCatalog.bind_providers(dict(px=px)) |  | ||||||
| 
 |  | ||||||
|     def test_bind_providers(self): |  | ||||||
|         """Test setting of provider via bind_providers() to catalog.""" |  | ||||||
|         px = providers.Provider() |  | ||||||
|         py = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         CatalogB.bind_providers(dict(px=px, py=py)) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogB.px, px) |  | ||||||
|         self.assertIs(CatalogB.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogB.py, py) |  | ||||||
|         self.assertIs(CatalogB.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|         del CatalogB.px |  | ||||||
|         del CatalogB.py |  | ||||||
| 
 |  | ||||||
|     def test_setattr(self): |  | ||||||
|         """Test setting of providers via attributes to catalog.""" |  | ||||||
|         px = providers.Provider() |  | ||||||
|         py = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         CatalogB.px = px |  | ||||||
|         CatalogB.py = py |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogB.px, px) |  | ||||||
|         self.assertIs(CatalogB.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogB.py, py) |  | ||||||
|         self.assertIs(CatalogB.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|         del CatalogB.px |  | ||||||
|         del CatalogB.py |  | ||||||
| 
 |  | ||||||
|     def test_unbind_provider(self): |  | ||||||
|         """Test that catalog unbinds provider correct.""" |  | ||||||
|         CatalogB.px = providers.Provider() |  | ||||||
|         CatalogB.unbind_provider('px') |  | ||||||
|         self.assertFalse(CatalogB.has_provider('px')) |  | ||||||
| 
 |  | ||||||
|     def test_unbind_via_delattr(self): |  | ||||||
|         """Test that catalog unbinds provider correct.""" |  | ||||||
|         CatalogB.px = providers.Provider() |  | ||||||
|         del CatalogB.px |  | ||||||
|         self.assertFalse(CatalogB.has_provider('px')) |  | ||||||
| 
 |  | ||||||
|     def test_provider_is_bound(self): |  | ||||||
|         """Test that providers are bound to the catalogs.""" |  | ||||||
|         self.assertTrue(CatalogA.is_provider_bound(CatalogA.p11)) |  | ||||||
|         self.assertEquals(CatalogA.get_provider_bind_name(CatalogA.p11), 'p11') |  | ||||||
| 
 |  | ||||||
|         self.assertTrue(CatalogA.is_provider_bound(CatalogA.p12)) |  | ||||||
|         self.assertEquals(CatalogA.get_provider_bind_name(CatalogA.p12), 'p12') |  | ||||||
| 
 |  | ||||||
|     def test_provider_binding_to_different_catalogs(self): |  | ||||||
|         """Test that provider could be bound to different catalogs.""" |  | ||||||
|         p11 = CatalogA.p11 |  | ||||||
|         p12 = CatalogA.p12 |  | ||||||
| 
 |  | ||||||
|         class CatalogD(catalogs.DeclarativeCatalog): |  | ||||||
|             """Test catalog.""" |  | ||||||
| 
 |  | ||||||
|             pd1 = p11 |  | ||||||
|             pd2 = p12 |  | ||||||
| 
 |  | ||||||
|         class CatalogE(catalogs.DeclarativeCatalog): |  | ||||||
|             """Test catalog.""" |  | ||||||
| 
 |  | ||||||
|             pe1 = p11 |  | ||||||
|             pe2 = p12 |  | ||||||
| 
 |  | ||||||
|         self.assertTrue(CatalogA.is_provider_bound(p11)) |  | ||||||
|         self.assertTrue(CatalogD.is_provider_bound(p11)) |  | ||||||
|         self.assertTrue(CatalogE.is_provider_bound(p11)) |  | ||||||
|         self.assertEquals(CatalogA.get_provider_bind_name(p11), 'p11') |  | ||||||
|         self.assertEquals(CatalogD.get_provider_bind_name(p11), 'pd1') |  | ||||||
|         self.assertEquals(CatalogE.get_provider_bind_name(p11), 'pe1') |  | ||||||
| 
 |  | ||||||
|         self.assertTrue(CatalogA.is_provider_bound(p12)) |  | ||||||
|         self.assertTrue(CatalogD.is_provider_bound(p12)) |  | ||||||
|         self.assertTrue(CatalogE.is_provider_bound(p12)) |  | ||||||
|         self.assertEquals(CatalogA.get_provider_bind_name(p12), 'p12') |  | ||||||
|         self.assertEquals(CatalogD.get_provider_bind_name(p12), 'pd2') |  | ||||||
|         self.assertEquals(CatalogE.get_provider_bind_name(p12), 'pe2') |  | ||||||
| 
 |  | ||||||
|     def test_provider_rebinding_to_the_same_catalog(self): |  | ||||||
|         """Test provider rebinding to the same catalog.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             class TestCatalog(catalogs.DeclarativeCatalog): |  | ||||||
|                 """Test catalog.""" |  | ||||||
| 
 |  | ||||||
|                 p1 = providers.Provider() |  | ||||||
|                 p2 = p1 |  | ||||||
| 
 |  | ||||||
|     def test_provider_rebinding_to_the_same_catalogs_hierarchy(self): |  | ||||||
|         """Test provider rebinding to the same catalogs hierarchy.""" |  | ||||||
|         class TestCatalog1(catalogs.DeclarativeCatalog): |  | ||||||
|             """Test catalog.""" |  | ||||||
| 
 |  | ||||||
|             p1 = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             class TestCatalog2(TestCatalog1): |  | ||||||
|                 """Test catalog.""" |  | ||||||
| 
 |  | ||||||
|                 p2 = TestCatalog1.p1 |  | ||||||
| 
 |  | ||||||
|     def test_get(self): |  | ||||||
|         """Test getting of providers using get() method.""" |  | ||||||
|         self.assertIs(CatalogB.get_provider('p11'), CatalogB.p11) |  | ||||||
|         self.assertIs(CatalogB.get_provider('p12'), CatalogB.p12) |  | ||||||
|         self.assertIs(CatalogB.get_provider('p22'), CatalogB.p22) |  | ||||||
|         self.assertIs(CatalogB.get_provider('p22'), CatalogB.p22) |  | ||||||
| 
 |  | ||||||
|     def test_get_undefined(self): |  | ||||||
|         """Test getting of undefined providers using get() method.""" |  | ||||||
|         with self.assertRaises(errors.UndefinedProviderError): |  | ||||||
|             CatalogB.get('undefined') |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.UndefinedProviderError): |  | ||||||
|             CatalogB.get_provider('undefined') |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.UndefinedProviderError): |  | ||||||
|             CatalogB.undefined |  | ||||||
| 
 |  | ||||||
|     def test_has(self): |  | ||||||
|         """Test checks of providers availability in catalog.""" |  | ||||||
|         self.assertTrue(CatalogB.has_provider('p11')) |  | ||||||
|         self.assertTrue(CatalogB.has_provider('p12')) |  | ||||||
|         self.assertTrue(CatalogB.has_provider('p21')) |  | ||||||
|         self.assertTrue(CatalogB.has_provider('p22')) |  | ||||||
|         self.assertFalse(CatalogB.has_provider('undefined')) |  | ||||||
| 
 |  | ||||||
|     def test_filter_all_providers_by_type(self): |  | ||||||
|         """Test getting of all catalog providers of specific type.""" |  | ||||||
|         self.assertTrue(len(CatalogB.filter(providers.Provider)) == 4) |  | ||||||
|         self.assertTrue(len(CatalogB.filter(providers.Object)) == 0) |  | ||||||
| 
 |  | ||||||
|     def test_repr(self): |  | ||||||
|         """Test catalog representation.""" |  | ||||||
|         self.assertIn('CatalogA', repr(CatalogA)) |  | ||||||
|         self.assertIn('p11', repr(CatalogA)) |  | ||||||
|         self.assertIn('p12', repr(CatalogA)) |  | ||||||
| 
 |  | ||||||
|         self.assertIn('CatalogB', repr(CatalogB)) |  | ||||||
|         self.assertIn('p11', repr(CatalogB)) |  | ||||||
|         self.assertIn('p12', repr(CatalogB)) |  | ||||||
|         self.assertIn('p21', repr(CatalogB)) |  | ||||||
|         self.assertIn('p22', repr(CatalogB)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class TestCatalogWithProvidingCallbacks(unittest.TestCase): |  | ||||||
|     """Catalog with providing callback tests.""" |  | ||||||
| 
 |  | ||||||
|     def test_concept(self): |  | ||||||
|         """Test concept.""" |  | ||||||
|         class UsersService(object): |  | ||||||
|             """Users service, that has dependency on database.""" |  | ||||||
| 
 |  | ||||||
|         class AuthService(object): |  | ||||||
|             """Auth service, that has dependencies on users service.""" |  | ||||||
| 
 |  | ||||||
|             def __init__(self, users_service): |  | ||||||
|                 """Initializer.""" |  | ||||||
|                 self.users_service = users_service |  | ||||||
| 
 |  | ||||||
|         class Services(catalogs.DeclarativeCatalog): |  | ||||||
|             """Catalog of service providers.""" |  | ||||||
| 
 |  | ||||||
|             @providers.Factory |  | ||||||
|             def users(): |  | ||||||
|                 """Provide users service. |  | ||||||
| 
 |  | ||||||
|                 :rtype: providers.Provider -> UsersService |  | ||||||
|                 """ |  | ||||||
|                 return UsersService() |  | ||||||
| 
 |  | ||||||
|             @providers.Factory |  | ||||||
|             @injections.inject(users_service=users) |  | ||||||
|             def auth(**kwargs): |  | ||||||
|                 """Provide users service. |  | ||||||
| 
 |  | ||||||
|                 :rtype: providers.Provider -> AuthService |  | ||||||
|                 """ |  | ||||||
|                 return AuthService(**kwargs) |  | ||||||
| 
 |  | ||||||
|         # Retrieving catalog providers: |  | ||||||
|         users_service = Services.users() |  | ||||||
|         auth_service = Services.auth() |  | ||||||
| 
 |  | ||||||
|         # Making some asserts: |  | ||||||
|         self.assertIsInstance(auth_service.users_service, UsersService) |  | ||||||
|         self.assertIsNot(users_service, Services.users()) |  | ||||||
|         self.assertIsNot(auth_service, Services.auth()) |  | ||||||
| 
 |  | ||||||
|         # Overriding auth service provider and making some asserts: |  | ||||||
|         class ExtendedAuthService(AuthService): |  | ||||||
|             """Extended version of auth service.""" |  | ||||||
| 
 |  | ||||||
|             def __init__(self, users_service, ttl): |  | ||||||
|                 """Initializer.""" |  | ||||||
|                 self.ttl = ttl |  | ||||||
|                 super(ExtendedAuthService, self).__init__( |  | ||||||
|                     users_service=users_service) |  | ||||||
| 
 |  | ||||||
|         class OverriddenServices(Services): |  | ||||||
|             """Catalog of service providers.""" |  | ||||||
| 
 |  | ||||||
|             @providers.override(Services.auth) |  | ||||||
|             @providers.Factory |  | ||||||
|             @injections.inject(users_service=Services.users) |  | ||||||
|             @injections.inject(ttl=3600) |  | ||||||
|             def auth(**kwargs): |  | ||||||
|                 """Provide users service. |  | ||||||
| 
 |  | ||||||
|                 :rtype: providers.Provider -> AuthService |  | ||||||
|                 """ |  | ||||||
|                 return ExtendedAuthService(**kwargs) |  | ||||||
| 
 |  | ||||||
|         auth_service = Services.auth() |  | ||||||
| 
 |  | ||||||
|         self.assertIsInstance(auth_service, ExtendedAuthService) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class CopyingTests(unittest.TestCase): |  | ||||||
|     """Declarative catalogs copying tests.""" |  | ||||||
| 
 |  | ||||||
|     def test_copy(self): |  | ||||||
|         """Test catalog providers copying.""" |  | ||||||
|         @catalogs.copy(CatalogA) |  | ||||||
|         class CatalogA1(CatalogA): |  | ||||||
|             pass |  | ||||||
| 
 |  | ||||||
|         @catalogs.copy(CatalogA) |  | ||||||
|         class CatalogA2(CatalogA): |  | ||||||
|             pass |  | ||||||
| 
 |  | ||||||
|         self.assertIsNot(CatalogA.p11, CatalogA1.p11) |  | ||||||
|         self.assertIsNot(CatalogA.p12, CatalogA1.p12) |  | ||||||
| 
 |  | ||||||
|         self.assertIsNot(CatalogA.p11, CatalogA2.p11) |  | ||||||
|         self.assertIsNot(CatalogA.p12, CatalogA2.p12) |  | ||||||
| 
 |  | ||||||
|         self.assertIsNot(CatalogA1.p11, CatalogA2.p11) |  | ||||||
|         self.assertIsNot(CatalogA1.p12, CatalogA2.p12) |  | ||||||
| 
 |  | ||||||
|     def test_copy_with_replacing(self): |  | ||||||
|         """Test catalog providers copying.""" |  | ||||||
|         class CatalogA(catalogs.DeclarativeCatalog): |  | ||||||
|             p11 = providers.Object(0) |  | ||||||
|             p12 = providers.Factory(dict) \ |  | ||||||
|                 .add_kwargs(p11=p11) |  | ||||||
| 
 |  | ||||||
|         @catalogs.copy(CatalogA) |  | ||||||
|         class CatalogA1(CatalogA): |  | ||||||
|             p11 = providers.Object(1) |  | ||||||
|             p13 = providers.Object(11) |  | ||||||
| 
 |  | ||||||
|         @catalogs.copy(CatalogA) |  | ||||||
|         class CatalogA2(CatalogA): |  | ||||||
|             p11 = providers.Object(2) |  | ||||||
|             p13 = providers.Object(22) |  | ||||||
| 
 |  | ||||||
|         self.assertIsNot(CatalogA.p11, CatalogA1.p11) |  | ||||||
|         self.assertIsNot(CatalogA.p12, CatalogA1.p12) |  | ||||||
| 
 |  | ||||||
|         self.assertIsNot(CatalogA.p11, CatalogA2.p11) |  | ||||||
|         self.assertIsNot(CatalogA.p12, CatalogA2.p12) |  | ||||||
| 
 |  | ||||||
|         self.assertIsNot(CatalogA1.p11, CatalogA2.p11) |  | ||||||
|         self.assertIsNot(CatalogA1.p12, CatalogA2.p12) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogA.p12.kwargs['p11'], CatalogA.p11) |  | ||||||
|         self.assertIs(CatalogA1.p12.kwargs['p11'], CatalogA1.p11) |  | ||||||
|         self.assertIs(CatalogA2.p12.kwargs['p11'], CatalogA2.p11) |  | ||||||
| 
 |  | ||||||
|         self.assertEqual(CatalogA.p12(), dict(p11=0)) |  | ||||||
|         self.assertEqual(CatalogA1.p12(), dict(p11=1)) |  | ||||||
|         self.assertEqual(CatalogA2.p12(), dict(p11=2)) |  | ||||||
| 
 |  | ||||||
|         self.assertEqual(CatalogA1.p13(), 11) |  | ||||||
|         self.assertEqual(CatalogA2.p13(), 22) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class InstantiationTests(unittest.TestCase): |  | ||||||
|     """Declarative catalogs instantiation tests.""" |  | ||||||
| 
 |  | ||||||
|     def setUp(self): |  | ||||||
|         """Set test environment up.""" |  | ||||||
|         self.catalog = CatalogA() |  | ||||||
| 
 |  | ||||||
|     def tearDown(self): |  | ||||||
|         """Tear test environment down.""" |  | ||||||
|         self.catalog = None |  | ||||||
| 
 |  | ||||||
|     def test_access_instance_attributes(self): |  | ||||||
|         """Test accessing declarative catalog instance attributes.""" |  | ||||||
|         self.assertEqual(self.catalog.providers, |  | ||||||
|                          CatalogA.providers) |  | ||||||
|         self.assertEqual(self.catalog.cls_providers, |  | ||||||
|                          CatalogA.cls_providers) |  | ||||||
|         self.assertEqual(self.catalog.inherited_providers, |  | ||||||
|                          CatalogA.inherited_providers) |  | ||||||
|         self.assertEqual(self.catalog.overridden_by, |  | ||||||
|                          CatalogA.overridden_by) |  | ||||||
|         self.assertEqual(self.catalog.is_overridden, |  | ||||||
|                          CatalogA.is_overridden) |  | ||||||
|         self.assertEqual(self.catalog.last_overriding, |  | ||||||
|                          CatalogA.last_overriding) |  | ||||||
|  | @ -1,221 +0,0 @@ | ||||||
| """Dependency injector dynamic catalog unittests.""" |  | ||||||
| 
 |  | ||||||
| import unittest2 as unittest |  | ||||||
| 
 |  | ||||||
| from dependency_injector import ( |  | ||||||
|     catalogs, |  | ||||||
|     providers, |  | ||||||
|     errors, |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class DynamicCatalogTests(unittest.TestCase): |  | ||||||
|     """Dynamic catalog tests.""" |  | ||||||
| 
 |  | ||||||
|     catalog = None |  | ||||||
|     """:type: di.DynamicCatalog""" |  | ||||||
| 
 |  | ||||||
|     def setUp(self): |  | ||||||
|         """Set test environment up.""" |  | ||||||
|         self.catalog = catalogs.DynamicCatalog(p1=providers.Provider(), |  | ||||||
|                                                p2=providers.Provider()) |  | ||||||
| 
 |  | ||||||
|     def test_providers(self): |  | ||||||
|         """Test `di.DeclarativeCatalog.inherited_providers` contents.""" |  | ||||||
|         self.assertDictEqual(self.catalog.providers, |  | ||||||
|                              dict(p1=self.catalog.p1, |  | ||||||
|                                   p2=self.catalog.p2)) |  | ||||||
| 
 |  | ||||||
|     def test_bind_provider(self): |  | ||||||
|         """Test setting of provider via bind_provider() to catalog.""" |  | ||||||
|         px = providers.Provider() |  | ||||||
|         py = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         self.catalog.bind_provider('px', px) |  | ||||||
|         self.catalog.bind_provider('py', py) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(self.catalog.px, px) |  | ||||||
|         self.assertIs(self.catalog.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(self.catalog.py, py) |  | ||||||
|         self.assertIs(self.catalog.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|     def test_bind_existing_provider(self): |  | ||||||
|         """Test setting of provider via bind_provider() to catalog.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             self.catalog.bind_provider('p1', providers.Factory(object)) |  | ||||||
| 
 |  | ||||||
|     def test_force_bind_existing_provider(self): |  | ||||||
|         """Test setting of provider via bind_provider() to catalog.""" |  | ||||||
|         p1 = providers.Factory(object) |  | ||||||
|         self.catalog.bind_provider('p1', p1, force=True) |  | ||||||
|         self.assertIs(self.catalog.p1, p1) |  | ||||||
| 
 |  | ||||||
|     def test_bind_provider_with_valid_provided_type(self): |  | ||||||
|         """Test setting of provider with provider type restriction.""" |  | ||||||
|         class SomeProvider(providers.Provider): |  | ||||||
|             """Some provider.""" |  | ||||||
| 
 |  | ||||||
|         class SomeCatalog(catalogs.DynamicCatalog): |  | ||||||
|             """Some catalog with provider type restriction.""" |  | ||||||
| 
 |  | ||||||
|             provider_type = SomeProvider |  | ||||||
| 
 |  | ||||||
|         px = SomeProvider() |  | ||||||
|         py = SomeProvider() |  | ||||||
|         catalog = SomeCatalog() |  | ||||||
| 
 |  | ||||||
|         catalog.bind_provider('px', px) |  | ||||||
|         catalog.py = py |  | ||||||
| 
 |  | ||||||
|         self.assertIs(catalog.px, px) |  | ||||||
|         self.assertIs(catalog.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(catalog.py, py) |  | ||||||
|         self.assertIs(catalog.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|     def test_bind_provider_with_invalid_provided_type(self): |  | ||||||
|         """Test setting of provider with provider type restriction.""" |  | ||||||
|         class SomeProvider(providers.Provider): |  | ||||||
|             """Some provider.""" |  | ||||||
| 
 |  | ||||||
|         class SomeCatalog(catalogs.DynamicCatalog): |  | ||||||
|             """Some catalog with provider type restriction.""" |  | ||||||
| 
 |  | ||||||
|             provider_type = SomeProvider |  | ||||||
| 
 |  | ||||||
|         px = providers.Provider() |  | ||||||
|         catalog = SomeCatalog() |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             catalog.bind_provider('px', px) |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             catalog.px = px |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             catalog.bind_providers(dict(px=px)) |  | ||||||
| 
 |  | ||||||
|     def test_bind_providers(self): |  | ||||||
|         """Test setting of provider via bind_providers() to catalog.""" |  | ||||||
|         px = providers.Provider() |  | ||||||
|         py = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         self.catalog.bind_providers(dict(px=px, py=py)) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(self.catalog.px, px) |  | ||||||
|         self.assertIs(self.catalog.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(self.catalog.py, py) |  | ||||||
|         self.assertIs(self.catalog.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|     def test_bind_providers_with_existing(self): |  | ||||||
|         """Test setting of provider via bind_providers() to catalog.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             self.catalog.bind_providers(dict(p1=providers.Factory(object))) |  | ||||||
| 
 |  | ||||||
|     def test_bind_providers_force(self): |  | ||||||
|         """Test setting of provider via bind_providers() to catalog.""" |  | ||||||
|         p1 = providers.Factory(object) |  | ||||||
|         self.catalog.bind_providers(dict(p1=p1), force=True) |  | ||||||
|         self.assertIs(self.catalog.p1, p1) |  | ||||||
| 
 |  | ||||||
|     def test_setattr(self): |  | ||||||
|         """Test setting of providers via attributes to catalog.""" |  | ||||||
|         px = providers.Provider() |  | ||||||
|         py = providers.Provider() |  | ||||||
| 
 |  | ||||||
|         self.catalog.px = px |  | ||||||
|         self.catalog.py = py |  | ||||||
| 
 |  | ||||||
|         self.assertIs(self.catalog.px, px) |  | ||||||
|         self.assertIs(self.catalog.get_provider('px'), px) |  | ||||||
| 
 |  | ||||||
|         self.assertIs(self.catalog.py, py) |  | ||||||
|         self.assertIs(self.catalog.get_provider('py'), py) |  | ||||||
| 
 |  | ||||||
|     def test_unbind_provider(self): |  | ||||||
|         """Test that catalog unbinds provider correct.""" |  | ||||||
|         self.catalog.px = providers.Provider() |  | ||||||
|         self.catalog.unbind_provider('px') |  | ||||||
|         self.assertFalse(self.catalog.has_provider('px')) |  | ||||||
| 
 |  | ||||||
|     def test_unbind_via_delattr(self): |  | ||||||
|         """Test that catalog unbinds provider correct.""" |  | ||||||
|         self.catalog.px = providers.Provider() |  | ||||||
|         del self.catalog.px |  | ||||||
|         self.assertFalse(self.catalog.has_provider('px')) |  | ||||||
| 
 |  | ||||||
|     def test_provider_is_bound(self): |  | ||||||
|         """Test that providers are bound to the catalogs.""" |  | ||||||
|         self.assertTrue(self.catalog.is_provider_bound(self.catalog.p1)) |  | ||||||
|         self.assertEquals( |  | ||||||
|             self.catalog.get_provider_bind_name(self.catalog.p1), 'p1') |  | ||||||
|         self.assertTrue(self.catalog.is_provider_bound(self.catalog.p2)) |  | ||||||
|         self.assertEquals( |  | ||||||
|             self.catalog.get_provider_bind_name(self.catalog.p2), 'p2') |  | ||||||
| 
 |  | ||||||
|     def test_provider_binding_to_different_catalogs(self): |  | ||||||
|         """Test that provider could be bound to different catalogs.""" |  | ||||||
|         p1 = self.catalog.p1 |  | ||||||
|         p2 = self.catalog.p2 |  | ||||||
| 
 |  | ||||||
|         catalog_a = catalogs.DynamicCatalog(pa1=p1, pa2=p2) |  | ||||||
|         catalog_b = catalogs.DynamicCatalog(pb1=p1, pb2=p2) |  | ||||||
| 
 |  | ||||||
|         self.assertTrue(self.catalog.is_provider_bound(p1)) |  | ||||||
|         self.assertTrue(catalog_a.is_provider_bound(p1)) |  | ||||||
|         self.assertTrue(catalog_b.is_provider_bound(p1)) |  | ||||||
|         self.assertEquals(self.catalog.get_provider_bind_name(p1), 'p1') |  | ||||||
|         self.assertEquals(catalog_a.get_provider_bind_name(p1), 'pa1') |  | ||||||
|         self.assertEquals(catalog_b.get_provider_bind_name(p1), 'pb1') |  | ||||||
| 
 |  | ||||||
|         self.assertTrue(self.catalog.is_provider_bound(p2)) |  | ||||||
|         self.assertTrue(catalog_a.is_provider_bound(p2)) |  | ||||||
|         self.assertTrue(catalog_b.is_provider_bound(p2)) |  | ||||||
|         self.assertEquals(self.catalog.get_provider_bind_name(p2), 'p2') |  | ||||||
|         self.assertEquals(catalog_a.get_provider_bind_name(p2), 'pa2') |  | ||||||
|         self.assertEquals(catalog_b.get_provider_bind_name(p2), 'pb2') |  | ||||||
| 
 |  | ||||||
|     def test_provider_rebinding_to_the_same_catalog(self): |  | ||||||
|         """Test provider rebinding to the same catalog.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             self.catalog.p3 = self.catalog.p1 |  | ||||||
| 
 |  | ||||||
|     def test_provider_binding_with_the_same_name(self): |  | ||||||
|         """Test binding of provider with the same name.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             self.catalog.bind_provider('p1', providers.Provider()) |  | ||||||
| 
 |  | ||||||
|     def test_get(self): |  | ||||||
|         """Test getting of providers using get() method.""" |  | ||||||
|         self.assertIs(self.catalog.get_provider('p1'), self.catalog.p1) |  | ||||||
|         self.assertIs(self.catalog.get_provider('p2'), self.catalog.p2) |  | ||||||
| 
 |  | ||||||
|     def test_get_undefined(self): |  | ||||||
|         """Test getting of undefined providers using get() method.""" |  | ||||||
|         with self.assertRaises(errors.UndefinedProviderError): |  | ||||||
|             self.catalog.get_provider('undefined') |  | ||||||
| 
 |  | ||||||
|         with self.assertRaises(errors.UndefinedProviderError): |  | ||||||
|             self.catalog.undefined |  | ||||||
| 
 |  | ||||||
|     def test_has_provider(self): |  | ||||||
|         """Test checks of providers availability in catalog.""" |  | ||||||
|         self.assertTrue(self.catalog.has_provider('p1')) |  | ||||||
|         self.assertTrue(self.catalog.has_provider('p2')) |  | ||||||
|         self.assertFalse(self.catalog.has_provider('undefined')) |  | ||||||
| 
 |  | ||||||
|     def test_filter_all_providers_by_type(self): |  | ||||||
|         """Test getting of all catalog providers of specific type.""" |  | ||||||
|         self.assertTrue(len(self.catalog.filter(providers.Provider)) == 2) |  | ||||||
|         self.assertTrue(len(self.catalog.filter(providers.Object)) == 0) |  | ||||||
| 
 |  | ||||||
|     def test_repr(self): |  | ||||||
|         """Test catalog representation.""" |  | ||||||
|         representation = repr(self.catalog) |  | ||||||
| 
 |  | ||||||
|         self.assertIn('dependency_injector.catalogs.dynamic.DynamicCatalog', |  | ||||||
|                       representation) |  | ||||||
|         self.assertIn('p1', representation) |  | ||||||
|         self.assertIn('p2', representation) |  | ||||||
|  | @ -1,142 +0,0 @@ | ||||||
| """Dependency injector catalogs overriding 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 OverrideTests(unittest.TestCase): |  | ||||||
|     """Catalog overriding and override decorator test cases.""" |  | ||||||
| 
 |  | ||||||
|     def tearDown(self): |  | ||||||
|         """Tear test environment down.""" |  | ||||||
|         CatalogA.reset_override() |  | ||||||
| 
 |  | ||||||
|     def test_overriding(self): |  | ||||||
|         """Test catalog overriding with another catalog.""" |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|             p11 = providers.Object(1) |  | ||||||
|             p12 = providers.Object(2) |  | ||||||
| 
 |  | ||||||
|         self.assertEqual(CatalogA.p11(), 1) |  | ||||||
|         self.assertEqual(CatalogA.p12(), 2) |  | ||||||
|         self.assertEqual(len(CatalogA.overridden_by), 1) |  | ||||||
| 
 |  | ||||||
|     def test_override_declarative_catalog_with_itself(self): |  | ||||||
|         """Test catalog overriding of declarative catalog with itself.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             CatalogA.override(CatalogA) |  | ||||||
| 
 |  | ||||||
|     def test_override_declarative_catalog_with_subclass(self): |  | ||||||
|         """Test catalog overriding of declarative catalog with subclass.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             CatalogB.override(CatalogA) |  | ||||||
| 
 |  | ||||||
|     def test_override_dynamic_catalog_with_itself(self): |  | ||||||
|         """Test catalog overriding of dynamic catalog with itself.""" |  | ||||||
|         catalog = catalogs.DynamicCatalog(p11=providers.Object(1), |  | ||||||
|                                           p12=providers.Object(2)) |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             catalog.override(catalog) |  | ||||||
| 
 |  | ||||||
|     def test_overriding_with_dynamic_catalog(self): |  | ||||||
|         """Test catalog overriding with another dynamic catalog.""" |  | ||||||
|         CatalogA.override(catalogs.DynamicCatalog(p11=providers.Object(1), |  | ||||||
|                                                   p12=providers.Object(2))) |  | ||||||
|         self.assertEqual(CatalogA.p11(), 1) |  | ||||||
|         self.assertEqual(CatalogA.p12(), 2) |  | ||||||
|         self.assertEqual(len(CatalogA.overridden_by), 1) |  | ||||||
| 
 |  | ||||||
|     def test_is_overridden(self): |  | ||||||
|         """Test catalog is_overridden property.""" |  | ||||||
|         self.assertFalse(CatalogA.is_overridden) |  | ||||||
| 
 |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|         self.assertTrue(CatalogA.is_overridden) |  | ||||||
| 
 |  | ||||||
|     def test_last_overriding(self): |  | ||||||
|         """Test catalog last_overriding property.""" |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog1(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog2(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|         self.assertIs(CatalogA.last_overriding, OverridingCatalog2) |  | ||||||
| 
 |  | ||||||
|     def test_last_overriding_on_not_overridden(self): |  | ||||||
|         """Test catalog last_overriding property on not overridden catalog.""" |  | ||||||
|         self.assertIsNone(CatalogA.last_overriding) |  | ||||||
| 
 |  | ||||||
|     def test_reset_last_overriding(self): |  | ||||||
|         """Test resetting last overriding catalog.""" |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog1(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|             p11 = providers.Object(1) |  | ||||||
|             p12 = providers.Object(2) |  | ||||||
| 
 |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog2(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|             p11 = providers.Object(3) |  | ||||||
|             p12 = providers.Object(4) |  | ||||||
| 
 |  | ||||||
|         CatalogA.reset_last_overriding() |  | ||||||
| 
 |  | ||||||
|         self.assertEqual(CatalogA.p11(), 1) |  | ||||||
|         self.assertEqual(CatalogA.p12(), 2) |  | ||||||
| 
 |  | ||||||
|     def test_reset_last_overriding_when_not_overridden(self): |  | ||||||
|         """Test resetting last overriding catalog when it is not overridden.""" |  | ||||||
|         with self.assertRaises(errors.Error): |  | ||||||
|             CatalogA.reset_last_overriding() |  | ||||||
| 
 |  | ||||||
|     def test_reset_override(self): |  | ||||||
|         """Test resetting all catalog overrides.""" |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog1(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|             p11 = providers.Object(1) |  | ||||||
|             p12 = providers.Object(2) |  | ||||||
| 
 |  | ||||||
|         @catalogs.override(CatalogA) |  | ||||||
|         class OverridingCatalog2(catalogs.DeclarativeCatalog): |  | ||||||
|             """Overriding catalog.""" |  | ||||||
| 
 |  | ||||||
|             p11 = providers.Object(3) |  | ||||||
|             p12 = providers.Object(4) |  | ||||||
| 
 |  | ||||||
|         CatalogA.reset_override() |  | ||||||
| 
 |  | ||||||
|         self.assertFalse(CatalogA.p11.is_overridden) |  | ||||||
|         self.assertFalse(CatalogA.p12.is_overridden) |  | ||||||
|  | @ -276,5 +276,162 @@ class DeclarativeContainerTests(unittest.TestCase): | ||||||
|         self.assertEqual(_Container1.p13(), 11) |         self.assertEqual(_Container1.p13(), 11) | ||||||
|         self.assertEqual(_Container2.p13(), 22) |         self.assertEqual(_Container2.p13(), 22) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | class DeclarativeContainerInstanceTests(unittest.TestCase): | ||||||
|  |     """Declarative container instance tests.""" | ||||||
|  | 
 | ||||||
|  |     def test_providers_attribute(self): | ||||||
|  |         """Test providers attribute.""" | ||||||
|  |         container_a1 = ContainerA() | ||||||
|  |         container_a2 = ContainerA() | ||||||
|  | 
 | ||||||
|  |         self.assertIsNot(container_a1.p11, container_a2.p11) | ||||||
|  |         self.assertIsNot(container_a1.p12, container_a2.p12) | ||||||
|  |         self.assertNotEqual(container_a1.providers, container_a2.providers) | ||||||
|  | 
 | ||||||
|  |     def test_set_get_del_providers(self): | ||||||
|  |         """Test set/get/del provider attributes.""" | ||||||
|  |         p13 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         container_a1 = ContainerA() | ||||||
|  |         container_a2 = ContainerA() | ||||||
|  | 
 | ||||||
|  |         container_a1.p13 = p13 | ||||||
|  |         container_a2.p13 = p13 | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11, | ||||||
|  |                                                     p12=ContainerA.p12)) | ||||||
|  |         self.assertEqual(ContainerA.cls_providers, dict(p11=ContainerA.p11, | ||||||
|  |                                                         p12=ContainerA.p12)) | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(container_a1.providers, dict(p11=container_a1.p11, | ||||||
|  |                                                       p12=container_a1.p12, | ||||||
|  |                                                       p13=p13)) | ||||||
|  |         self.assertEqual(container_a2.providers, dict(p11=container_a2.p11, | ||||||
|  |                                                       p12=container_a2.p12, | ||||||
|  |                                                       p13=p13)) | ||||||
|  | 
 | ||||||
|  |         del container_a1.p13 | ||||||
|  |         self.assertEqual(container_a1.providers, dict(p11=container_a1.p11, | ||||||
|  |                                                       p12=container_a1.p12)) | ||||||
|  | 
 | ||||||
|  |         del container_a2.p13 | ||||||
|  |         self.assertEqual(container_a2.providers, dict(p11=container_a2.p11, | ||||||
|  |                                                       p12=container_a2.p12)) | ||||||
|  | 
 | ||||||
|  |         del container_a1.p11 | ||||||
|  |         del container_a1.p12 | ||||||
|  |         self.assertEqual(container_a1.providers, dict()) | ||||||
|  |         self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11, | ||||||
|  |                                                     p12=ContainerA.p12)) | ||||||
|  | 
 | ||||||
|  |         del container_a2.p11 | ||||||
|  |         del container_a2.p12 | ||||||
|  |         self.assertEqual(container_a2.providers, dict()) | ||||||
|  |         self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11, | ||||||
|  |                                                     p12=ContainerA.p12)) | ||||||
|  | 
 | ||||||
|  |     def test_set_invalid_provider_type(self): | ||||||
|  |         """Test setting of invalid provider.""" | ||||||
|  |         container_a = ContainerA() | ||||||
|  |         container_a.provider_type = providers.Object | ||||||
|  | 
 | ||||||
|  |         with self.assertRaises(errors.Error): | ||||||
|  |             container_a.px = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         self.assertIs(ContainerA.provider_type, | ||||||
|  |                       containers.DeclarativeContainer.provider_type) | ||||||
|  | 
 | ||||||
|  |     def test_override(self): | ||||||
|  |         """Test override.""" | ||||||
|  |         class _Container(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         class _OverridingContainer1(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         class _OverridingContainer2(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  |             p12 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         container = _Container() | ||||||
|  |         overriding_container1 = _OverridingContainer1() | ||||||
|  |         overriding_container2 = _OverridingContainer2() | ||||||
|  | 
 | ||||||
|  |         container.override(overriding_container1) | ||||||
|  |         container.override(overriding_container2) | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(container.overridden_by, | ||||||
|  |                          (overriding_container1, | ||||||
|  |                           overriding_container2)) | ||||||
|  |         self.assertEqual(container.p11.overridden_by, | ||||||
|  |                          (overriding_container1.p11, | ||||||
|  |                           overriding_container2.p11)) | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(_Container.overridden_by, tuple()) | ||||||
|  |         self.assertEqual(_Container.p11.overridden_by, tuple()) | ||||||
|  | 
 | ||||||
|  |     def test_override_with_itself(self): | ||||||
|  |         """Test override container with itself.""" | ||||||
|  |         container = ContainerA() | ||||||
|  |         with self.assertRaises(errors.Error): | ||||||
|  |             container.override(container) | ||||||
|  | 
 | ||||||
|  |     def test_reset_last_overridding(self): | ||||||
|  |         """Test reset of last overriding.""" | ||||||
|  |         class _Container(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         class _OverridingContainer1(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         class _OverridingContainer2(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  |             p12 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         container = _Container() | ||||||
|  |         overriding_container1 = _OverridingContainer1() | ||||||
|  |         overriding_container2 = _OverridingContainer2() | ||||||
|  | 
 | ||||||
|  |         container.override(overriding_container1) | ||||||
|  |         container.override(overriding_container2) | ||||||
|  |         container.reset_last_overriding() | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(container.overridden_by, | ||||||
|  |                          (overriding_container1,)) | ||||||
|  |         self.assertEqual(container.p11.overridden_by, | ||||||
|  |                          (overriding_container1.p11,)) | ||||||
|  | 
 | ||||||
|  |     def test_reset_last_overridding_when_not_overridden(self): | ||||||
|  |         """Test reset of last overriding.""" | ||||||
|  |         container = ContainerA() | ||||||
|  | 
 | ||||||
|  |         with self.assertRaises(errors.Error): | ||||||
|  |             container.reset_last_overriding() | ||||||
|  | 
 | ||||||
|  |     def test_reset_override(self): | ||||||
|  |         """Test reset all overridings.""" | ||||||
|  |         class _Container(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         class _OverridingContainer1(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         class _OverridingContainer2(containers.DeclarativeContainer): | ||||||
|  |             p11 = providers.Provider() | ||||||
|  |             p12 = providers.Provider() | ||||||
|  | 
 | ||||||
|  |         container = _Container() | ||||||
|  |         overriding_container1 = _OverridingContainer1() | ||||||
|  |         overriding_container2 = _OverridingContainer2() | ||||||
|  | 
 | ||||||
|  |         container.override(overriding_container1) | ||||||
|  |         container.override(overriding_container2) | ||||||
|  |         container.reset_override() | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(container.overridden_by, tuple()) | ||||||
|  |         self.assertEqual(container.p11.overridden_by, tuple()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ import unittest2 as unittest | ||||||
| 
 | 
 | ||||||
| from dependency_injector import utils | from dependency_injector import utils | ||||||
| from dependency_injector import providers | from dependency_injector import providers | ||||||
| from dependency_injector import catalogs |  | ||||||
| from dependency_injector import errors | from dependency_injector import errors | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -69,56 +68,3 @@ class EnsureIsProviderTests(unittest.TestCase): | ||||||
|     def test_with_object(self): |     def test_with_object(self): | ||||||
|         """Test with object.""" |         """Test with object.""" | ||||||
|         self.assertRaises(errors.Error, utils.ensure_is_provider, object()) |         self.assertRaises(errors.Error, utils.ensure_is_provider, object()) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class IsCatalogTests(unittest.TestCase): |  | ||||||
|     """`is_catalog()` test cases.""" |  | ||||||
| 
 |  | ||||||
|     def test_with_declarative_catalog(self): |  | ||||||
|         """Test with class.""" |  | ||||||
|         self.assertTrue(utils.is_catalog(catalogs.DeclarativeCatalog)) |  | ||||||
| 
 |  | ||||||
|     def test_with_dynamic_catalog(self): |  | ||||||
|         """Test with class.""" |  | ||||||
|         self.assertTrue(utils.is_catalog(catalogs.DynamicCatalog())) |  | ||||||
| 
 |  | ||||||
|     def test_with_child_class(self): |  | ||||||
|         """Test with parent class.""" |  | ||||||
|         class Catalog(catalogs.DeclarativeCatalog): |  | ||||||
|             """Example catalog child class.""" |  | ||||||
| 
 |  | ||||||
|         self.assertTrue(utils.is_catalog(Catalog)) |  | ||||||
| 
 |  | ||||||
|     def test_with_string(self): |  | ||||||
|         """Test with string.""" |  | ||||||
|         self.assertFalse(utils.is_catalog('some_string')) |  | ||||||
| 
 |  | ||||||
|     def test_with_object(self): |  | ||||||
|         """Test with object.""" |  | ||||||
|         self.assertFalse(utils.is_catalog(object())) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class IsDynamicCatalogTests(unittest.TestCase): |  | ||||||
|     """`is_dynamic_catalog()` test cases.""" |  | ||||||
| 
 |  | ||||||
|     def test_with_declarative_catalog(self): |  | ||||||
|         """Test with declarative catalog.""" |  | ||||||
|         self.assertFalse(utils.is_dynamic_catalog(catalogs.DeclarativeCatalog)) |  | ||||||
| 
 |  | ||||||
|     def test_with_dynamic_catalog(self): |  | ||||||
|         """Test with dynamic catalog.""" |  | ||||||
|         self.assertTrue(utils.is_dynamic_catalog(catalogs.DynamicCatalog())) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class IsDeclarativeCatalogTests(unittest.TestCase): |  | ||||||
|     """`is_declarative_catalog()` test cases.""" |  | ||||||
| 
 |  | ||||||
|     def test_with_declarative_catalog(self): |  | ||||||
|         """Test with declarative catalog.""" |  | ||||||
|         self.assertTrue(utils.is_declarative_catalog( |  | ||||||
|             catalogs.DeclarativeCatalog)) |  | ||||||
| 
 |  | ||||||
|     def test_with_dynamic_catalog(self): |  | ||||||
|         """Test with dynamic catalog.""" |  | ||||||
|         self.assertFalse(utils.is_declarative_catalog( |  | ||||||
|             catalogs.DynamicCatalog())) |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user