From 1ad852d193e4f51ad66e8527f9a5d25c6e02f684 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Mon, 31 Aug 2020 21:26:21 -0400 Subject: [PATCH] Factory provider docs update (#287) * Update index page * Update providers index page * Make a little wording fix on containers index page * Refactor factory provider docs header * Update factory injection docs * Update factory init injections example and picture * Start work on underlying providers * Finish the docs for factory arguments to the underlying providers * Edit providers delegation section * Edit section about specialized factory provider * Edit abstract factory section * Edit FactoryAggregate docs * Add meta keywords and description --- docs/containers/index.rst | 2 +- docs/images/providers/factory.png | Bin 9465 -> 0 bytes docs/images/providers/factory_delegation.png | Bin 21993 -> 0 bytes .../providers/factory_init_injections.png | Bin 32985 -> 0 bytes docs/providers/factory.rst | 256 ++++++++---------- docs/providers/images/abstract_factory.png | Bin 0 -> 24650 bytes docs/providers/images/factory_aggregate.png | Bin 0 -> 14680 bytes docs/providers/images/factory_delegation.png | Bin 0 -> 18306 bytes .../images/factory_init_injections.png | Bin 0 -> 11004 bytes .../factory_init_injections_underlying.png | Bin 0 -> 26540 bytes docs/providers/index.rst | 32 ++- examples/providers/abstract_factory.py | 75 +++++ examples/providers/abstract_factory/cache.py | 25 -- .../providers/abstract_factory/example.py | 36 --- examples/providers/factory.py | 16 +- examples/providers/factory_aggregate.py | 55 ++++ .../providers/factory_aggregate/example.py | 31 --- examples/providers/factory_aggregate/games.py | 27 -- .../providers/factory_aggregate/prototype.py | 17 -- examples/providers/factory_delegation.py | 89 ++---- examples/providers/factory_init_injections.py | 61 ++--- ... => factory_init_injections_underlying.py} | 8 +- examples/providers/factory_provided_type.py | 13 +- 23 files changed, 338 insertions(+), 405 deletions(-) delete mode 100644 docs/images/providers/factory.png delete mode 100644 docs/images/providers/factory_delegation.png delete mode 100644 docs/images/providers/factory_init_injections.png create mode 100644 docs/providers/images/abstract_factory.png create mode 100644 docs/providers/images/factory_aggregate.png create mode 100644 docs/providers/images/factory_delegation.png create mode 100644 docs/providers/images/factory_init_injections.png create mode 100644 docs/providers/images/factory_init_injections_underlying.png create mode 100644 examples/providers/abstract_factory.py delete mode 100644 examples/providers/abstract_factory/cache.py delete mode 100644 examples/providers/abstract_factory/example.py create mode 100644 examples/providers/factory_aggregate.py delete mode 100644 examples/providers/factory_aggregate/example.py delete mode 100644 examples/providers/factory_aggregate/games.py delete mode 100644 examples/providers/factory_aggregate/prototype.py rename examples/providers/{factory_deep_init_injections.py => factory_init_injections_underlying.py} (83%) diff --git a/docs/containers/index.rst b/docs/containers/index.rst index 510d4d02..1e5d7c33 100644 --- a/docs/containers/index.rst +++ b/docs/containers/index.rst @@ -12,7 +12,7 @@ There are several use cases how you can use containers: container ``Users``, that contains all functional parts of the ``users`` package). -Containers package API docs - :py:mod:`dependency_injector.containers`. +Containers module API docs - :py:mod:`dependency_injector.containers`. .. toctree:: :maxdepth: 2 diff --git a/docs/images/providers/factory.png b/docs/images/providers/factory.png deleted file mode 100644 index ff79ee5ea7fca31038b41145230f05cf931bfbdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9465 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 P{RazEYZKB{@1*|%R^`kc diff --git a/docs/images/providers/factory_init_injections.png b/docs/images/providers/factory_init_injections.png deleted file mode 100644 index f39b44d702ef647978f50b17ef9cf02b704e64bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32985 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 JrttXr{{t|Im6ZSh diff --git a/docs/providers/factory.rst b/docs/providers/factory.rst index 2aa7f3ab..7708f25e 100644 --- a/docs/providers/factory.rst +++ b/docs/providers/factory.rst @@ -1,193 +1,167 @@ -Factory providers ------------------ +Factory provider +---------------- + +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Factory,Abstract Factory, + Pattern,Example,Aggregate + :description: Factory provider helps to implement dependency injection in Python. This page + demonstrates how to use Factory provider, inject the dependencies, and assemble + object graphs passing the injections deep inside. It also provides the examples + of the Abstract Factory pattern & provider and Factories Aggregation pattern. .. currentmodule:: dependency_injector.providers -:py:class:`Factory` provider creates new instance of specified class on every -call. - -Nothing could be better than brief example: - -.. image:: /images/providers/factory.png - :width: 80% - :align: center +:py:class:`Factory` provider creates new objects. .. literalinclude:: ../../examples/providers/factory.py :language: python + :lines: 3- -Factory providers and __init__ injections -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The first argument of the ``Factory`` provider is a class, a factory function or a method +that creates an object. -:py:class:`Factory` takes a various number of positional and keyword arguments -that are used as ``__init__()`` injections. Every time, when -:py:class:`Factory` creates new one instance, positional and keyword -argument injections would be passed as instance arguments. +The rest of the ``Factory`` positional and keyword arguments are the dependencies. +``Factory`` injects the dependencies every time when creates a new object. The dependencies are +injected following these rules: -Injections are done according to the next rules: ++ If the dependency is a provider, this provider is called and the result of the call is injected. ++ If you need to inject the provider itself, you should use the ``.provider`` attribute. More at + :ref:`factory_providers_delegation`. ++ All other dependencies are injected *"as is"*. ++ Positional context arguments are appended after ``Factory`` positional dependencies. ++ Keyword context arguments have the priority over the ``Factory`` keyword dependencies with the + same name. -+ All providers (instances of :py:class:`Provider`) are called every time - when injection needs to be done. -+ Providers could be injected "as is" (delegated), if it is defined obviously. - Check out :ref:`factory_providers_delegation`. -+ All other injectable values are provided *"as is"*. -+ Positional context arguments will be appended after :py:class:`Factory` - positional injections. -+ Keyword context arguments have priority on :py:class:`Factory` keyword - injections and will be merged over them. - -For example, 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. - -Example below is a little bit more complicated. It shows how to create -:py:class:`Factory` of particular class with ``__init__()`` injections which -injectable values are also provided by another factories: - -.. image:: /images/providers/factory_init_injections.png +.. image:: images/factory_init_injections.png .. literalinclude:: ../../examples/providers/factory_init_injections.py :language: python + :lines: 3- -Factory providers and building complex object graphs -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Passing arguments to the underlying providers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can use :py:class:`Factory` provider to build complex object graphs. +``Factory`` provider can pass the arguments to the underlying providers. This helps when you need +to assemble a nested objects graph and pass the arguments deep inside. -Consider next example: +Consider the example: -.. literalinclude:: ../../examples/providers/factory_deep_init_injections.py +.. image:: images/factory_init_injections_underlying.png + +To create an ``Algorithm`` you need to provide all the dependencies: ``ClassificationTask``, +``Loss``, and ``Regularizer``. The last object in the chain, the ``Regularizer`` has a dependency +on the ``alpha`` value. The ``alpha`` value varies from algorithm to algorithm: + +.. code-block:: python + + Algorithm( + task=ClassificationTask( + loss=Loss( + regularizer=Regularizer( + alpha=alpha, # <-- the dependency + ), + ), + ), + ) + + +``Factory`` provider helps to deal with the such assembly. You need to create the factories for +all the classes and use special double-underscore ``__`` syntax for passing the ``alpha`` argument: + +.. literalinclude:: ../../examples/providers/factory_init_injections_underlying.py :language: python + :lines: 3- + :emphasize-lines: 24-35,39,42,45 -.. note:: +When you use ``__`` separator in the name of the keyword argument the ``Factory`` looks for +the dependency with the same name as the left part of the ``__`` expression. - You can use ``__`` separator in the name of the keyword argument to pass the value to the child - factory, e.g. ``algorithm_factory(task__loss__regularizer__alpha=0.5)``. +.. code-block:: + + __= + +If ```` is found the underlying provider will receive the +``=`` as an argument. .. _factory_providers_delegation: -Factory providers delegation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Passing providers to the objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`Factory` provider could be delegated to any other provider via any -kind of injection. +When you need to inject the provider itself, but not the result of its call, use the ``.provider`` +attribute of the provider that you're going to inject. -As it was mentioned earlier, if :py:class:`Factory` is -injectable value, it will be called every time when injection needs to be -done. But sometimes there is a need to inject :py:class:`Factory` provider -itself (not a result of its call) as a dependency. Such injections are called -- *delegated provider injections*. - -Saying in other words, delegation of factories - is a way to inject factories -themselves, instead of results of their calls. - -:py:class:`Factory` delegation is performed by wrapping delegated -:py:class:`Factory` into special provider type - :py:class:`Delegate`, that -just returns wrapped :py:class:`Factory`. - -Actually, there are three ways for creating factory delegates: - -+ ``DelegatedFactory(...)`` - use special type of factory - - :py:class:`DelegatedFactory`. Such factories are always injected as - delegates ("as is"). -+ ``Delegate(Factory(...))`` - obviously wrapping factory into - :py:class:`Delegate` provider. -+ ``Factory(...).delegate()`` - calling factory :py:meth:`Factory.delegate` - method, that returns delegate wrapper for current factory. -+ ``Factory(...).provider`` - getting factory :py:attr:`Factory.provider` - attribute, that returns delegate wrapper for current factory (alias of - ``Factory(...).delegate()`` method). - -Example: - -.. image:: /images/providers/factory_delegation.png - :width: 85% - :align: center +.. image:: images/factory_delegation.png .. literalinclude:: ../../examples/providers/factory_delegation.py :language: python + :lines: 3- + :emphasize-lines: 25 -.. _factory_providers_specialization: +.. note:: Any provider has a ``.provider`` attribute. -Factory providers specialization -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Specializing the provided type +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`Factory` provider could be specialized for any kind of needs via -creating its subclasses. - -One of such specialization features is a limitation to :py:class:`Factory` -provided type: +You can create a specialized ``Factory`` provider that provides only specific type. For doing +this you need to create a subclass of the ``Factory`` provider and define the ``provided_type`` +class attribute. .. literalinclude:: ../../examples/providers/factory_provided_type.py :language: python + :lines: 3- + :emphasize-lines: 12-14 -.. _abstract_factory_providers: +Abstract factory +~~~~~~~~~~~~~~~~ -Abstract factory providers -~~~~~~~~~~~~~~~~~~~~~~~~~~ +:py:class:`AbstractFactory` provider helps when you need to create a provider of some base class +and the particular implementation is not yet know. ``AbstractFactory`` provider is a ``Factory`` +provider with two peculiarities: -:py:class:`AbstractFactory` provider is a :py:class:`Factory` provider that -must be explicitly overridden before calling. ++ Provides only objects of a specified type. ++ Must be overridden before usage. -.. note:: - - Overriding of :py:class:`AbstractFactory` provider is possible only by - another :py:class:`Factory` provider. - -:py:class:`AbstractFactory` provider is useful when it is needed to specify -explicitly that it only provides abstraction, but not an implementation. -Client code must override such factories with factories that provide particular -implementations. Otherwise, :py:class:`AbstractFactory` will raise an error -on attempt of calling it. At the same time, :py:class:`AbstractFactory` is -regular provider that could be injected into other providers (or used for -any other kind of bindings) without being overridden. After -:py:class:`AbstractFactory` provider has been overridden, its behaviour is -identical to regular :py:class:`Factory` provider. - -Example: - -.. image:: /images/providers/abstract_factory.png +.. image:: images/abstract_factory.png :width: 100% :align: center -Listing of ``cache.py``: - -.. literalinclude:: ../../examples/providers/abstract_factory/cache.py +.. literalinclude:: ../../examples/providers/abstract_factory.py :language: python + :lines: 3- + :emphasize-lines: 32 -Listing of ``example.py``: +Factory aggregate +~~~~~~~~~~~~~~~~~ -.. literalinclude:: ../../examples/providers/abstract_factory/example.py +:py:class:`FactoryAggregate` provider aggregates multiple factories. When you call the +``FactoryAggregate`` it delegates the call to one of the factories. + +The aggregated factories are associated with the string names. When you call the +``FactoryAggregate`` you have to provide one of the these names as a first argument. +``FactoryAggregate`` looks for the factory with a matching name and delegates it the work. The +rest of the arguments are passed to the delegated ``Factory``. + +.. image:: images/factory_aggregate.png + :width: 100% + :align: center + +.. literalinclude:: ../../examples/providers/factory_aggregate.py :language: python + :lines: 3- + :emphasize-lines: 31-35,43 -Factory aggregate providers -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can get a dictionary of the aggregated factories using the ``.factories`` attribute of the +``FactoryAggregate``. To get a game factories dictionary from the previous example you can use +``game_factory.factories`` attribute. -:py:class:`FactoryAggregate` provider is a special type of provider that -aggregates other :py:class:`Factory` providers. +You can also access an aggregated factory as an attribute. To create the ``Chess`` object from the +previous example you can do ``chess = game_factory.chess('John', 'Jane')``. .. note:: + You can not override the ``FactoryAggregate`` provider. - :py:class:`FactoryAggregate` is not overridable. Calling of - :py:meth:`FactoryAggregate.override` will result in raising of an - exception. - -Next prototype might be the best demonstration of -:py:class:`FactoryAggregate` features: - -.. literalinclude:: ../../examples/providers/factory_aggregate/prototype.py - :language: python - -Example below shows one of the :py:class:`FactoryAggregate` use cases, when -concrete implementation (game) must be selected based on dynamic input (CLI). - -Listing of ``games.py``: - -.. literalinclude:: ../../examples/providers/factory_aggregate/games.py - :language: python - -Listing of ``example.py``: - -.. literalinclude:: ../../examples/providers/factory_aggregate/example.py - :language: python +.. note:: + When you inject the ``FactoryAggregate`` provider it is passed "as is". .. disqus:: diff --git a/docs/providers/images/abstract_factory.png b/docs/providers/images/abstract_factory.png new file mode 100644 index 0000000000000000000000000000000000000000..172c7ef02197bb61c2eaaf5b24d13c77f21e0154 GIT binary patch literal 24650 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 U@I!IqHCS~Xdx*QM+(J+O3FRa}GXMYp literal 0 HcmV?d00001 diff --git a/docs/providers/images/factory_aggregate.png b/docs/providers/images/factory_aggregate.png new file mode 100644 index 0000000000000000000000000000000000000000..0b563372deb5b6a6fa27543fe9bc8a22e734eddb GIT binary patch literal 14680 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 R+*FEmIqH6-@^2Te{|BODOvnHL literal 0 HcmV?d00001 diff --git a/docs/providers/images/factory_delegation.png b/docs/providers/images/factory_delegation.png new file mode 100644 index 0000000000000000000000000000000000000000..4def0d0826b8eca367af48f82615162a2084139d GIT binary patch literal 18306 zcmeIacTkgE*Ds8spdetQ7ZqvJR3MZ9VxdS2LK2X!bV4ry0Ra^i>Cz1(ARvS*p-2fx z2bJC-0qG*u(4+(;v=i_9dG7bTGv~~_f1K}|?>qBmCX>0YoxQHT*Iw7&>-Sr0?}!Hw zEfyvoCOSGg7VZ1$Ms#$HP&&F}i>K&mcO<0b%V<9*9PjAgp`$B_W8Qy!l6HOB_P&um z9bKRZ9o@5+baYhOt!ImLbjTZYbmT{Lbl`V%bex{(YC{!TLCFI>n8wl3(ca$P)YMdN zZmzq#yR@`4t;E#SG%+#p>({SjGFe?+UDHz5Ck+-`=ae(zpWf^By41!wTA%GAGZz=v z*47r+MW)=h+5?rATO`+`DX*z7HiV1^?vHM~Cn5L7JO~7WgwiE-Wr5^YH*%MwqV6?Q zebML7pAQTS1m~Gs2CEynsql-kKlfBhe0Jw6-dI}f;@H?28ynl(w{OG4!$aH^F%cRe z?g~-W4ljzVUldyN>T-UhHSw5@u9iC8o0I(aX&0wG@0)TLu`yxOme&(hIpRB5ZrsdKR%1=BqWNG$JhV`k91kS2oE$scs_OzTPYVSXy%D?D=NTo^TFV(**s#J8Pkb$7oXj`$N;fGkrA1`sr`3V`#b5qYx?| z75`25Rw#8xW-FW#`=ynQbHOp|Xi>o@*5H`XQT^r`S$TGOs_zmHTHsRey`zcEWV&C| zmZ2t7SN8?OFV{|GHaJ?}RpWiO^A+1?-EOshZL9Spwj*^%91hpzKQnW#@tSOg5Om%0 zcOW}edE{zQeWaG3>Ym>w|97`fb$eF|DISXrhkiX8lX;1KbKH%}m-*imf3aV@ZXfs7 zHZf#8T-tv6>u*1)!(Ws3YTc;CGpM|*PMK#rcLeKkYWG5=g1#86e{#rTeyFIr`U<92 z-#TP%s-K&}^d1E@oH%BvAAHKP_Vcxkl{#bCb#-gRqRpA_6Ccl7llrVXCoc;O75C*z zpoOvxD1uv@?_aUm*T2q+y7_D;j0^j9fGy-H$4uhg)I!g+@#N5_m+pqro1L8iqJN+K zXm@VV`RTa}&I0%TDve|%^-VqFP#@D@ynE(5e|+trNbXMC$*W11xz@^48L-ERjlkh| z*eOQH$whia(j_$0bR$3)Ooye0L9g&BvcG5h4h!`Ze@Tx$zI6+t5$=Tq{6i-D=%W8Tj=(8*M%e$b!|H7E72Y$P9tpNjt{r%jNxMsh z`ukH_l-98c+8-4z5B2z%xF_{)$om$>ogj|P`9V_5D9GF3rQpm-tX||RiXWkBM^r10JD=hX`Q(dW=#+O@5u#t9@)8*m(ydzQP@hB>DMWaS6GUEZ^H8_89QGy^uY++k9#V z>pb;w+x^f!cm#}o7I8+W8cTIFfA01gUnKBDRtOgqe8jH>)Wv!)j??iC04Adu?m_s1 ziWIZKKjxuBNsPp=TN|>JSF#n+dsqb&qFqgRS0HRtv z2Hnt(EG92rOsM^B5m~V{n;Mz~Rnxp=H&*F@ejA9Qm^^kDooPYyH!i zhe82@8V?nftn4&u#2etzhR;CB1 zm4b(&IIkUxBpho%qY|x~@xAhnKRzFA0lGozC)FfYsQn^1i9G9xNau9tO7FZ7K_c%n zFET?KB=|;1Qub4{s#-gloTw=30t}apu;C>H%zPn<1ofIdES6uaE2z4a8opXYi88lz4z91O z8IjnXVWe5JG`0vAIdKE^^|Qx-`GAKll(S1v>%m61PC*MVTPp6eBEcORj0UMHdqt$) z!ybN;0hz_;kuT{ds!MH-&BJ&@KBW7FcXt)KzCf*m#8|%*H$g$<`rejzV{sKro0+{1 z(FsL)hnr0(;msho7QKM&uvj>zsv!IP=YvWPv)$SdXh-=Th|ZjyHfi`O!39F!*5x%g z_*edTRgiZWpB3UXEsi~`o4Ps;J@!{?afm$SgjRs8O|qXS3nH^|SH~XZkWr4+kTgZF zZi07eax;A5q0o)|Y|~z^Ibzpo`|!*5Lu8Sbuj34|o_wq`#Nuvl3C@aZmD?+OBegdM z2#va;oS7Eb4CZM2LTG~-cMYZ>rR@5W0%dop2tr_Kbhs=FnYit!3OCj%p6IVt!--e{ z!@M)Zg+7IK+Pv{+~Wnqy!KE&Aldp6;F~_B5p; z+~1}~beSQJk$nPT?EUlM2l|XuUaG((=+ArIYrqedePo=2C@5NL871MaJRH)x+KO_4 z#B}e&MBCL}h+95s&w7YMZTvmv{)lBTay(55`6OScdltq?X|e+Uz=c}!7~?<5wO(H) z5=TA9dR_7+eh@pE!$XNYXRWXI6vNCw*hnw!2HqyZae^wwtc?4aq>R7STva?l`cm6H-~ayy0Y*ZD=^-9GvFk2WKMU-G*Faq$ra zF#HAVvriH4nvsE2v9+-eto3SdAmXOkUe)DU6%$7kn(TcRduW^T00-Aw@f^eTZaJnx z&B3>?#^l!UsM-1ef`7vgg{f*EWqB{?$+j=AZr$Vp6@cfm?W7-?t zgI(THP}N4Du5o2Va!w9uCpu|R-Y0|ACuMa4;sUDY+tzKR;HnV++(h3Qoh9cOAJz5p z)pc(*Wa5DgMFgvyhfFZhbW>7zbQ+fF zT*t#{K$6vUxx#JZ7!O!k4^9sIy#TF zLicaioF4hSr`2ExeGp1KKCYWO`O{E06tUn*Hm2G1gSt4MTpiUjz|-WG_72x;MX8(c z4QQH$h_-Z(ADDz`lgW=2okI#fF{%o(ffdeU!830=MmL`%oMEUwG%W|iwXF)J3XElw zM)+cfFyiMi#YfVL0j#yxy937RZ^q1 zo7!k+5DU8;t#2I;xyS@NkEPDPO7B7;_th+JYC6k$zm9$|?_cx#{gch5fbIN)UENDH z_!Cr>^ofbd85o-tHDe7lg2qEs4-R>CsmVImyS>ERN;ru?BXGbSfJ`Q;he$HV0jg3NsPV9^zt{$uYEE@1QrqOkkao%z=U&Y z4;ykQ#q!(Sz%E(2!GeSq?+q?3zJLD>rc6rXC`-9q9=_6H))uE0w5u{O0duyZJzK5KU)BLb` zq|Y_BqS7F)PbJr51g^rzQZ<2KqfQH3>Fyi2GiK?0HGGBk5Y0UA##thm=9)u_mRa4r zZzn9l%!Q*}6N^oMO?RS3M^-G1b&w%yCh2u`ACZ+8WI+@KmkZSOhbB0IS6i*BdBafZ zG#_p|w+TpZ1cI+19Wpp7&ZmOY>rl;a(7_K}f>5zI1=8=#2p@ouJ4p}kHUQ!8e|y~8 za|k%luWJbF*2Ulx=S#hDwo?HrX1(YS`MC^{3P^k*XhX+mz&HG7s$>9B+TtYwVEtgj1D6Q{Asi$~9otTVev){d> ze#SEO=}kg>0r^=oVBQ2AJXXu3rg!vOnWGa8tuKvGEyU(7+0WRN(44l;?J2t`ItbYp>dIvQm zgB1xaRb{RNJb%H-ti;<8jDeLv|N3(%KesS$`g8cNkSqyG!1 z{<%(@I&x!q@xK7WWVU~R@IljG{qJM+#HsxQhAE8y$oQ`#?EjL`$r9+X_Y4rqjNlgI zNm0n6$8F}UOQ#!^PhhDuElFlI9Fuw(B1E@#7ENY^y!!a^kfHo?DSI_N^LPF`p*Xdz z|EJpJDgH-c|A#yKf2U9ZdM`fgTxgV{KqVtr>w31AlkKBBts^EP@QCYH0)z3-p$AIu zp&lL{YfD=0?jE6p@Ve{t;nICq6ctHfwPIz7Cv2-|=LiHTrFXzKzLvE*|H95eBVHWQ6IZIqJxSsjRS4AZT3Kbp4dldGzQp z$ln%A_EVQaqP~Va_nCTTC3!X6U5$Sn*sL23Ne>ur1+rKCUqOePfWz8**jv3$9JkKV zoCWo6=O6rmfsITnPoyou)-0t!0p1S|XImv6B>A1f){D`%o`Fyn;H_f8OTJ{0B5paP z_!bH9P>js=MNIQQdD^J?0|tA$fE!I`eFZn+zv4w+4}%_zkcsJpc&)?n)fpl$gJ9;F zU?iD0rFvc3d5+N+x2SD7>VIKf4;*s;JCTO0sAVLejKE68=K8qTgK`F?0V#Sd@V<4i-cozrq<~WKCBXiasWl&4*+xfGpWDlrnQ%0+_YWMveO?k^p#1U7&9P7y* z7^4$%aV)bnT&-6j8R}T3dFiKqfcpNCWbrO2=;;&m1fD)_PNQtZXYq%?s!0J=B}dTzxFf+X`k||gL?y_St~37wmmSV8muyS^W9CI9Rn)c_6Qg$bxu|jxVX4^Kwt_v(B*%-+|R~b zH}eV2Q>=`<0!q-{WSNVw;9N^y`Fi;S5Dv{f#e`HJ)6+D*Z$FE~vSMDA1L!@z~))1adEi)}w%I2&t|PFU&TTeHqQ^~AE;y|xcwLcI`p z3S!rqw@u93Z+-z)rp-DumA1NLZ@p3L32z-pl9jFYPlO&NO&{qL9v;L(4We@V5vC6e zGyn{1cNE~BofKle_+BGPAN*RiS>(FyV~k9sml2Z_qPMW)UgDiHoLEA9^;>wUg=ivR zHxJKM8a6ECmUHGoz%0*6>4IWRpshphKYR|XdfdA8?fNaor}~}@o#^pp2|=SI`9=W% zIDVb!;I2wSKmha4M!8EuKd!zLL8ywMM~~B9gkO*YA3>yG=jSGRNY6`G zEu-NKNO$$*zyevWkwZ6hHS6DvdMttR9|BxHK@J{w4vPk#!e*SR^TC<1${Tl{m*afx z_S2xS`ZN?CX@F;%R$mexIP(ACv{Cv_=w5Ka1FH&mc8y7k-!eX2YHu!^q!+lI9c$G^b#roBA5940B}SyXwk{l+de3g z;D4bqBNl2-8&zLr%DnN$MGb#4+)YQ{F_c^fc;IdeKuB4a2vJ_-pMA<$O_oy4su?gm z>AME(QgpQ^(;=)ORz79gOV>(9*#U4;y^>f`L}b7iQ_Yk>LjgghsPKnfb?TNr&K6jn zsBX9z|C3dVMAHWT>I_6KVu1VIaNrx`!dzZ##WU!^Pd{>jX~?*|&b?N^fOO@tuB_ni z@Kh)Pe*_EnBu97>A*310>^8_{!`IO))sGd)h){ybHw9-EJsqZ{T+L~Za^o7YvaD1H zT1GdlWh*g~l$R^gQqrbT+636=Rtw?Lh^xFrGeF~@PbId)gK@=xzq3iZ2bLxCGg;fm zREa>bJ;6d7oEwnf0@f-#YtK_OweM6k)F6CP38Y=F&qNXQNK)3vrj>kp<<814Uk`1O zn0STCX`L<)d0YwId<{*_sor2B(WT2TbP_xJwq=1DCQm$+bF(Fmb*E`@Sp3(gInj=$ z)&q#|Y#4%U5OWSPL9+(z7*Hvz4SW)%kn;?ADwHYiCfFXH=YMM)F{(QukHy`rD!o6v zbh=y#`3(aDt(q(;b(a1#>xL%6Z5^3+9?9dBk@=%f!zaRWHu8DOp}leF?eqGbuI0)g z(vD(psZBa`hF+O;5Ro{#Ag-l@x0VN6L_zU#UI=DIQf6?g7!pjfRJerwtO;oZZ0_Vd zFL)Fgfr=R0#`{}GfE^0O3ZSpjW!XL5_n^vT;7dLs1Cg8)&e>f9wnK`D14o>P3xVGKsdHS6ut%&!5YIz4bIa@qIDGO)vZA8yx1_F{uo) zD&(a z>WPOhKeX4B3V1scJs0BSWwm(I*sp5JmtDVm;0+S%0JgJGcbJ>{ddT!}QRAY^(m{vg zHIeUf403R|PrB+}PL}-f_5fJ_qf)LIQM{NpZdt?C!zn8>0U_AC1+|gxmZz=B=9s{- zcj`Ik2!mMjs?*)b31B1oVe1`nZ7g1R%AVxKu=hRen(Eg3tGcTk-6g+ zHQ=d4V;OuGqGb?31hFeU7fvm+(5Si|KGDU@JN&hWHNL$|LFj4$l%i0fM7X)GWh`jF z=Pbwn#?s+KJJxjU(^UT1dl=bks{!uYx$O)aKT6Vhm7chywa52ww$#hjfRW_|_KH5Y zl72n{RmR;776&Ut1?pTyk1|0hj(BLzZ;3xY;3m%Hf9?{VtlWj~dUvIVC!?L=bXNCr@Ex~Fqu6EeXPX^g$K~ z^6nqxJ_Cic_jB8iyh5PjYwL@9b8i~O5D$SGWw^CK^`~%!@88hi4#pAR%PE3-U3WKT z)L}*orlg1HdHXs-o3X>bM}`n@%Ry}CJJ;D}IdhqM;-jxEpSk%H0XaVb5CcTm4C11wHG_H|%$;~n!` z6;*Avqk7ISp)^Y2aCwEerVuJ{bZfsVx$ukkg9J;&&%@oH(`#`x)>9rG_ogU7pihy~ zrUm9k|I?$89U3Vh>g&bk(b%s2)49Od z0(Hh0@gpb2>9HsO1so7!rTQ*nC!3+pgC=|0&;FWJ|H9!ccX$luNd?_IuQLZYOt*FP z8x#pF=)a*ZQL}_36cSLrWLL~dc`Ok2ZA(P&i!VSfXatu29eS3JEL89zZw3418OL1- z2+#{UJDgYX;^e<#)TGCJ#hc30nW( zi8lYl?*ISL{TY5`b~?m&n40w6&usqu8R_dIczXuQgKDsSK2MXlq%Set+l znq}$!ub7WFuCD|x9{&~lC^|tc+VI7{QWgGRW@!G~jQ&LgwO#`w&$Z52_PRRqwMLm- ze>f#UBR+EUdkxeuFvf8`?uQ?DwAKZUl7D}mBq|@nQa5psI#jnqO~y!1aKK9NSj5Kf z7=M|i=e*-R4*tcIN4LEqA>G+xBa|-V0q2Wz#mO_Dy1q>+1u6X;vSzm5{?VVeV8V0d zfoS#LVmv3>?=IYe1QeuUdu)7o!fs?@k4ZmI-`nIzV1j z^{A~$XxR%>AzV0)rDE12e0R;bW9h|3x@Cn?cj~hSwjt=z=-|xz;@G^+?$oHao0OoZ z!n8&Bz=xbE7Pu&x#kNRXYv{P#Adlt@-J2q>v2A{XFrr5TMYR1~pI8h<4Tm`@nhB3t z3bhB*QzuO{Dj%_~5_hfK8oE_hXJE8wj8T=Pp2EEGsQ)LwxZ)EKim30{nq=U(RF8+D zZ}3zIqE5*_460CmaM%}6y#(nv)ub8+^`F0psm8oAXkRnpC>}IfI+XA!yH~cc|BQWf z-J;sJp2rSqYO;dE35)}K?LW^#kg_+Tv$Jdbq%q{D%Zik`vw_hAGewYtnp};FmJrf( zgNOkeZ)VK?=Odslw3!i^L?dd7l`o4;k$~$?a+9%QHFb=g9~ir|%}!iLNFTr)<=CoN|akN0piyiR_g;ug2<)%e}tPo zjo|3Tpv7@Ov4XnXWbS~#r9L3LyNWE7@rEsTCbg>s44T?%N>R8=dEZM1y z$(v0dV{z*gZM+5s8Q7)TqJ?&y0fX^A(g zSpoIrt$kH3GN#Q(ylm{#v4i<%O{vX^uyc5J6}W6{xf-G#z2!m-8`pe%>Y^YnCNyei&stvWnM4cUwlo< zY_fUS`S}k~Q%r{C$eCh-LZ}kp%N`h6S=s$Y{Q@8;mgQ^vr<$O%@JZDJdOejdI~G1G$CdiLHSZl^R~}xv-l*g`h9MRI&b=TMe}N z@fg_k-Z*M2XUSv!2dbOM#=bZyLcA%vcu~;{o63)je!PtLH?n3CFLXlC}(r83d!KsPvxTz7j%qGTm2qK z-BSjE4mm(OxdB2y{58RS5m9ncPHFkMiRd#I=ZAH}q0M#1YWXsov$^@uz1dePIdGig zo^;ntvgtz&tI8HnMz zMJ{^ewJgrJi~P1|`6%*I3wd?QHCl!=kifPha=^%+<8FHBa7J9_+P#VWH}VEyst%Ab zz(Hl@wrFK0bWr>Wjlp+2NT<6IyK*xCpT&0Sk z!eY3|e&ie$Ut7$m8JZVM?qdVZP*?yTS+8Tch2kh;}u#(AN5wu6r&DQO2TUnTOs zxO1ICj&Jn<2++{OLZ-88pxhQOTu}iF5~#?8^2b*w5{z2zv!fww78bcRSujF;tZ0O( z%_FN37n_dpfcfzk_gg;HIDQ@1uB8Y9vwpA&m$en>KBM#6r7A zxg;pw5BRkSo^10lOlC4E_3+gA;cPb5CI59QoI4*38@t6hIC*nuE#`JNqe?%U7*2IJ zIdT~CHf^t<>D6B(-HM*znOv)tTe&SrTs^h8v@-*OR3BX-=BG7Lzt6$=soKNZE&()@ zXef1H`+^)jQZde$+ld15I^gdGgOBpOseG7aAvBFtLwwYl#_Nt|6+ZfQO`v!hHdy|1 zvgvC827lv~$$odx*|~tFh(MW9UWkm}1XkN|0M+^h#3oKo(;fT)+bp|mQaLA0w-_rh z7QPyYOU7xpLL^8oA|$hF%o*2rZ67e=4(qI2K~+?vSv{oz{A~k#ueRDyvQM0D=3et3 zx)V7hspeN)#N%@d28CoKMOgI%4dTx$DKEgyRiCod;DsAiQU;-gEao;(S z)NUM;EWUJ0|CP6DVA*h)Dih=z;GQ@Zg-$a$=@1l(K;xc@6}#hMhcjPD07G-zFH_6617rwO9@5f;VR9>UVGGMyjDJ%j`(=><}jb zt+~puZEWn^cOggd=qHmR-S%^^pb$}P$K}L$Bw{7fb%lP&tH$)6G+(GI1vlwJscYZVuQ1#u^~Px_i&z~1 zU1KE^FHOi=y53OLhFczXf@Xd2&^7yV5X2X2j3#rSi)UaZ1+hcqyZEnul_AG$fPk%-6f!x{SF(AJKi)lIItMqrTYQ&9Nw)5D$> zk9Td(Puz5Uw6J7t+$cb>mc>wrHmb~j7GSrL6{9IkGS@QH@($q2#Y;ozKQqaxk7BQt4!42F$AKaGo8(|i&ygDobEmuTJ&L_^MJ9r7POhhDyG7wBJ zC;DMI;002)NqR}uQzhSiR9Ze9O2D)a{&2J9z$lR#g? z3*lc5jH4MIEoHq#e$_;wBT_)G71%KpCam~4S13`cgIttE-IcTn)uzf5Tj3bp!Taj| z_zbWjT+3e(OP1(1yE_vRpCSKN*2}j%f6hsFKR{SkIo%t? z{W=hMsHhbrIWbKy=MHFRxW~ZKpWJtI?VID0C7NvT1bb`wY}SST#EGqys#TaFij))m zYTjy*=rp(w=j)pb->LhJ>wNg( zn<96A*@^4I)9h4Fnqk1(&Gq9qCSK~`Mz88Y-vxJGXWpC3JIlvZtyYVU(b z;VcZFd^+4O7$K%rP;F{r6Rh4eq`rcK&J$mFswhN^Y_L1zA%sUb3|0 z2qNCk3v`pf8Nj2Zei)+)jBlvip^}MpBK=OI7&1rj=EU|rDclPSNkC%gtP%5Urp{$+2K#Hvp5+k={u!$_7kV->(w&!lR?wh(nfGTzV!iXbkjRBd*LG;IFc+cinac zRk>X^=05t1UiM~6v^2tfyjSzVA$17j&7Bw;8a(9Ky)H@Dun zgP|>@({_24bC?#EqA|H1+bH!MXMbFcd={7R-tX?9h&;p^h_L#7aHV*mp?|6x+KgJN zv2Mt?lM`ch!5S&qL+><4LFO zrM=>sjgAH)bc)>^Lp@JZn0&t!{`f$+J?T9VW!x`h9*`#~YvK(}(#bWv`Bs#{Jr?|t zJ9#8wc+R^e_uCRw`r6Iwt|651q=&wb(*vMTi$ZH?c5O(kYg|P1xlu`_ z?1P`;jil&FJf>slG;lg)WGn9rLDafIY4dU=tw*Oz5Td!+R9n#h z7qK20s$!AMm@5C`F$zg=fTmq9bFPqC8c|3*$B{37Ut3E+WG+Wcwt>&MJJC7do`wj! zGNklQ>EZs5(uBNAkLu3{M8R$As*^v}?z#SaW0!Cya-+VB-dldBqSC!AHQnLJYv5Lb zq(O(l`!3Q)zXwBjich>`!o~wsYdMOh7>ThHC5KO2C|55y!i#-BNpAL0XJ^ETf~FCY zXX>iC|AOAcy)kow_V1O#mG`xE2Xp9ij1K;^UiSKNa-Cb*T!v`nQC08`&;YVPixVN(vhc`ZS1n-ehWnYO~c!{N%20-X}jIj{Cj*X^gJ$;376PvV!d zo!g|oDrqZ$&Lz991uto^W2}HAz29;7Cx1WR)z)<03Q>U!j|xyw6|OGlIAzl3~wTm>>^vXiTn<41j5CCO*$rf(1%ShC^THjfM7KD z;tsYupG~<>du%`O#EAy`kn>)}u*Ptu@9l3my}y7Ck^-<8lyU>?Q!-s1}jtB3^>2)DxmKGr&#nvQz^dK>{ zzpU*+>roG0v(rDao?K6<6>Cs_&%oGV3|ga$dt5!pRdUY=H@cix7Hw6C3@8qN0aYF8 z1Y{eE_uTE5{9v~l>flRj6Q>RMg0Fg#=Z(6C0h?Rho#sYUL%>>v4W{-7#zVv4S2s~5 zZD(L33hJK~3SnOos%x&kSBX{e+KN#W!M3>UXCC>}8hK60s^Rz1p4w8Y@1lyfm5Lr9 z+|0jGLr;q@?9uiHeMQvl-k^7H^()?coKTz7;ze5o*Qn5j;rXsw!JZRbPlRLJ0lHRZ zS`0l7^2+wuUmNHC&yep(3DcAa;3yyk?$VIr!4M`n<^?}qvOF<=*1mRR+IY@9|J!7D z0^!$jnkD>|hFEzXNPar;YNDB3AJv|cyM*q>cE=a`!wWlxEwr36k*{#}+wXV&9cFR2 zp8$Z-SDKO~^^c!7P$uBDXtVr4giqaA@K6Igg{TBkW&K;SR|3RxI*{*g!81Y_a3~6DTXwQraJ1Z>u+TFKWL^n%Axq-;8J7zZ$jtd)yrh>E4qw z+~qyfUHo$WHvdg%&-qc4L(YlcDNPW`K~C@3vuAwUJK zQ?t{qfk3YZs_2q^i!gLTL-Dwd? zwFjD1uJNb0j}(Bgti1jryM2fRj^4QjlqQBKIBIE9j0a9Gzy3tj4_K)9PZS#D?9)Q zzkT2082$5Wkj)+^t17-K4pwl^B;>#mgI|GGy1!$Av7JC?DFe9y36{jL#D7 z+-*K?BNUN1b_d<+qEBE<+L%Rb2X)RJBBc*5w&c}kO5?TdBp}D=JSy%M)Qstv(65dBv`Z1nC+x-Ct%`zO53qVR&+^pD*HI^uzgb)aZqp zm6m_TNNWwv18UGq*H4vK98T<+o z3h7!`3IEh??N=hTsYhw-r*h}rqVckwUC|%hyb!L{rg*z*=BC)2ItZbSr_Rj_Yp`Iq z6iM97tEz^o$c7YAbfD1R_MhVqA(f|nwtR7?p@)~rDz-wAghCDcgo!@kK^9RzJ`TZU z*zmANm;qT60Kw92d7qeD<>#dNfW$RToS~)k{xw#s#0YZ((nK+Dt5|zPruO+(oAW>Y zu(8|T2vqTNzxNj%qo7zyl@c(hm6q;e%Uj{z6HN zYYmiFzbQQtu;#rUl^-OnZ`=SbstK|w?j9OG)&jJi`d7UkAm*lyo5Y5@C;3~%pXS*o zZ7&;u+Dyx{w?}>u?FqP#A?E&-57Bq+K;{kH=)mZIz4Ej)kHVI(60a`lCpMBAbc&PGQ-a28M6LHRa$?)1c^=~eeP-~M6BHlnv1x)%ze>5P&u*HPH+VZj3HR91?VYw>O@P)PnyL1w@o-kBv7-KJ zhgyB-pWW`;zGOiOy&BgF50(MEFLcmnz}ePt@}7DOG>ZjYO`pC0>9pmi&)OSXkcRvq zFkD(%$g$5Z5Vq{{Hcfz(LgBEo^85jFqQ|Z_a`J>;Ig|ZUfqMPVCj8*Bkme8F&M6Vj z!efZHGj{yFI*tV`z7o6U%{{EWZb&D|H(CObTxB!c1NG}6PFOx z+F=BlxkW5y?)>RN(h$?EptPT7|DEK_KKDX2BZ>D{~h&?Vx zJ0;+w0_}VN2FS^0bxi;r$WxqdnFVq(pLPlDupZ<%QHS9Tc8;R`0!Scpq7R%JSW@ms)cBn*F_f);e^H*B45; zBJxa+dv+AelkuM1REg7c!SjQ|r|9HT&rnZ3OZ7x@S98%n5q)~VOupc_ zp_92Gb3^KeqLl1S*o~WDkPKKxLE^>@@QoY80a7mise+q_owGy0|Gq+=Q1bAfr)q0J L)Qj#udhtI1pVNW4 literal 0 HcmV?d00001 diff --git a/docs/providers/images/factory_init_injections.png b/docs/providers/images/factory_init_injections.png new file mode 100644 index 0000000000000000000000000000000000000000..f176cc8a6f778d1695b58112753fd4f602c16cb4 GIT binary patch literal 11004 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 literal 0 HcmV?d00001 diff --git a/docs/providers/images/factory_init_injections_underlying.png b/docs/providers/images/factory_init_injections_underlying.png new file mode 100644 index 0000000000000000000000000000000000000000..f6e79408d3b3d35ec7420204ab631ff764d7d50c GIT binary patch literal 26540 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 qv74KZo0~q!zVZ(Zl4!BJccuJ!gKX?I^mRLvf& literal 0 HcmV?d00001 diff --git a/docs/providers/index.rst b/docs/providers/index.rst index 15e2eccb..bd5a4745 100644 --- a/docs/providers/index.rst +++ b/docs/providers/index.rst @@ -3,18 +3,32 @@ Providers ========= -Providers are strategies of accessing objects. They define how particular -objects are provided. +Providers help to assemble the objects. They create objects and inject the dependencies. -Every provider is callable (implements ``__call__()``). Every call to provider -instance returns provided result, according to the providing strategy of -particular provider. +Each provider is a callable. You call the provider like a function when you need to create an +object. Provider retrieves the underlying dependencies and inject them into the created object. +It causes the cascade effect that helps to assemble object graphs. -Current documentation section consists from description of standard providers -library and some useful information like overriding of providers and writing -of custom providers. +.. code-block:: bash -Providers package API docs - :py:mod:`dependency_injector.providers` + provider1() + │ + ├──> provider2() + │ + ├──> provider3() + │ │ + │ └──> provider4() + │ + └──> provider5() + │ + └──> provider6() + +Another providers feature is an overriding. Any of the providers can be overridden by another +provider. When provider is overridden it calls to the overriding provider instead of providing +the object by its own. This helps in testing. This also helps in overriding API clients with +stubs for the development or staging environment. + +Providers module API docs - :py:mod:`dependency_injector.providers` .. toctree:: :maxdepth: 2 diff --git a/examples/providers/abstract_factory.py b/examples/providers/abstract_factory.py new file mode 100644 index 00000000..03ccf4f4 --- /dev/null +++ b/examples/providers/abstract_factory.py @@ -0,0 +1,75 @@ +"""`AbstractFactory` providers example.""" + +import abc +import dataclasses +import random +from typing import List + +from dependency_injector import providers + + +class AbstractCacheClient(metaclass=abc.ABCMeta): + ... + + +@dataclasses.dataclass +class RedisCacheClient(AbstractCacheClient): + host: str + port: int + db: int + + +@dataclasses.dataclass +class MemcachedCacheClient(AbstractCacheClient): + hosts: List[str] + port: int + prefix: str + + +@dataclasses.dataclass +class Service: + cache: AbstractCacheClient + + +cache_client_factory = providers.AbstractFactory(AbstractCacheClient) +service_factory = providers.Factory( + Service, + cache=cache_client_factory, +) + + +if __name__ == '__main__': + cache_type = random.choice(['redis', 'memcached', None]) + + if cache_type == 'redis': + cache_client_factory.override( + providers.Factory( + RedisCacheClient, + host='localhost', + port=6379, + db=0, + ), + ) + elif cache_type == 'memcached': + cache_client_factory.override( + providers.Factory( + MemcachedCacheClient, + hosts=['10.0.1.1'], + port=11211, + prefix='my_app', + ), + ) + + service = service_factory() + print(service.cache) + # The output depends on cache_type variable value. + # + # If the value is 'redis': + # RedisCacheClient(host='localhost', port=6379, db=0) + # + # If the value is 'memcached': + # MemcachedCacheClient(hosts=['10.0.1.1'], port=11211, prefix='my_app') + # + # If the value is None: + # Error: AbstractFactory() must be + # overridden before calling diff --git a/examples/providers/abstract_factory/cache.py b/examples/providers/abstract_factory/cache.py deleted file mode 100644 index 51cdc3c2..00000000 --- a/examples/providers/abstract_factory/cache.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Example hierarchy of cache clients with abstract base class.""" - - -class AbstractCacheClient: - """Abstract cache client.""" - - -class RedisCacheClient(AbstractCacheClient): - """Cache client implementation based on Redis.""" - - def __init__(self, host, port, db): - """Initialize instance.""" - self.host = host - self.port = port - self.db = db - - -class MemcacheCacheClient(AbstractCacheClient): - """Cache client implementation based on Memcached.""" - - def __init__(self, hosts, port, prefix): - """Initialize instance.""" - self.hosts = hosts - self.port = port - self.prefix = prefix diff --git a/examples/providers/abstract_factory/example.py b/examples/providers/abstract_factory/example.py deleted file mode 100644 index 46382afa..00000000 --- a/examples/providers/abstract_factory/example.py +++ /dev/null @@ -1,36 +0,0 @@ -"""`AbstractFactory` providers example.""" - -import cache - -import dependency_injector.providers as providers - - -# Define abstract cache client factory: -cache_client_factory = providers.AbstractFactory(cache.AbstractCacheClient) - -if __name__ == '__main__': - # Override abstract factory with redis client factory: - cache_client_factory.override( - providers.Factory( - cache.RedisCacheClient, - host='localhost', - port=6379, - db=0, - ), - ) - redis_cache = cache_client_factory() - print(redis_cache) - # - - # Override abstract factory with memcache client factory: - cache_client_factory.override( - providers.Factory( - cache.MemcacheCacheClient, - hosts=['10.0.1.1', '10.0.1.2', '10.0.1.3'], - port=11211, - prefix='my_app', - ), - ) - memcache_cache = cache_client_factory() - print(memcache_cache) - # diff --git a/examples/providers/factory.py b/examples/providers/factory.py index 17b1c9ec..33453dd3 100644 --- a/examples/providers/factory.py +++ b/examples/providers/factory.py @@ -1,15 +1,15 @@ """`Factory` providers example.""" -import collections - -import dependency_injector.providers as providers +from dependency_injector import providers -User = collections.namedtuple('User', []) +class User: + ... + -# Factory provider creates new instance of specified class on every call. users_factory = providers.Factory(User) -# Creating several User objects: -user1 = users_factory() # Same as: user1 = User() -user2 = users_factory() # Same as: user2 = User() + +if __name__ == '__main__': + user1 = users_factory() + user2 = users_factory() diff --git a/examples/providers/factory_aggregate.py b/examples/providers/factory_aggregate.py new file mode 100644 index 00000000..7facca65 --- /dev/null +++ b/examples/providers/factory_aggregate.py @@ -0,0 +1,55 @@ +"""`FactoryAggregate` provider example.""" + +import dataclasses +import sys + +from dependency_injector import providers + + +@dataclasses.dataclass +class Game: + player1: str + player2: str + + def play(self): + print( + f'{self.player1} and {self.player2} are ' + f'playing {self.__class__.__name__.lower()}' + ) + + +class Chess(Game): + ... + + +class Checkers(Game): + ... + + +class Ludo(Game): + ... + + +game_factory = providers.FactoryAggregate( + chess=providers.Factory(Chess), + checkers=providers.Factory(Checkers), + ludo=providers.Factory(Ludo), +) + + +if __name__ == '__main__': + game_type = sys.argv[1].lower() + player1 = sys.argv[2].capitalize() + player2 = sys.argv[3].capitalize() + + selected_game = game_factory(game_type, player1, player2) + selected_game.play() + + # $ python factory_aggregate.py chess John Jane + # John and Jane are playing chess + # + # $ python factory_aggregate.py checkers John Jane + # John and Jane are playing checkers + # + # $ python factory_aggregate.py ludo John Jane + # John and Jane are playing ludo diff --git a/examples/providers/factory_aggregate/example.py b/examples/providers/factory_aggregate/example.py deleted file mode 100644 index 906c8484..00000000 --- a/examples/providers/factory_aggregate/example.py +++ /dev/null @@ -1,31 +0,0 @@ -"""`FactoryAggregate` providers example.""" - -import sys - -import dependency_injector.providers as providers - -from games import Chess, Checkers, Ludo - - -game_factory = providers.FactoryAggregate( - chess=providers.Factory(Chess), - checkers=providers.Factory(Checkers), - ludo=providers.Factory(Ludo), -) - -if __name__ == '__main__': - game_type = sys.argv[1].lower() - player1 = sys.argv[2].capitalize() - player2 = sys.argv[3].capitalize() - - selected_game = game_factory(game_type, player1, player2) - selected_game.play() - - # $ python example.py chess John Jane - # John and Jane are playing chess - # - # $ python example.py checkers John Jane - # John and Jane are playing checkers - # - # $ python example.py ludo John Jane - # John and Jane are playing ludo diff --git a/examples/providers/factory_aggregate/games.py b/examples/providers/factory_aggregate/games.py deleted file mode 100644 index aa9e7a8a..00000000 --- a/examples/providers/factory_aggregate/games.py +++ /dev/null @@ -1,27 +0,0 @@ -"""Example games module.""" - - -class Game: - """Base game class.""" - - def __init__(self, player1, player2): - """Initialize instance.""" - self.player1 = player1 - self.player2 = player2 - - def play(self): - """Play game.""" - print('{0} and {1} are playing {2}'.format( - self.player1, self.player2, self.__class__.__name__.lower())) - - -class Chess(Game): - """Chess game.""" - - -class Checkers(Game): - """Checkers game.""" - - -class Ludo(Game): - """Ludo game.""" diff --git a/examples/providers/factory_aggregate/prototype.py b/examples/providers/factory_aggregate/prototype.py deleted file mode 100644 index 930a3159..00000000 --- a/examples/providers/factory_aggregate/prototype.py +++ /dev/null @@ -1,17 +0,0 @@ -"""FactoryAggregate provider prototype.""" - - -class FactoryAggregate: - """FactoryAggregate provider prototype.""" - - def __init__(self, **factories): - """Initialize instance.""" - self.factories = factories - - def __call__(self, factory_name, *args, **kwargs): - """Create object.""" - return self.factories[factory_name](*args, **kwargs) - - def __getattr__(self, factory_name): - """Return factory with specified name.""" - return self.factories[factory_name] diff --git a/examples/providers/factory_delegation.py b/examples/providers/factory_delegation.py index 0aee54d3..f6bc02d1 100644 --- a/examples/providers/factory_delegation.py +++ b/examples/providers/factory_delegation.py @@ -1,82 +1,37 @@ """`Factory` providers delegation example.""" -import collections +from typing import Callable, List -import dependency_injector.providers as providers - - -Photo = collections.namedtuple('Photo', []) +from dependency_injector import providers class User: - """Example user model.""" - - def __init__(self, photos_factory): - """Initialize instance.""" - self.photos_factory = photos_factory - self._main_photo = None - - @property - def main_photo(self): - """Return user's main photo.""" - if not self._main_photo: - self._main_photo = self.photos_factory() - return self._main_photo + def __init__(self, uid: int) -> None: + self.uid = uid -# Defining User and Photo factories using DelegatedFactory provider: -photos_factory = providers.DelegatedFactory(Photo) -users_factory = providers.Factory( - User, - photos_factory=photos_factory, -) +class UserRepository: + def __init__(self, user_factory: Callable[..., User]) -> None: + self.user_factory = user_factory -# or using Delegate(Factory(...)) + def get_all(self) -> List[User]: + return [ + self.user_factory(**user_data) + for user_data in [{'uid': 1}, {'uid': 2}] + ] -photos_factory = providers.Factory(Photo) -users_factory = providers.Factory( - User, - photos_factory=providers.Delegate(photos_factory), + +user_factory = providers.Factory(User) +user_repository_factory = providers.Factory( + UserRepository, + user_factory=user_factory.provider, ) -# or using Factory(...).delegate() +if __name__ == '__main__': + user_repository = user_repository_factory() -photos_factory = providers.Factory(Photo) -users_factory = providers.Factory( - User, - photos_factory=photos_factory.delegate(), -) + user1, user2 = user_repository.get_all() - -# Creating several User objects: -user1 = users_factory() -user2 = users_factory() - -# Same as: -# user1 = User(photos_factory=photos_factory) -# user2 = User(photos_factory=photos_factory) - -# Making some asserts: -assert isinstance(user1.main_photo, Photo) -assert isinstance(user2.main_photo, Photo) - -# or using Factory(...).provider - -photos_factory = providers.Factory(Photo) -users_factory = providers.Factory( - User, - photos_factory=photos_factory.provider, -) - -# Creating several User objects: -user1 = users_factory() -user2 = users_factory() - -# Same as: -# user1 = User(photos_factory=photos_factory) -# user2 = User(photos_factory=photos_factory) - -# Making some asserts: -assert isinstance(user1.main_photo, Photo) -assert isinstance(user2.main_photo, Photo) + assert user1.uid == 1 + assert user2.uid == 2 diff --git a/examples/providers/factory_init_injections.py b/examples/providers/factory_init_injections.py index 2bdb0b24..682ace80 100644 --- a/examples/providers/factory_init_injections.py +++ b/examples/providers/factory_init_injections.py @@ -1,39 +1,36 @@ """`Factory` providers init injections example.""" -import collections - -import dependency_injector.providers as providers +from dependency_injector import providers -CreditCard = collections.namedtuple('CreditCard', []) -Photo = collections.namedtuple('Photo', []) -User = collections.namedtuple('User', ['uid', 'main_photo', 'credit_card']) - -# User, Photo and CreditCard factories: -credit_cards_factory = providers.Factory(CreditCard) -photos_factory = providers.Factory(Photo) -users_factory = providers.Factory(User, - main_photo=photos_factory, - credit_card=credit_cards_factory) - -# Creating several User objects: -user1 = users_factory(1) -# Same as: user1 = User(1, -# main_photo=Photo(), -# credit_card=CreditCard()) -user2 = users_factory(2) -# Same as: user2 = User(2, -# main_photo=Photo(), -# credit_card=CreditCard()) +class Photo: + ... -# Context keyword arguments have priority on keyword argument injections: -main_photo = Photo() -credit_card = CreditCard() +class User: + def __init__(self, uid: int, main_photo: Photo) -> None: + self.uid = uid + self.main_photo = main_photo -user3 = users_factory(3, - main_photo=main_photo, - credit_card=credit_card) -# Same as: user3 = User(3, -# main_photo=main_photo, -# credit_card=credit_card) + +photo_factory = providers.Factory(Photo) +user_factory = providers.Factory( + User, + main_photo=photo_factory, +) + + +if __name__ == '__main__': + user1 = user_factory(1) + # Same as: # user1 = User(1, main_photo=Photo()) + + user2 = user_factory(2) + # Same as: # user2 = User(2, main_photo=Photo()) + + # Context keyword arguments have a priority: + another_photo = Photo() + user3 = user_factory( + uid=3, + main_photo=another_photo, + ) + # Same as: # user3 = User(uid=3, main_photo=another_photo) diff --git a/examples/providers/factory_deep_init_injections.py b/examples/providers/factory_init_injections_underlying.py similarity index 83% rename from examples/providers/factory_deep_init_injections.py rename to examples/providers/factory_init_injections_underlying.py index 3791b906..cf49388e 100644 --- a/examples/providers/factory_deep_init_injections.py +++ b/examples/providers/factory_init_injections_underlying.py @@ -4,22 +4,22 @@ from dependency_injector import providers class Regularizer: - def __init__(self, alpha): + def __init__(self, alpha: float) -> None: self.alpha = alpha class Loss: - def __init__(self, regularizer): + def __init__(self, regularizer: Regularizer) -> None: self.regularizer = regularizer class ClassificationTask: - def __init__(self, loss): + def __init__(self, loss: Loss) -> None: self.loss = loss class Algorithm: - def __init__(self, task): + def __init__(self, task: ClassificationTask) -> None: self.task = task diff --git a/examples/providers/factory_provided_type.py b/examples/providers/factory_provided_type.py index 8009300f..7e37cfa5 100644 --- a/examples/providers/factory_provided_type.py +++ b/examples/providers/factory_provided_type.py @@ -1,30 +1,29 @@ """`Factory` specialization with limitation to provided type example.""" -import dependency_injector.providers as providers -import dependency_injector.errors as errors +from dependency_injector import providers, errors class BaseService: - """Base service class.""" + ... class SomeService(BaseService): - """Some service.""" + ... class ServiceProvider(providers.Factory): - """Service provider.""" provided_type = BaseService -# Creating service provider with correct provided type: +# Creating service provider with a correct provided type: some_service_provider = ServiceProvider(SomeService) -# Trying to create service provider incorrect provided type: +# Trying to create service provider an incorrect provided type: try: some_service_provider = ServiceProvider(object) except errors.Error as exception: print(exception) + # The output is: # can provide only # instances