Update docs for declarative catalogs

This commit is contained in:
Roman Mogilatov 2015-11-16 13:28:27 +02:00
parent dc79339cae
commit 9a5e8f4a5a
20 changed files with 176 additions and 59 deletions

View File

@ -330,7 +330,7 @@ class DeclarativeCatalogMetaClass(type):
@six.add_metaclass(DeclarativeCatalogMetaClass) @six.add_metaclass(DeclarativeCatalogMetaClass)
class DeclarativeCatalog(object): class DeclarativeCatalog(object):
"""Declarative catalog catalog of providers. """Declarative catalog of providers.
``DeclarativeCatalog`` is a catalog of providers that could be defined in ``DeclarativeCatalog`` is a catalog of providers that could be defined in
declarative manner. It should cover most of the cases when list of declarative manner. It should cover most of the cases when list of
@ -347,25 +347,27 @@ class DeclarativeCatalog(object):
name = str() name = str()
"""Catalog's name. """Catalog's name.
By default it is catalog's module + class names.
:type: str :type: str
""" """
cls_providers = dict() cls_providers = dict()
"""Read-only dictionary of current catalog providers. """Read-only dictionary of current catalog providers.
:type: dict[str, dependency_injector.Provider] :type: dict[str, :py:class:`dependency_injector.providers.Provider`]
""" """
inherited_providers = dict() inherited_providers = dict()
"""Read-only dictionary of inherited providers. """Read-only dictionary of inherited providers.
:type: dict[str, dependency_injector.Provider] :type: dict[str, :py:class:`dependency_injector.providers.Provider`]
""" """
providers = dict() providers = dict()
"""Read-only dictionary of all providers. """Read-only dictionary of all providers.
:type: dict[str, dependency_injector.Provider] :type: dict[str, :py:class:`dependency_injector.providers.Provider`]
""" """
overridden_by = tuple() overridden_by = tuple()
@ -384,8 +386,8 @@ class DeclarativeCatalog(object):
last_overriding = None last_overriding = None
"""Read-only reference to the last overriding catalog, if any. """Read-only reference to the last overriding catalog, if any.
:type: dependency_injector.DeclarativeCatalog | :type: :py:class:`dependency_injector.catalogs.DeclarativeCatalog` |
dependency_injector.DynamicCatalog :py:class:`dependency_injector.catalogs.DynamicCatalog` | None
""" """
_catalog = DynamicCatalog _catalog = DynamicCatalog
@ -396,8 +398,8 @@ class DeclarativeCatalog(object):
def is_bundle_owner(cls, bundle): def is_bundle_owner(cls, bundle):
"""Check if catalog is bundle owner. """Check if catalog is bundle owner.
:param bundle: Catalog's bundle :param bundle: Catalog's bundle instance
:type bundle: dependency_injector.CatalogBundle :type bundle: :py:class:`dependency_injector.catalogs.CatalogBundle`
:rtype: bool :rtype: bool
""" """
@ -408,9 +410,9 @@ class DeclarativeCatalog(object):
"""Return provider's name in catalog. """Return provider's name in catalog.
:param provider: Provider instance :param provider: Provider instance
:type provider: dependency_injector.Provider :type provider: :py:class:`dependency_injector.providers.Provider`
:raise: dependency_injector.UndefinedProviderError :raise: :py:class:`dependency_injector.errors.UndefinedProviderError`
:return: Provider's name :return: Provider's name
:rtype: str :rtype: str
@ -422,7 +424,7 @@ class DeclarativeCatalog(object):
"""Check if provider is bound to the catalog. """Check if provider is bound to the catalog.
:param provider: Provider instance :param provider: Provider instance
:type provider: dependency_injector.Provider :type provider: :py:class:`dependency_injector.providers.Provider`
:rtype: bool :rtype: bool
""" """
@ -433,7 +435,7 @@ class DeclarativeCatalog(object):
"""Return dict of providers, that are instance of provided type. """Return dict of providers, that are instance of provided type.
:param provider_type: Provider type :param provider_type: Provider type
:type provider_type: dependency_injector.Provider :type provider: :py:class:`dependency_injector.providers.Provider`
""" """
return cls._catalog.filter(provider_type) return cls._catalog.filter(provider_type)
@ -442,8 +444,9 @@ class DeclarativeCatalog(object):
"""Override current catalog providers by overriding catalog providers. """Override current catalog providers by overriding catalog providers.
:param overriding: Overriding catalog :param overriding: Overriding catalog
:type overriding: dependency_injector.DeclarativeCatalog | :type overriding:
dependency_injector.DynamicCatalog :py:class:`dependency_injector.catalogs.DeclarativeCatalog` |
:py:class:`dependency_injector.catalogs.DynamicCatalog`
:rtype: None :rtype: None
""" """
@ -472,13 +475,15 @@ class DeclarativeCatalog(object):
:param name: Provider's name :param name: Provider's name
:type name: str :type name: str
:raise: dependency_injector.UndefinedProviderError :raise: :py:class:`dependency_injector.errors.UndefinedProviderError`
:return: Provider with specified name :return: Provider with specified name
:rtype: dependency_injector.providers.Provider :rtype: :py:class:`dependency_injector.providers.Provider`
""" """
return cls._catalog.get_provider(name) return cls._catalog.get_provider(name)
get = get_provider # Backward compatibility for versions < 0.11.*
@classmethod @classmethod
def bind_provider(cls, name, provider): def bind_provider(cls, name, provider):
"""Bind provider to catalog with specified name. """Bind provider to catalog with specified name.
@ -487,9 +492,9 @@ class DeclarativeCatalog(object):
:type name: str :type name: str
:param provider: Provider instance :param provider: Provider instance
:type provider: dependency_injector.Provider :type provider: :py:class:`dependency_injector.providers.Provider`
:raise: dependency_injector.Error :raise: :py:class:`dependency_injector.errors.Error`
:rtype: None :rtype: None
""" """
@ -501,9 +506,10 @@ class DeclarativeCatalog(object):
:param providers: Dictionary of providers, where key is a name :param providers: Dictionary of providers, where key is a name
and value is a provider and value is a provider
:type providers: dict[str, dependency_injector.Provider] :type providers:
dict[str, :py:class:`dependency_injector.providers.Provider`]
:raise: dependency_injector.Error :raise: :py:class:`dependency_injector.errors.Error`
:rtype: None :rtype: None
""" """
@ -521,6 +527,8 @@ class DeclarativeCatalog(object):
""" """
return hasattr(cls, name) return hasattr(cls, name)
has = has_provider # Backward compatibility for versions < 0.11.*
@classmethod @classmethod
def unbind_provider(cls, name): def unbind_provider(cls, name):
"""Remove provider binding. """Remove provider binding.
@ -532,8 +540,48 @@ class DeclarativeCatalog(object):
""" """
delattr(cls, name) delattr(cls, name)
get = get_provider # Backward compatibility for versions < 0.11.* @classmethod
has = has_provider # Backward compatibility for versions < 0.11.* def __getattr__(cls, name):
"""Return provider with specified name or raise en error.
:param name: Attribute's name
:type name: str
:raise: :py:class:`dependency_injector.errors.UndefinedProviderError`
"""
raise NotImplementedError('Implementated in metaclass')
@classmethod
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
"""
raise NotImplementedError('Implementated in metaclass')
@classmethod
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
"""
raise NotImplementedError('Implementated in metaclass')
# Backward compatibility for versions < 0.11.* # Backward compatibility for versions < 0.11.*

View File

@ -39,7 +39,7 @@ class Injection(object):
return self.injectable return self.injectable
class NamedInjection(Injection): class _NamedInjection(Injection):
"""Base class of named injections.""" """Base class of named injections."""
__slots__ = ('name',) __slots__ = ('name',)
@ -47,7 +47,7 @@ class NamedInjection(Injection):
def __init__(self, name, injectable): def __init__(self, name, injectable):
"""Initializer.""" """Initializer."""
self.name = name self.name = name
super(NamedInjection, self).__init__(injectable) super(_NamedInjection, self).__init__(injectable)
class Arg(Injection): class Arg(Injection):
@ -56,19 +56,19 @@ class Arg(Injection):
__IS_ARG_INJECTION__ = True __IS_ARG_INJECTION__ = True
class KwArg(NamedInjection): class KwArg(_NamedInjection):
"""Keyword argument injection.""" """Keyword argument injection."""
__IS_KWARG_INJECTION__ = True __IS_KWARG_INJECTION__ = True
class Attribute(NamedInjection): class Attribute(_NamedInjection):
"""Attribute injection.""" """Attribute injection."""
__IS_ATTRIBUTE_INJECTION__ = True __IS_ATTRIBUTE_INJECTION__ = True
class Method(NamedInjection): class Method(_NamedInjection):
"""Method injection.""" """Method injection."""
__IS_METHOD_INJECTION__ = True __IS_METHOD_INJECTION__ = True

View File

@ -3,5 +3,5 @@
.. automodule:: dependency_injector.catalogs .. automodule:: dependency_injector.catalogs
:members: :members:
:special-members:
:member-order: bysource :member-order: bysource
:special-members:

View File

@ -1,12 +1,11 @@
API API Documentation
=== =================
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
top_level
providers providers
injections
catalogs catalogs
errors
utils utils
errors

7
docs/api/injections.rst Normal file
View File

@ -0,0 +1,7 @@
``dependency_injector.injections``
----------------------------------
.. automodule:: dependency_injector.injections
:members:
:member-order: bysource
:inherited-members:

View File

@ -3,6 +3,4 @@
.. automodule:: dependency_injector.providers .. automodule:: dependency_injector.providers
:members: :members:
:special-members:
:private-members:
:member-order: bysource :member-order: bysource

View File

@ -2,5 +2,3 @@
----------------------- -----------------------
.. automodule:: dependency_injector .. automodule:: dependency_injector
:members:
:special-members:

View File

@ -3,3 +3,4 @@
.. automodule:: dependency_injector.utils .. automodule:: dependency_injector.utils
:members: :members:
:member-order: bysource

View File

@ -1,17 +1,27 @@
Declarative catalogs Declarative catalogs
-------------------- --------------------
:py:class:`dependency_injector.catalogs.DeclarativeCatalog` is a catalog of .. module:: dependency_injector.catalogs
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 :py:class:`DeclarativeCatalog` is a catalog of providers that could be
deterministic (catalog will not change its structure in runtime). 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).
Declarative catalogs have to extend base declarative catalog class - Declarative catalogs have to extend base declarative catalog class -
:py:class:`dependency_injector.catalogs.DeclarativeCatalog`. :py:class:`dependency_injector.catalogs.DeclarativeCatalog`.
Providers have to be defined like catalog's class attributes. Every provider in Declarative catalog's providers have to be defined like catalog's class
catalog has name. This name should follow ``some_provider`` convention, attributes. Every provider in catalog has name. This name should follow
that is standard naming convention for attribute names in Python. ``some_provider`` convention, that is standard naming convention for
attribute names in Python.
.. note::
Declarative catalogs have several features that could be useful
for some kind of operations on catalog's providers, please visit API
documentation for getting full list of features -
:py:class:`dependency_injector.catalogs.DeclarativeCatalog`.
.. note:: .. note::
@ -31,16 +41,20 @@ Here is an simple example of declarative catalog with several factories:
.. literalinclude:: ../../examples/catalogs/declarative.py .. literalinclude:: ../../examples/catalogs/declarative.py
:language: python :language: python
:py:class:`dependency_injector.catalogs.DeclarativeCatalog` has several Example of declarative catalogs inheritance:
features that could be useful for some kind of operations on catalog's
providers (please visit API docs for getting full list of feautes -
:py:class:`dependency_injector.catalogs.DeclarativeCatalog`):
Example: .. image:: /images/catalogs/declarative_inheritance.png
.. image:: /images/catalogs/declarative_api.png
:width: 100% :width: 100%
:align: center :align: center
.. literalinclude:: ../../examples/catalogs/declarative_api.py .. literalinclude:: ../../examples/catalogs/declarative_inheritance.py
:language: python
Example of declarative catalog's provider injections:
.. image:: /images/catalogs/declarative_injections.png
:width: 100%
:align: center
.. literalinclude:: ../../examples/catalogs/declarative_injections.py
:language: python :language: python

View File

@ -1,2 +1,4 @@
Dynamic catalogs Dynamic catalogs
---------------- ----------------
.. module:: dependency_injector.catalogs

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@ -1,4 +1,4 @@
"""Declarative catalog example.""" """Declarative catalog simple example."""
from dependency_injector import catalogs from dependency_injector import catalogs
from dependency_injector import providers from dependency_injector import providers

View File

@ -1,4 +1,4 @@
"""Declarative catalog API example.""" """Declarative catalogs inheritance example."""
from dependency_injector import catalogs from dependency_injector import catalogs
from dependency_injector import providers from dependency_injector import providers

View File

@ -0,0 +1,50 @@
"""Declarative catalog's provider injections example."""
import sqlite3
from dependency_injector import catalogs
from dependency_injector import providers
class UsersService(object):
"""Users service, that has dependency on database."""
def __init__(self, db):
"""Initializer."""
self.db = db
class AuthService(object):
"""Auth service, that has dependencies on users service and database."""
def __init__(self, db, users_service):
"""Initializer."""
self.db = db
self.users_service = users_service
class Services(catalogs.DeclarativeCatalog):
"""Catalog of service providers."""
database = providers.Singleton(sqlite3.connect, ':memory:')
""":type: providers.Provider -> sqlite3.Connection"""
users = providers.Factory(UsersService,
db=database)
""":type: providers.Provider -> UsersService"""
auth = providers.Factory(AuthService,
db=database,
users_service=users)
""":type: providers.Provider -> AuthService"""
# Retrieving catalog providers:
users_service = Services.users()
auth_service = Services.auth()
# Making some asserts:
assert users_service.db is auth_service.db is Services.database()
assert isinstance(auth_service.users_service, UsersService)
assert users_service is not Services.users()
assert auth_service is not Services.auth()