From 5b76551790bf31c465b81c132807e161bc2275e6 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 27 May 2015 19:00:41 +0300 Subject: [PATCH] Working copy of docs --- docs/index.rst | 1 + docs/injections.rst | 37 +++++++++ docs/providers.rst | 75 ++++++++++++++++++- examples/readme2/factory_providers.py | 13 ++++ .../readme2/factory_providers_init_args.py | 34 +++++++++ 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 docs/injections.rst create mode 100644 examples/readme2/factory_providers.py create mode 100644 examples/readme2/factory_providers_init_args.py diff --git a/docs/index.rst b/docs/index.rst index 9bed770b..ad7a2c2b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -39,6 +39,7 @@ Contents introduction installation providers + injections catalogs decorators examples diff --git a/docs/injections.rst b/docs/injections.rst new file mode 100644 index 00000000..c9104855 --- /dev/null +++ b/docs/injections.rst @@ -0,0 +1,37 @@ +Injections +========== + +Injections are *Objects* entities that are used for specification of dependency +injection types. + +Different functions, classes and objects can take dependency injections in +various forms. Some of them take dependencies like keyword arguments during +call time, other require setting of attributes or calling of specialized +methods for doing dependency injections. + +So, when you are doing dependency injection you need to specify its type and +that is the place where *Injections* need to be used. + +Some key points of *Objects* injections: + + - Every *Objects* injection always takes injectable value as an + ``injectable`` param. Every Python object could be an injectable. + - Every *Objects* injection always has ``value`` property that returns + injection's injectable. ``value`` property is calculated every time it is + accessed. Every Python object, except of *Objects* providers, that was + provided as and ``injectable`` will be returned by ``value`` property + *"as is"*. *Objects* providers will be called every time during ``value`` + accessing and result of such calls will be returned. + - Every *Objects* *Injection* can have additional params that are needed + for doing particular type of injection. + +There are several types of *Injections*: + + - ``KwArg`` - is used for making keyword argument injections for any kind + of callables (functions, methods, objects instantiation and so on). Takes + keyword argument name as string and injectable. + - ``Attribute`` - is used for making injections by setting of injection's + value to a particular attribute. Takes attribute name as string and + injectable. + - ``Method`` - is used for making injections by calling of method with + injectable value. Takes method name as string and injectable. diff --git a/docs/providers.rst b/docs/providers.rst index 89775790..e6609c3c 100644 --- a/docs/providers.rst +++ b/docs/providers.rst @@ -3,10 +3,77 @@ Providers Providers are strategies of accessing objects. -All providers are callable. They describe how particular objects will be -provided. +All providers are callable. They describe how particular objects are provided. +Factory providers +----------------- + +``Factory`` provider creates new instance of specified class on every call. + +Nothing could be better than brief example: + +.. code-block:: python + + """`Factory` providers example.""" + + from objects.providers import Factory + + + # Factory provider creates new instance of specified class on every call. + object_factory = Factory(object) + + object_1 = object_factory() + object_2 = object_factory() + + assert object_1 is not object_2 + assert isinstance(object_1, object) and isinstance(object_2, object) + +Factory providers and injections +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Objects can take dependencies in different forms. Some objects take init +arguments, other are using attributes setting or method calls to be +initialized. It affects how such objects need to be created and initialized, +and that is the place where ``objects.injections`` need to be used. + +``Factory`` provider takes various number of positional arguments, that define +what kind of dependency injections need to be done. + +All of those instructions are defined in ``objects.injections`` module and are +subclasses of ``objects.injections.Injection``. There are several types of +injections that are used by ``Factory`` provider: + + - ``KwArg`` - injection is done by passing injectable value in object's + ``__init__()`` method in time of object's creation via keyword argument. + Takes keyword name of ``__init__()`` argument and injectable value. + - ``Attribute`` - injection is done by setting specified attribute with + injectable value right after object's creation. Takes attribute name and + injectable value. + - ``Method`` - injection is done by calling of specified method with + injectable value right after object's creation and attribute injections + are done. Takes method name and injectable value. + +All ``Injection``'s injectable values are provided *"as is"*, except of +providers. Providers will be called every time, when injection needs to be +done. + +Factory providers and __init__ injections +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - KwArg example. + - Context args priority example. + +Factory providers and attribute injections +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - Attributes example. + +Factory providers and method injections +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - Method example. + Instance providers & Injections ------------------------------- @@ -367,3 +434,7 @@ Example: assert object_a_1 is not object_a_2 assert object_a_1.get_one() == object_a_2.get_one() == 2 + + + +.. _Constructor injection: http://en.wikipedia.org/wiki/Dependency_injection#Constructor_injection diff --git a/examples/readme2/factory_providers.py b/examples/readme2/factory_providers.py new file mode 100644 index 00000000..e4a87ba5 --- /dev/null +++ b/examples/readme2/factory_providers.py @@ -0,0 +1,13 @@ +"""`Factory` providers example.""" + +from objects.providers import Factory + + +# Factory provider creates new instance of specified class on every call. +object_factory = Factory(object) + +object_1 = object_factory() +object_2 = object_factory() + +assert object_1 is not object_2 +assert isinstance(object_1, object) and isinstance(object_2, object) diff --git a/examples/readme2/factory_providers_init_args.py b/examples/readme2/factory_providers_init_args.py new file mode 100644 index 00000000..3430877a --- /dev/null +++ b/examples/readme2/factory_providers_init_args.py @@ -0,0 +1,34 @@ +"""`Factory` providers with constructor injections example.""" + +from objects.providers import Factory +from objects.injections import KwArg + + +class ObjectA(object): + + """ObjectA has few dependencies that need to provided as init args.""" + + def __init__(self, object_b, object_c): + """Initializer.""" + self.object_b = object_b + self.object_c = object_c + + +# Creating of dependencies. +object_b = object() +object_c = object() + +# Creating ObjectA factory. +object_a_factory = Factory(ObjectA, + KwArg('object_b', object_b), + KwArg('object_c', object_c)) + + +object_a_1 = object_a_factory() # Same as ObjectA(object_b, object_c) +object_a_2 = object_a_factory() # Same as ObjectA(object_b, object_c) + +assert object_a_1 is not object_a_2 +assert isinstance(object_a_1, ObjectA) +assert isinstance(object_a_2, ObjectA) +assert object_a_1.object_b is object_a_2.object_b is object_b +assert object_a_1.object_c is object_a_2.object_c is object_c