Update catalog bundles docs

This commit is contained in:
Roman Mogilatov 2015-11-20 13:46:57 +02:00
parent b29387abdd
commit e55f6ed212
7 changed files with 93 additions and 55 deletions

View File

@ -13,7 +13,23 @@ from .utils import ensure_is_catalog_bundle
@six.python_2_unicode_compatible
class CatalogBundle(object):
"""Bundle of catalog providers."""
"""Bundle of catalog providers.
:py:class:`CatalogBundle` is a frozen, limited collection of catalog
providers. While catalog could be used as a centralized place for
particular providers group, such bundles of catalog providers can be used
for creating several frozen, limited scopes that could be passed to
different subsystems.
:py:class:`CatalogBundle` has API's parity with catalogs
(:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) in terms of
retrieving the providers, but it is "frozen" in terms of modification
provider's list.
:py:class:`CatalogBundle` is considered to be dependable on catalogs
(:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) entity by
its design.
"""
catalog = None
"""Bundle's catalog.
@ -25,6 +41,16 @@ class CatalogBundle(object):
__IS_CATALOG_BUNDLE__ = True
__slots__ = ('providers', '__dict__')
@classmethod
def sub_cls_factory(cls, catalog):
"""Create bundle subclass for catalog.
:return: Subclass of
:py:class:`dependency_injector.catalogs.CatalogBundle`
:rtype: :py:class:`dependency_injector.catalogs.CatalogBundle`
"""
return type('BundleSubclass', (cls,), dict(catalog=catalog))
def __init__(self, *providers):
"""Initializer.
@ -44,16 +70,6 @@ class CatalogBundle(object):
self.__dict__.update(self.providers)
super(CatalogBundle, self).__init__()
@classmethod
def sub_cls_factory(cls, catalog):
"""Create bundle subclass for catalog.
:return: Subclass of
:py:class:`dependency_injector.catalogs.CatalogBundle`
:rtype: :py:class:`dependency_injector.catalogs.CatalogBundle`
"""
return type('BundleSubclass', (cls,), dict(catalog=catalog))
def get_provider(self, name):
"""Return provider with specified name or raise an error.
@ -523,10 +539,10 @@ class DeclarativeCatalogMetaClass(type):
class DeclarativeCatalog(object):
"""Declarative catalog of providers.
``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).
: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).
"""
Bundle = CatalogBundle

View File

@ -1,23 +1,43 @@
Catalog provider bundles
------------------------
``di.DeclarativeCatalog.Bundle`` is a limited collection of catalog providers.
While catalog could be used as a centralized place for particular providers
group, such bundles of catalog providers can be used for creating several
limited scopes that could be passed to different subsystems.
.. module:: dependency_injector.catalogs
``di.DeclarativeCatalog.Bundle`` has exactly the same API as
``di.DeclarativeCatalog`` except of the limitations on getting providers.
:py:class:`CatalogBundle` is a frozen, limited collection of catalog
providers. While catalog could be used as a centralized place for
particular providers group, such bundles of catalog providers can be used
for creating several frozen, limited scopes that could be passed to different
subsystems.
Each ``di.DeclarativeCatalog`` has a reference to its bundle class -
``di.DeclarativeCatalog.Bundle``. For example, if some concrete catalog has name
``SomeCatalog``, then its bundle class could be reached as
``SomeCatalog.Bundle``.
:py:class:`CatalogBundle` has API's parity with catalogs
(:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) in terms of
retrieving the providers, but it is "frozen" in terms of modification
provider's list.
``di.DeclarativeCatalog.Bundle`` expects to get the list of its catalog providers
:py:class:`CatalogBundle` is considered to be dependable on catalogs
(:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`) entity by
its design.
Each catalog (:py:class:`DeclarativeCatalog` or :py:class:`DynamicCatalog`)
has a reference to its bundle class - :py:attr:`DeclarativeCatalog.Bundle`
(or :py:attr:`DynamicCatalog.Bundle` consequently). For example, subclass of
:py:class:`CatalogBundle` for some concrete declarative catalog
``SomeCatalog`` could be reached as ``SomeCatalog.Bundle``.
:py:class:`CatalogBundle` expects to get the list of its catalog providers
as positional arguments and will limit the scope of created bundle to this
list.
.. note::
Some notes about :py:class:`CatalogBundle` design.
Design and syntax of :py:class:`CatalogBundle` was developed with the idea
of keeping full functionalities of type-hinting and introspection of
modern IDE's. This design came from some practical experience of using
:py:class:`CatalogBundle` and considered to be the most comfortable for
developer.
Example:
.. image:: /images/catalogs/bundles.png

View File

@ -3,10 +3,10 @@ Declarative catalogs
.. module:: dependency_injector.catalogs
: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).
: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).
Declarative catalogs have to extend base declarative catalog class -
:py:class:`dependency_injector.catalogs.DeclarativeCatalog`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

View File

@ -1,38 +1,40 @@
"""Catalog bundles example."""
import dependency_injector as di
from dependency_injector import catalogs
from dependency_injector import providers
from dependency_injector import errors
import services
import views
# Declaring services catalog:
class Services(di.DeclarativeCatalog):
class Services(catalogs.DeclarativeCatalog):
"""Example catalog of service providers."""
users = di.Factory(services.UsersService)
""":type: di.Provider -> services.UsersService"""
users = providers.Factory(services.Users)
""":type: providers.Provider -> services.Users"""
auth = di.Factory(services.AuthService)
""":type: di.Provider -> services.AuthService"""
auth = providers.Factory(services.Auth)
""":type: providers.Provider -> services.Auth"""
photos = di.Factory(services.PhotosService)
""":type: di.Provider -> services.PhotosService"""
photos = providers.Factory(services.Photos)
""":type: providers.Provider -> services.Photos"""
# Declaring views catalog:
class Views(di.DeclarativeCatalog):
class Views(catalogs.DeclarativeCatalog):
"""Example catalog of web views."""
auth = di.Factory(views.AuthView,
services=Services.Bundle(Services.users,
Services.auth))
""":type: di.Provider -> views.AuthView"""
auth = providers.Factory(views.Auth,
services=Services.Bundle(Services.users,
Services.auth))
""":type: providers.Provider -> views.Auth"""
photos = di.Factory(views.PhotosView,
services=Services.Bundle(Services.users,
Services.photos))
""":type: di.Provider -> views.PhotosView"""
photos = providers.Factory(views.Photos,
services=Services.Bundle(Services.users,
Services.photos))
""":type: providers.Provider -> views.Photos"""
# Creating example views:
@ -47,7 +49,7 @@ assert auth_view.services.users is Services.users
assert auth_view.services.auth is Services.auth
try:
auth_view.services.photos
except di.Error:
except errors.Error:
# `photos` service provider is not in scope of `auth_view` services bundle,
# so `di.Error` will be raised.
pass
@ -56,7 +58,7 @@ assert photos_view.services.users is Services.users
assert photos_view.services.photos is Services.photos
try:
photos_view.services.auth
except di.Error as exception:
except errors.Error as exception:
# `auth` service provider is not in scope of `photo_processing_view`
# services bundle, so `di.Error` will be raised.
pass

View File

@ -5,13 +5,13 @@ class BaseService(object):
"""Example base class of service."""
class UsersService(BaseService):
class Users(BaseService):
"""Example users service."""
class AuthService(BaseService):
class Auth(BaseService):
"""Example auth service."""
class PhotosService(BaseService):
class Photos(BaseService):
"""Example photo service."""

View File

@ -7,15 +7,15 @@ class BaseWebView(object):
def __init__(self, services):
"""Initializer.
:type services: catalogs.Services
:param services: Bundle of service providers
:type services: catalogs.Services
"""
self.services = services
class AuthView(BaseWebView):
class Auth(BaseWebView):
"""Example auth web view."""
class PhotosView(BaseWebView):
class Photos(BaseWebView):
"""Example photo processing web view."""