mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
Update Factory docs about positional and keyword arguments
This commit is contained in:
parent
9b4a7bd28c
commit
cc29d68337
|
@ -11,15 +11,17 @@ follows `Semantic versioning`_
|
|||
Development version
|
||||
-------------------
|
||||
|
||||
- Add functionality for decorating classes with ``@di.inject``.
|
||||
- Add functionality for creating ``di.AbstractCatalog`` provider bundles.
|
||||
- Add enhancement for ``di.AbstractCatalog`` inheritance.
|
||||
- Enhance ``di.AbstractCatalog`` inheritance.
|
||||
- Add images for catalog "Writing catalogs" and "Operating with catalogs"
|
||||
examples.
|
||||
- Add support of Python 3.5.
|
||||
- Add support of six 1.10.0.
|
||||
- Add functionality for using positional argument injections with
|
||||
``di.Factory`` and ``di.Singleton`` providers.
|
||||
- Add optimization for ``di.Injection.value`` property that will compute
|
||||
type of injection once, instead of doing this on every call.
|
||||
- Add functionality for decorating classes with ``@di.inject``.
|
||||
- Add support of Python 3.5.
|
||||
- Add support of six 1.10.0.
|
||||
- Add minor refactorings and code style fixes.
|
||||
|
||||
0.9.5
|
||||
|
|
|
@ -15,46 +15,57 @@ Nothing could be better than brief example:
|
|||
Factory providers and __init__ injections
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``di.Factory`` takes a various number of keyword arguments that are
|
||||
transformed into keyword argument injections. Every time, when ``di.Factory``
|
||||
creates new one instance, keyword argument injections would be passed as an
|
||||
instance's keyword arguments.
|
||||
``di.Factory`` takes a various number of positional and keyword arguments that
|
||||
are used as ``__init__()`` injections. Every time, when ``di.Factory``
|
||||
creates new one instance, positional and keyword argument injections would be
|
||||
passed as an instance's arguments.
|
||||
|
||||
All injectable values are provided *"as is"*, except of providers (subclasses
|
||||
of ``di.Provider``). Providers will be called every time, when injection needs
|
||||
to be done. For example, if injectable value of keyword argument injection is a
|
||||
``di.Factory``, it will provide new one instance (as a result of its call) as
|
||||
an injectable value every time, when injection needs to be done.
|
||||
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
|
||||
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.
|
||||
|
||||
Example below is a little bit more complicated. It shows how to create
|
||||
``di.Factory`` of particular class with ``__init__`` keyword argument
|
||||
injections which injectable values are also provided by another factories:
|
||||
``di.Factory`` of particular class with ``__init__()`` argument injections
|
||||
which injectable values are also provided by another factories:
|
||||
|
||||
.. note::
|
||||
|
||||
Current keyword argument injections syntax (in an example below) is a
|
||||
**simplified one**. Full syntax and other types of injections could be
|
||||
found in sections below.
|
||||
Current positional and keyword argument injections syntax (in the examples
|
||||
below) is a **simplified one** version of full syntax. Examples of full
|
||||
syntax and other types of injections could be found in sections below.
|
||||
|
||||
While keyword argument injections may be the best way of passing
|
||||
injections, current simplified syntax might be the preferable one and
|
||||
could be widely used.
|
||||
While positional / keyword argument injections may be the best way of
|
||||
passing injections, current simplified syntax might be the preferable one
|
||||
and could be widely used.
|
||||
|
||||
.. image:: /images/providers/factory_init_injections.png
|
||||
:width: 90%
|
||||
:align: center
|
||||
|
||||
.. literalinclude:: ../../examples/providers/factory_init_injections.py
|
||||
Example of usage positional argument injections:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/factory_init_args.py
|
||||
:language: python
|
||||
|
||||
Example of usage keyword argument injections:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/factory_init_kwargs.py
|
||||
:language: python
|
||||
|
||||
Factory providers and __init__ injections priority
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Next example shows how ``di.Factory`` provider deals with positional and
|
||||
keyword ``__init__`` context arguments. In few words, ``di.Factory``
|
||||
provider fully passes positional context arguments to class's ``__init__``
|
||||
method, but keyword context arguments have priority on predefined keyword
|
||||
argument injections.
|
||||
keyword ``__init__()`` context arguments. In few words, ``di.Factory``
|
||||
behaviour here is very like a standard Python ``functools.partial``:
|
||||
|
||||
- Positional context arguments will be appended after ``di.Factory``
|
||||
positional injections.
|
||||
- Keyword context arguments have priority on ``di.Factory`` keyword injections
|
||||
and will be merged over them.
|
||||
|
||||
So, please, follow the example below:
|
||||
|
||||
|
@ -67,7 +78,7 @@ So, please, follow the example below:
|
|||
Factory providers and other types of injections
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Objects can take dependencies in different forms(some objects take init
|
||||
Objects can take dependencies in different forms (some objects take init
|
||||
arguments, other use attributes setting or method calls). It affects how
|
||||
such objects are created and initialized.
|
||||
|
||||
|
@ -78,8 +89,11 @@ All of those instructions are defined in ``di.injections`` module and are
|
|||
subclasses of ``di.injections.Injection`` (shortcut ``di.Injection``). There
|
||||
are several types of injections that are used by ``di.Factory`` provider:
|
||||
|
||||
+ ``di.Arg`` - injection is done by passing injectable value in object's
|
||||
``__init__()`` method in time of object's creation as positional argument.
|
||||
Takes injectable value only.
|
||||
+ ``di.KwArg`` - injection is done by passing injectable value in object's
|
||||
``__init__()`` method in time of object's creation via keyword argument.
|
||||
``__init__()`` method in time of object's creation as keyword argument.
|
||||
Takes keyword name of ``__init__()`` argument and injectable value.
|
||||
+ ``di.Attribute`` - injection is done by setting specified attribute with
|
||||
injectable value right after object's creation. Takes attribute's name
|
||||
|
|
34
examples/providers/factory_init_args.py
Normal file
34
examples/providers/factory_init_args.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
"""`di.Factory` providers with init positional injections example."""
|
||||
|
||||
import dependency_injector as di
|
||||
|
||||
|
||||
class User(object):
|
||||
"""Example class User."""
|
||||
|
||||
def __init__(self, main_photo):
|
||||
"""Initializer."""
|
||||
self.main_photo = main_photo
|
||||
super(User, self).__init__()
|
||||
|
||||
|
||||
class Photo(object):
|
||||
"""Example class Photo."""
|
||||
|
||||
# User and Photo factories:
|
||||
photos_factory = di.Factory(Photo)
|
||||
users_factory = di.Factory(User, photos_factory)
|
||||
|
||||
# Creating several User objects:
|
||||
user1 = users_factory() # Same as: user1 = User(Photo())
|
||||
user2 = users_factory() # Same as: user2 = User(Photo())
|
||||
|
||||
# Making some asserts:
|
||||
assert isinstance(user1, User)
|
||||
assert isinstance(user1.main_photo, Photo)
|
||||
|
||||
assert isinstance(user2, User)
|
||||
assert isinstance(user2.main_photo, Photo)
|
||||
|
||||
assert user1 is not user2
|
||||
assert user1.main_photo is not user2.main_photo
|
|
@ -62,7 +62,8 @@ assert user1.credit_card is not user2.credit_card
|
|||
main_photo_mock = Photo()
|
||||
credit_card_mock = CreditCard()
|
||||
|
||||
user3 = users_factory(3, main_photo=main_photo_mock,
|
||||
user3 = users_factory(3,
|
||||
main_photo=main_photo_mock,
|
||||
credit_card=credit_card_mock)
|
||||
|
||||
assert user3.id == 3
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""`di.Factory` providers with init injections example."""
|
||||
"""`di.Factory` providers with init keyword injections example."""
|
||||
|
||||
import dependency_injector as di
|
||||
|
||||
|
@ -17,8 +17,7 @@ class Photo(object):
|
|||
|
||||
# User and Photo factories:
|
||||
photos_factory = di.Factory(Photo)
|
||||
users_factory = di.Factory(User,
|
||||
main_photo=photos_factory)
|
||||
users_factory = di.Factory(User, main_photo=photos_factory)
|
||||
|
||||
# Creating several User objects:
|
||||
user1 = users_factory() # Same as: user1 = User(main_photo=Photo())
|
Loading…
Reference in New Issue
Block a user