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') __slots__ = ('instance', 'factory')
def __init__(self, provides, *args, **kwargs): 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 self.instance = None
"""Read-only reference to singleton's instance. """Read-only reference to singleton's instance.
@ -492,33 +503,78 @@ class Value(StaticProvider):
class Callable(Provider): 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 :py:class:`Callable` provider provides callable that is called on every
with some predefined dependency injections. 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') __slots__ = ('callback', 'args', 'kwargs')
def __init__(self, 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): if not callable(callback):
raise Error('Callable expected, got {0}'.format(str(callback))) raise Error('Callable expected, got {0}'.format(str(callback)))
self.callback = callback self.callback = callback
self.args = _parse_args_injections(args) """Wrapped callable.
self.kwargs = _parse_kwargs_injections(args, kwargs)
super(Callable, self).__init__()
def _provide(self, *args, **kwargs): :type: callable
"""Return provided instance.""" """
return self.callback(*_get_injectable_args(args, self.args),
**_get_injectable_kwargs(kwargs, self.kwargs)) 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 @property
def injections(self): 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 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): class Config(Provider):
"""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 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 some injections. Every call of this provider returns result of call of initial
callable. callable.
Callable providers and injections Callable providers and injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Callable`` takes a various number of positional and keyword arguments :py:class:`Callable` takes a various number of positional and keyword
that are used as decorated callable injections. Every time, when arguments that are used as decorated callable injections. Every time, when
``di.Callable`` is called, positional and keyword argument injections would be :py:class:`Callable` is called, positional and keyword argument injections
passed as an callable arguments. would be passed as an callable arguments.
Such behaviour is very similar to the standard Python ``functools.partial`` Such behaviour is very similar to the standard Python ``functools.partial``
object, except of one thing: all injectable values are provided 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, 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 if injectable value of injection is a :py:class:`Factory`, it will provide
instance (as a result of its call) every time, when injection needs to be done. 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 :py:class:`Callable` behaviour with context positional and keyword arguments
very like a standard Python ``functools.partial``: 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. 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. 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: injections:
.. literalinclude:: ../../examples/providers/callable_args.py .. literalinclude:: ../../examples/providers/callable_args.py
:language: python :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: injections:
.. image:: /images/providers/callable.png .. image:: /images/providers/callable.png
@ -47,13 +50,13 @@ injections:
Callable providers delegation Callable providers delegation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Callable`` provider could be delegated to any other provider via any kind :py:class:`Callable` provider could be delegated to any other provider via any
of injection. Delegation of ``di.Callable`` providers is the same as kind of injection. Delegation of :py:class:`Callable` providers is the same as
``di.Factory`` and ``di.Singleton`` providers delegation, please follow :py:class:`Factory` and :py:class:`Singleton` providers delegation, please
*Factory providers delegation* section for example. follow *Factory providers delegation* section for example.
``di.Callable`` delegate could be created obviously using :py:class:`Callable` delegate could be created obviously using
``di.Delegate(di.Callable())`` or by calling ``di.Callable.delegate()`` method. ``Delegate(Callable(...))`` or by calling ``Callable(...).delegate()`` method.
Example: 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: # Creating even and odd filter providers:
even_filter = di.Callable(filter, lambda x: x % 2 == 0) even_filter = providers.Callable(filter, lambda x: x % 2 == 0)
odd_filter = di.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: # Creating even and odd ranges using xrange() and filter providers:
even_range = even_filter(xrange(1, 10)) 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 sys
import dependency_injector as di
from dependency_injector import providers
# Creating some callable provider and few delegates of it: # 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_delegate1 = callable_provider.delegate()
callable_provider_delegate2 = di.Delegate(callable_provider) callable_provider_delegate2 = providers.Delegate(callable_provider)
# Making some asserts: # Making some asserts:
assert callable_provider_delegate1() is callable_provider 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 passlib.hash
import dependency_injector as di
from dependency_injector import providers
# Password hasher and verifier providers (hash function could be changed # Password hasher and verifier providers (hash function could be changed
# anytime (for example, to sha512) without any changes in client's code): # 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, salt_size=16,
rounds=10000) rounds=10000)
password_verifier = di.Callable(passlib.hash.sha256_crypt.verify) password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify)
# Making some asserts: # Making some asserts:
hashed_password = password_hasher('super secret') hashed_password = password_hasher('super secret')