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): | ||||
|     """Declarative inversion of control container meta class.""" | ||||
| 
 | ||||
|  | @ -20,7 +100,7 @@ class DeclarativeContainerMetaClass(type): | |||
| 
 | ||||
|         inherited_providers = tuple((name, provider) | ||||
|                                     for base in bases if utils.is_container( | ||||
|                                         base) | ||||
|                                         base) and base is not DynamicContainer | ||||
|                                     for name, provider in six.iteritems( | ||||
|                                         base.cls_providers)) | ||||
| 
 | ||||
|  | @ -70,9 +150,20 @@ class DeclarativeContainer(object): | |||
|     providers = dict() | ||||
|     cls_providers = dict() | ||||
|     inherited_providers = dict() | ||||
| 
 | ||||
|     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 | ||||
|     def override(cls, overriding): | ||||
|         """Override current container by overriding container. | ||||
|  | @ -163,7 +254,7 @@ def copy(container): | |||
|             else: | ||||
|                 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): | ||||
|             setattr(copied_container, name, provider) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| """Utils module.""" | ||||
| 
 | ||||
| import sys | ||||
| import copy | ||||
| import copy as _copy | ||||
| import types | ||||
| import threading | ||||
| 
 | ||||
|  | @ -23,9 +23,9 @@ else:  # pragma: no cover | |||
|     _OBJECT_INIT = None | ||||
| 
 | ||||
| if six.PY2:  # pragma: no cover | ||||
|     copy._deepcopy_dispatch[types.MethodType] = \ | ||||
|     _copy._deepcopy_dispatch[types.MethodType] = \ | ||||
|         lambda obj, memo: type(obj)(obj.im_func, | ||||
|                                     copy.deepcopy(obj.im_self, memo), | ||||
|                                     _copy.deepcopy(obj.im_self, memo), | ||||
|                                     obj.im_class) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -71,40 +71,6 @@ def is_container(instance): | |||
|             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): | ||||
|     """Return string representation of provider. | ||||
| 
 | ||||
|  | @ -142,6 +108,6 @@ def fetch_cls_init(cls): | |||
|         return cls_init | ||||
| 
 | ||||
| 
 | ||||
| def _copy_providers(providers, memo=None): | ||||
|     """Make full copy of providers dictionary.""" | ||||
|     return copy.deepcopy(providers, memo) | ||||
| def deepcopy(instance, memo=None): | ||||
|     """Make full copy of instance.""" | ||||
|     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', | ||||
|       license='BSD New', | ||||
|       packages=['dependency_injector', | ||||
|                 'dependency_injector.catalogs', | ||||
|                 'dependency_injector.providers'], | ||||
|       platforms=['any'], | ||||
|       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(_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__': | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import unittest2 as unittest | |||
| 
 | ||||
| from dependency_injector import utils | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import catalogs | ||||
| from dependency_injector import errors | ||||
| 
 | ||||
| 
 | ||||
|  | @ -69,56 +68,3 @@ class EnsureIsProviderTests(unittest.TestCase): | |||
|     def test_with_object(self): | ||||
|         """Test with 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