diff --git a/dependency_injector/catalogs.py b/dependency_injector/catalogs.py index 976912f8..e2aab1e0 100644 --- a/dependency_injector/catalogs.py +++ b/dependency_injector/catalogs.py @@ -220,7 +220,7 @@ class DynamicCatalog(object): @property def is_overridden(self): - """Read-only property that is set to True if catalog is overridden. + """Read-only property that is set to ``True`` if catalog is overridden. :rtype: bool """ @@ -464,7 +464,7 @@ class DeclarativeCatalogMetaClass(type): @property def is_overridden(cls): - """Read-only property that is set to True if catalog is overridden. + """Read-only property that is set to ``True`` if catalog is overridden. :rtype: bool """ @@ -585,7 +585,7 @@ class DeclarativeCatalog(object): """ is_overridden = bool - """Read-only property that is set to True if catalog is overridden. + """Read-only property that is set to ``True`` if catalog is overridden. :type: bool """ @@ -798,7 +798,7 @@ AbstractCatalog = DeclarativeCatalog def override(catalog): - """Catalog overriding decorator. + """:py:class:`DeclarativeCatalog` overriding decorator. :param catalog: Catalog that should be overridden by decorated catalog. :type catalog: :py:class:`dependency_injector.catalogs.DeclarativeCatalog` diff --git a/docs/catalogs/overriding.rst b/docs/catalogs/overriding.rst index feb6dfa5..7403d400 100644 --- a/docs/catalogs/overriding.rst +++ b/docs/catalogs/overriding.rst @@ -1,35 +1,49 @@ Overriding of catalogs ---------------------- +.. module:: dependency_injector.catalogs + Catalogs can be overridden by other catalogs. This, actually, means that all of the providers from overriding catalog will override providers with the same names in overridden catalog. -There are two ways to override catalog by another catalog: +There are two ways to override :py:class:`DeclarativeCatalog` with another +catalog: -- Use ``di.DeclarativeCatalog.override(AnotherCatalog)`` method. -- Use ``@di.override(AnotherCatalog)`` class decorator. +- Use :py:meth:`DeclarativeCatalog.override` method. +- Use :py:func:`override` class decorator. -Example of overriding catalog using ``di.DeclarativeCatalog.override()`` +Example of overriding catalog using :py:meth:`DeclarativeCatalog.override` method: -.. literalinclude:: ../../examples/catalogs/override.py +.. literalinclude:: ../../examples/catalogs/override_declarative.py :language: python -Example of overriding catalog using ``@di.override()`` decorator: +Example of overriding catalog using :py:func:`override` decorator: -.. literalinclude:: ../../examples/catalogs/override_decorator.py +.. literalinclude:: ../../examples/catalogs/override_declarative_decorator.py :language: python -Also there are several useful methods and properties that help to work with -catalog overridings: +Also there are several useful :py:class:`DeclarativeCatalog` methods and +properties that help to work with catalog overridings: -- ``di.DeclarativeCatalog.is_overridden`` - read-only, evaluated in runtime, - property that is set to True if catalog is overridden. -- ``di.DeclarativeCatalog.last_overriding`` - reference to the last overriding - catalog, if any. -- ``di.DeclarativeCatalog.overridden_by`` - tuple of all overriding catalogs. -- ``di.DeclarativeCatalog.reset_last_overriding()`` - reset last overriding - catalog. -- ``di.DeclarativeCatalog.reset_override()`` - reset all overridings for all - catalog providers. +- :py:attr:`DeclarativeCatalog.is_overridden` - read-only property that is set + to ``True`` if catalog is overridden. +- :py:attr:`DeclarativeCatalog.last_overriding` - read-only reference to + the last overriding catalog, if any. +- :py:attr:`DeclarativeCatalog.overridden_by` - tuple of all overriding + catalogs. +- :py:meth:`DeclarativeCatalog.reset_last_overriding()` - reset last + overriding catalog. +- :py:meth:`DeclarativeCatalog.reset_override()` - reset all overridings for + all catalog providers. + +:py:class:`DynamicCatalog` has exactly the same functionality, except of +:py:func:`override` decorator. Also :py:class:`DynamicCatalog` can override +:py:class:`DeclarativeCatalog` and vise versa. + +Example of overriding :py:class:`DeclarativeCatalog` by +:py:class:`DynamicCatalog`: + +.. literalinclude:: ../../examples/catalogs/override_declarative_by_dynamic.py + :language: python diff --git a/examples/catalogs/override.py b/examples/catalogs/override.py deleted file mode 100644 index 5f5648c4..00000000 --- a/examples/catalogs/override.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Catalog overriding example.""" - -import collections -import dependency_injector as di - - -# Creating some example classes: -Object1 = collections.namedtuple('Object1', ['arg1', 'arg2']) -Object2 = collections.namedtuple('Object2', ['object1']) -ExtendedObject2 = collections.namedtuple('ExtendedObject2', []) - - -class Catalog(di.DeclarativeCatalog): - """Providers catalog.""" - - object1_factory = di.Factory(Object1, - arg1=1, - arg2=2) - """:type: di.Provider -> Object1""" - - object2_factory = di.Factory(Object2, - object1=object1_factory) - """:type: di.Provider -> Object2""" - - -class AnotherCatalog(di.DeclarativeCatalog): - """Another providers catalog.""" - - object2_factory = di.Factory(ExtendedObject2) - """:type: di.Provider -> ExtendedObject2""" - - -# Overriding `Catalog` with `AnotherCatalog`: -Catalog.override(AnotherCatalog) - -# Creating some objects using overridden catalog: -object2_1 = Catalog.object2_factory() -object2_2 = Catalog.object2_factory() - -# Making some asserts: -assert object2_1 is not object2_2 - -assert isinstance(object2_1, ExtendedObject2) -assert isinstance(object2_2, ExtendedObject2) diff --git a/examples/catalogs/override_declarative.py b/examples/catalogs/override_declarative.py new file mode 100644 index 00000000..825ffe91 --- /dev/null +++ b/examples/catalogs/override_declarative.py @@ -0,0 +1,48 @@ +"""Declarative catalog overriding example.""" + +import collections + +from dependency_injector import catalogs +from dependency_injector import providers + + +# Creating some example classes: +Object1 = collections.namedtuple('Object1', ['arg1', 'arg2']) +Object2 = collections.namedtuple('Object2', ['object1']) +ExtendedObject2 = collections.namedtuple('ExtendedObject2', []) + + +class Catalog(catalogs.DeclarativeCatalog): + """Catalog of some providers.""" + + object1_factory = providers.Factory(Object1, + arg1=1, + arg2=2) + """:type: providers.Provider -> Object1""" + + object2_factory = providers.Factory(Object2, + object1=object1_factory) + """:type: providers.Provider -> Object2""" + + +class AnotherCatalog(catalogs.DeclarativeCatalog): + """Overriding catalog.""" + + object2_factory = providers.Factory(ExtendedObject2) + """:type: providers.Provider -> ExtendedObject2""" + + +# Overriding `Catalog` with `AnotherCatalog`: +Catalog.override(AnotherCatalog) + +# Creating some objects using overridden catalog: +object2_1 = Catalog.object2_factory() +object2_2 = Catalog.object2_factory() + +# Making some asserts: +assert Catalog.is_overridden + +assert object2_1 is not object2_2 + +assert isinstance(object2_1, ExtendedObject2) +assert isinstance(object2_2, ExtendedObject2) diff --git a/examples/catalogs/override_declarative_by_dynamic.py b/examples/catalogs/override_declarative_by_dynamic.py new file mode 100644 index 00000000..8886a271 --- /dev/null +++ b/examples/catalogs/override_declarative_by_dynamic.py @@ -0,0 +1,43 @@ +"""Declarative catalog overriding by dynamic catalog example.""" + +import collections + +from dependency_injector import catalogs +from dependency_injector import providers + + +# Creating some example classes: +Object1 = collections.namedtuple('Object1', ['arg1', 'arg2']) +Object2 = collections.namedtuple('Object2', ['object1']) +ExtendedObject2 = collections.namedtuple('ExtendedObject2', []) + + +class Catalog(catalogs.DeclarativeCatalog): + """Catalog of some providers.""" + + object1_factory = providers.Factory(Object1, + arg1=1, + arg2=2) + """:type: providers.Provider -> Object1""" + + object2_factory = providers.Factory(Object2, + object1=object1_factory) + """:type: providers.Provider -> Object2""" + + +# Overriding `Catalog` with some `DynamicCatalog` instance: +overriding_catalog = catalogs.DynamicCatalog( + object2_factory=providers.Factory(ExtendedObject2)) +Catalog.override(overriding_catalog) + +# Creating some objects using overridden catalog: +object2_1 = Catalog.object2_factory() +object2_2 = Catalog.object2_factory() + +# Making some asserts: +assert Catalog.is_overridden + +assert object2_1 is not object2_2 + +assert isinstance(object2_1, ExtendedObject2) +assert isinstance(object2_2, ExtendedObject2) diff --git a/examples/catalogs/override_declarative_decorator.py b/examples/catalogs/override_declarative_decorator.py new file mode 100644 index 00000000..2dcbc828 --- /dev/null +++ b/examples/catalogs/override_declarative_decorator.py @@ -0,0 +1,46 @@ +"""Declarative catalog overriding using `@override()` decorator example.""" + +import collections + +from dependency_injector import catalogs +from dependency_injector import providers + +# Creating some example classes: +Object1 = collections.namedtuple('Object1', ['arg1', 'arg2']) +Object2 = collections.namedtuple('Object2', ['object1']) +ExtendedObject2 = collections.namedtuple('ExtendedObject2', []) + + +class Catalog(catalogs.DeclarativeCatalog): + """Catalog of some providers.""" + + object1_factory = providers.Factory(Object1, + arg1=1, + arg2=2) + """:type: providers.Provider -> Object1""" + + object2_factory = providers.Factory(Object2, + object1=object1_factory) + """:type: providers.Provider -> Object2""" + + +# Overriding `Catalog` with `AnotherCatalog`: +@catalogs.override(Catalog) +class AnotherCatalog(catalogs.DeclarativeCatalog): + """Overriding catalog.""" + + object2_factory = providers.Factory(ExtendedObject2) + """:type: providers.Provider -> ExtendedObject2""" + + +# Creating some objects using overridden catalog: +object2_1 = Catalog.object2_factory() +object2_2 = Catalog.object2_factory() + +# Making some asserts: +assert Catalog.is_overridden + +assert object2_1 is not object2_2 + +assert isinstance(object2_1, ExtendedObject2) +assert isinstance(object2_2, ExtendedObject2) diff --git a/examples/catalogs/override_decorator.py b/examples/catalogs/override_decorator.py deleted file mode 100644 index 423d95e1..00000000 --- a/examples/catalogs/override_decorator.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Catalog overriding using `@di.override()` decorator example.""" - -import collections -import dependency_injector as di - - -# Creating some example classes: -Object1 = collections.namedtuple('Object1', ['arg1', 'arg2']) -Object2 = collections.namedtuple('Object2', ['object1']) -ExtendedObject2 = collections.namedtuple('ExtendedObject2', []) - - -class Catalog(di.DeclarativeCatalog): - """Providers catalog.""" - - object1_factory = di.Factory(Object1, - arg1=1, - arg2=2) - """:type: di.Provider -> Object1""" - - object2_factory = di.Factory(Object2, - object1=object1_factory) - """:type: di.Provider -> Object2""" - - -# Overriding `Catalog` with `AnotherCatalog`: -@di.override(Catalog) -class AnotherCatalog(di.DeclarativeCatalog): - """Another providers catalog.""" - - object2_factory = di.Factory(ExtendedObject2) - """:type: di.Provider -> ExtendedObject2""" - - -# Creating some objects using overridden catalog: -object2_1 = Catalog.object2_factory() -object2_2 = Catalog.object2_factory() - -# Making some asserts: -assert object2_1 is not object2_2 - -assert isinstance(object2_1, ExtendedObject2) -assert isinstance(object2_2, ExtendedObject2)