Update callable provider docs, including API, and examples

This commit is contained in:
Roman Mogilatov 2015-11-23 15:39:19 +02:00
parent cea843160c
commit a65155ed1c
6 changed files with 109 additions and 47 deletions

View File

@ -293,7 +293,18 @@ class Singleton(Provider):
__slots__ = ('instance', 'factory')
def __init__(self, provides, *args, **kwargs):
"""Initializer."""
"""Initializer.
:param provides: Class or other callable that provides object
for creation.
:type provides: type | callable
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections.
:type kwargs: dict
"""
self.instance = None
"""Read-only reference to singleton's instance.
@ -492,33 +503,78 @@ class Value(StaticProvider):
class Callable(Provider):
"""Callable provider.
""":py:class:`Callable` provider calls wrapped callable on every call.
Callable provider provides callable that is called on every provider call
with some predefined dependency injections.
:py:class:`Callable` provider provides callable that is called on every
provider call with some predefined dependency injections.
:py:class:`Callable` syntax of passing injections is the same like
:py:class:`Factory` one:
.. code-block:: python
some_function = Callable(some_function, 'arg1', 'arg2', arg3=3, arg4=4)
result = some_function()
"""
__slots__ = ('callback', 'args', 'kwargs')
def __init__(self, callback, *args, **kwargs):
"""Initializer."""
"""Initializer.
:param callback: wrapped callable.
:type callback: callable
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections.
:type kwargs: dict
"""
if not callable(callback):
raise Error('Callable expected, got {0}'.format(str(callback)))
self.callback = callback
self.args = _parse_args_injections(args)
self.kwargs = _parse_kwargs_injections(args, kwargs)
super(Callable, self).__init__()
"""Wrapped callable.
def _provide(self, *args, **kwargs):
"""Return provided instance."""
return self.callback(*_get_injectable_args(args, self.args),
**_get_injectable_kwargs(kwargs, self.kwargs))
:type: callable
"""
self.args = _parse_args_injections(args)
"""Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
"""
self.kwargs = _parse_kwargs_injections(args, kwargs)
"""Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
"""
super(Callable, self).__init__()
@property
def injections(self):
"""Return tuple of all injections."""
"""Read-only tuple of all injections.
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
"""
return self.args + self.kwargs
def _provide(self, *args, **kwargs):
"""Return provided instance.
:param args: tuple of context positional arguments
:type args: tuple[object]
:param kwargs: dictionary of context keyword arguments
:type kwargs: dict[str, object]
:rtype: object
"""
return self.callback(*_get_injectable_args(args, self.args),
**_get_injectable_kwargs(kwargs, self.kwargs))
class Config(Provider):
"""Config provider.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -1,40 +1,43 @@
Callable providers
------------------
``di.Callable`` provider is a provider that wraps particular callable with
.. module:: dependency_injector.providers
:py:class:`Callable` provider is a provider that wraps particular callable with
some injections. Every call of this provider returns result of call of initial
callable.
Callable providers and injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Callable`` takes a various number of positional and keyword arguments
that are used as decorated callable injections. Every time, when
``di.Callable`` is called, positional and keyword argument injections would be
passed as an callable arguments.
:py:class:`Callable` takes a various number of positional and keyword
arguments that are used as decorated callable injections. Every time, when
:py:class:`Callable` is called, positional and keyword argument injections
would be passed as an callable arguments.
Such behaviour is very similar to the standard Python ``functools.partial``
object, except of one thing: all injectable values are provided
*"as is"*, except of providers (subclasses of ``di.Provider``). Providers
*"as is"*, except of providers (subclasses of :py:class:`Provider`). Providers
will be called every time, when injection needs to be done. For example,
if injectable value of injection is a ``di.Factory``, it will provide new one
instance (as a result of its call) every time, when injection needs to be done.
if injectable value of injection is a :py:class:`Factory`, it will provide
new one instance (as a result of its call) every time, when injection needs
to be done.
``di.Callable`` behaviour with context positional and keyword arguments is
very like a standard Python ``functools.partial``:
:py:class:`Callable` behaviour with context positional and keyword arguments
is very like a standard Python ``functools.partial``:
- Positional context arguments will be appended after ``di.Callable``
- Positional context arguments will be appended after :py:class:`Callable`
positional injections.
- Keyword context arguments have priority on ``di.Callable`` keyword
- Keyword context arguments have priority on :py:class:`Callable` keyword
injections and will be merged over them.
Example that shows usage of ``di.Callable`` with positional argument
Example that shows usage of :py:class:`Callable` with positional argument
injections:
.. literalinclude:: ../../examples/providers/callable_args.py
:language: python
Next one example shows usage of ``di.Callable`` with keyword argument
Next one example shows usage of :py:class:`Callable` with keyword argument
injections:
.. image:: /images/providers/callable.png
@ -47,13 +50,13 @@ injections:
Callable providers delegation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Callable`` provider could be delegated to any other provider via any kind
of injection. Delegation of ``di.Callable`` providers is the same as
``di.Factory`` and ``di.Singleton`` providers delegation, please follow
*Factory providers delegation* section for example.
:py:class:`Callable` provider could be delegated to any other provider via any
kind of injection. Delegation of :py:class:`Callable` providers is the same as
:py:class:`Factory` and :py:class:`Singleton` providers delegation, please
follow *Factory providers delegation* section for example.
``di.Callable`` delegate could be created obviously using
``di.Delegate(di.Callable())`` or by calling ``di.Callable.delegate()`` method.
:py:class:`Callable` delegate could be created obviously using
``Delegate(Callable(...))`` or by calling ``Callable(...).delegate()`` method.
Example:

View File

@ -1,11 +1,11 @@
"""`di.Callable` providers with positional arguments example."""
"""`Callable` providers with positional arguments example."""
import dependency_injector as di
from dependency_injector import providers
# Creating even and odd filter providers:
even_filter = di.Callable(filter, lambda x: x % 2 == 0)
odd_filter = di.Callable(filter, lambda x: x % 2 != 0)
even_filter = providers.Callable(filter, lambda x: x % 2 == 0)
odd_filter = providers.Callable(filter, lambda x: x % 2 != 0)
# Creating even and odd ranges using xrange() and filter providers:
even_range = even_filter(xrange(1, 10))

View File

@ -1,13 +1,14 @@
"""`di.Callable` providers delegation example."""
"""`Callable` providers delegation example."""
import sys
import dependency_injector as di
from dependency_injector import providers
# Creating some callable provider and few delegates of it:
callable_provider = di.Callable(sys.exit)
callable_provider = providers.Callable(sys.exit)
callable_provider_delegate1 = callable_provider.delegate()
callable_provider_delegate2 = di.Delegate(callable_provider)
callable_provider_delegate2 = providers.Delegate(callable_provider)
# Making some asserts:
assert callable_provider_delegate1() is callable_provider

View File

@ -1,14 +1,16 @@
"""`di.Callable` providers with keyword arguments example."""
"""`Callable` providers with keyword arguments example."""
import passlib.hash
import dependency_injector as di
from dependency_injector import providers
# Password hasher and verifier providers (hash function could be changed
# anytime (for example, to sha512) without any changes in client's code):
password_hasher = di.Callable(passlib.hash.sha256_crypt.encrypt,
password_hasher = providers.Callable(passlib.hash.sha256_crypt.encrypt,
salt_size=16,
rounds=10000)
password_verifier = di.Callable(passlib.hash.sha256_crypt.verify)
password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify)
# Making some asserts:
hashed_password = password_hasher('super secret')