From c4b33749d245dd9d650836194e60a106249a8856 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Tue, 1 Sep 2020 21:39:23 -0400 Subject: [PATCH] Providers docs update (#289) * Update callable provider docs * Update coroutine provider docs * Edit object docs * Edit list provider docs * Edit configuration provider docs * Edit selector provider docs * Fix mypy stub of the ``DeclarativeContainer`` to specify the ``__init__`` interface * Edit Dependency provider docs --- docs/images/providers/callable.png | Bin 32436 -> 0 bytes docs/images/providers/dependency.png | Bin 42660 -> 0 bytes docs/main/changelog.rst | 5 +- docs/providers/callable.rst | 73 +++----------- docs/providers/configuration.rst | 87 ++++++++++------- docs/providers/coroutine.rst | 77 ++++----------- docs/providers/dependency.rst | 44 +++------ docs/providers/list.rst | 33 +++---- docs/providers/object.rst | 15 +-- docs/providers/selector.rst | 38 ++++---- examples/providers/callable.py | 18 ++++ examples/providers/callable_args.py | 16 ---- examples/providers/callable_kwargs.py | 16 ---- examples/providers/coroutine.py | 19 ++-- examples/providers/coroutine_async_await.py | 25 ----- examples/providers/dependency.py | 101 ++++++++------------ examples/providers/list.py | 20 ++-- examples/providers/object.py | 10 +- examples/providers/selector.py | 13 +-- src/dependency_injector/containers.pyi | 1 + 20 files changed, 217 insertions(+), 394 deletions(-) delete mode 100644 docs/images/providers/callable.png delete mode 100644 docs/images/providers/dependency.png create mode 100644 examples/providers/callable.py delete mode 100644 examples/providers/callable_args.py delete mode 100644 examples/providers/callable_kwargs.py delete mode 100644 examples/providers/coroutine_async_await.py diff --git a/docs/images/providers/callable.png b/docs/images/providers/callable.png deleted file mode 100644 index f34b2a6ad1ee8f2875ada583e3d502c3522a73d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32436 zcmd42cT|&I^C*fSq98@8Nbe*x1qG?1QbP|A2%%_b0)a^HAR@g<3qnApgkB6KbWj1M z_YykNt8|cl2-RYo*WSov8Jx3f%4VW)$HtSP*4z| zrjn9UVq)U@`nss7C=?166=kog@|vAZ8XSyHOoVG`X`P*&U0oI4zI~JMjE;^T9Aps_ z6WiJ<(a=yRDT(CdIEsmJR8)8t6*-@s<=wqYqo4qQLS;EQ8NPgRUtdqhV4PZ8-#R&| z2L(ZPc0Mt20ZiXzxn#FHq%{QBFTJVxsuD-rQ^kNjR;*BD21Gd#NZ;NYOOwbjYVsj8}KaBvWV!Q8!j*R67F zWpAc&A}7AZu79a1v;pdaQ#-#npZh&rF@kF8A0tO(@jRr@X!W~B&6M94MnOX_s>Jf) zyT`$w?cay1Cuhf&v85(&KfMUgXXLyM36ik?q+pdS>s6tm=@_PH>P*eZqU|nf7A56Y zs>FGpj^fS@;1gzK-m{0=9P*~TDz5;nK$^wviP^28&4Z=2ygNIv#!C%#U7o5u5{x2%|)lQGiIDj?YYot>e*u_~0|4g<|in(TL& z^uUjHh7Or;v(XGm(*!ZP2G>wkA_^yEQzN|GdaVX^B_g_u{`(MC1!mS9)sT zHL=wg5zI24F*`Pm4DE3ktZYH>d#DX@N#Az*Or8QsIx3fRrkdmmdu}r(UZsr?I_l+5 z73z3JW%t8_c1r4n(x_U!xomxH`dO^&xutjW?Dh!h=lTK4hwERDc_@wZ7YwiEpB`*a zlaUe7_+S3K`Qz%9qj>JM(BtrOR+>l&)w1yAlkRJ1DMzUPF%gYk<(Sh{1L^#at!k%N zRTugKFK3?+DaAj>IL%(eE{=ZEUDvrBdO7=)Na;O~JJ03{ooPaS65ECC3rQlB?z#=W zPoPE^bTRmZqTBYeD7T-==|W)_Tw0J_^Dr5ZzZq?5@mgRnI`y zb@De}&T0}Vk%o(KO*LZZRX$!$R!)0ZT=8!qx->Ul6V5n%|IH~7DucU*&$d?mv2k%dzdk+h;%IVJyVAFsC_&3%Kh zD8Q&WpXb9@5X3j#f)!*Yc1U$FR!kPj~?8( zfBXF+jDuDGwpV`7m-Z`w6|yQAoPV znW|ed4RcjE73@7>_gPu!b3fkQ`g%g(Dl4iY%Y^vh?m!Rh_;9kmVb2ls`$?T@-1y`} zyLO(L!vV@eMQP-kv~Sk1Y~0CKi-6mvNNn4y-5c@=4SQ@*Z!|b(PtH;0aMV#@6{TP< zU)v?!`O|0YOls|0KveH*m}+RGM_?4n?D0l{g;QE1pODWPTVij9Z_@n5q?|IFmArfVy`OGtJowV$oA9{-E?N=>+RXZM7g>$rzun$8aZ^_zT&&{uGcd-v5^dW z?MpWhyCwj+x>AszmRgdRN9*8)j%S@m6Y396&$Pcik++e;yB_~}y+!5nf%W`P@AO&u zba9TnyOmm2Z6Ddde9W1O;j#Cbymmyd^Kq;>PuzKiHFkPs!Mn!Yn1hW&Xn*{eryGhKTz%9AMT7iRy8 zqhIO}R~Hy1IpxxJM3omXCY{jduLIloWp*huD?au;Y{puDD5ca=VIqvK|HNASC<7hG zK24y`7>>dJaSl}C)@Ma`?0aozTFFYc~q><-HHWshZkw_0MCocb4LN zO{9gOlIOR(I@+BoFG7twwA4R^P>jFgn{4$q^x0Up#9$&p0;Ny%hTCoREVwE(g5b7U7Db8FnB z5hOW_5y8^U_#C-)l=pB*eYGirk5EP(am5OoCBu?a%FvGa@kI=~)2iFd(UbOAeEPmZ z0tKDZU7lIzHvW|J_o659Mv&uhYws>ADJ1q8$J7IdgXHOkE?PfMNncL;gw0AY|B%<1 zh(Z1KaMO%L#ogJ2+ZZPMPF0Vlyn0X8ll>IMr_*Q5Hp7(K9TUhLX9QK5pqtkkZTX5r~RS9ug8@O3Yk8R}fmX$L8)pO0TaUmjx z{EY9rGz@{PUu)Q6-wfB1{=Qe`7Jz_{lEt0e>oNMJgg8Fn{9pDSRB{MF7+%2W%y*hcrBV+Ct*5^6q*(6~4_9j71TV>$c zWHEcHPCo`?7NW2Jetd^adh5>CvGK&CsrfC|eYM+O8>k`P#ZrJs3S5i|;?&{s$)0`a zsm!0+zP@8hx}tOdPL=kC-GUmFna!{3)?3!7wBY=AAn_*c+EI}^9gVW!8){|Ltk|eQ zH3bl{nw>vf$#rA*`Tp+qlrxC6_U-(rr9kyoxK@*ZQ3SVXgx9D1Gi3eC%;Dtr6Q}-( z`k?*kCFJi1t%TLpA!17*nNj|icr{t&AC!s@DX&9HgnMYxcf zH(yG6l+BdSbrZlhaxsP7qDZ4Ao}hb6t24E(rTF}Vs5F(=@*5XuQ!+*6?YQ4yz+JOn z7xl}WD_)1aba{{i6tC~qGRdvb{MQoXh}(YF-;d&W~Ddr|B#mVQaru~_iOLN535TOl^A`bi?|L3njDTRZDa?OHLt z(UgJ(!gFSRPz3zhbB9NCD?tP~+f>0R=|pynXPC?oDCZEHy`QRf31lC%t?i5QtW}Fi zw>@y11d!0xeB-E+@OJA0MDKG;+K0JJ%I|$l-)1Xiszth_xF~>@6pVgNE#aKjvA)9# zbAJ~pKf%F-J>f7h3u3l}d{wO!P0ad8}_&O$I zQQ*^u7a@?DUzNyRAvUk$4p^Ku=_3RGsLK)Q*05gl%DsW-0=x%O@OsPggmZ3RSw7pi zS?39eoCj3^?-sYy6Yq^u-yAf^C4 zAJ}g>zw^a!Jk^6o?4M4#%ove3-QL$7w|?T^-b~+i-tm)3uD99!o$Xme671WA)>$Mb zP{Sx4h|h{Tjy^6}NoZ6w;tDZ0aI-bu9P>H5JmIiORdwQbmNI>*qfam;&rMrZQWcwG ztJxn5Q(dW!HiJzK2MJmn`X_vAi)=*+0@PKm5hVaR7S4a3&Ra5jUsqkg zzw=$$cB$=>^DoXW`XiB9pqJcTJ>6>Rk*C&64%8;Kq5p#000^Mad1!xh$ zlkE}2b1uchG3ev(0l;rIQ}y1@3l_d?^AT~kWJTbo&gn=q~*Xw!mr)#9{Jz;dV`fc?BZt7E0^0L~!C15pxeYC23%slCSU4u!M`yuso&=r)*^mr%b=mdIL_; zdPAE8PJ$(cljL2)2H}aZK|^owivQK-T}=@sx~8tpn*1C`RiTuG4!g`FN{qpsCP*XS zvZfCse^J;R*@r<2!SbGEh2^fbY1SpolYC4B98gM8BA>L!Z64?w)uv;H@11ldmG@1V z7s^_snyCv&H;*7et4Gj8IoGy$7paK_>mI`YV zun&rBWlecTWq*9wTBr-O&E*U2EXIsjYyZ#?d!4{b;KtpZ5)1Px$xOJVRx;oNu-q5n z5ht0TFESTiVm0RW&?x5^f_*0B9kppVEF_Ui-lMBlpF70Y(FMA0ob^7o<(VP%*}nNL z0_U&I2Apnf3zuo-43O_{}8^(O`rp(T)M zL@$S3b9_{YD0zKZp_p8fK2#EN;azr}FimfePcD9!*;ied+<%g$iY6X*CjTaTSxN6Sy#T@fY(>UX$Efvg!$4 z6@-i}v=fgZ#jaH?`Gs~)iEE1preKpP47_zE>Rr^)Db-cew~^dIc*WbCST?_vF~KLN zD-Bh*7-6v!mNluZCgb5TE*UcOCN$`w@@!6x!6_b#J*nf@tq>1b>B#0g$padK%##=+ z$jAa?_p)bQ_p>_~CyBXnnr5~f6)Fg*Dq{FGPupQ$2)GTHcB<0|E>BayZc+Z7CKUu( z0>_0`g-2QI^84nm>x;_|`v}_c;48!AH_!aH2NtJ{V%r$}R}+Fv-SC3TKK^6f8wVbu z{*OYvu^Uz{VySX!WiEX;za|vS-Na03D%}w4i5K#q&8pgMPi?lBAJtIy_kWepeY* zEH`KKXQpc&RVur$e&=F+N4|A{$&#mK8if|93q&Q(J2ii=*S2U1L<>9dL{2FZOg)gJs? zty1G|4{9noanF8Sy|Qu{--Of3jLh%ZRJ5fsDGO}#CdEIH0E0#xrX;54;|Ibk%~dVE z#N_6bC5Wu}6T56zNBr1Lgojrh^*B)_m!#YJ||nnFhow8x29D zlr82@Zs#eh?!gC`-QH*l-Qtl=TN-% z)^!~n%?Ng6Pt}WqSx?9gGB%oTJ;f&f z$!0iNUrq91q3l)4cClfq$R!v6*1X8A=$BCl)dyASS|iqy^7if@OFKrr8IS-@9BAhD zm1V-0J$ilyS3^*ic06UDZ^8pI)c#4*#?zSu_iB1CjnqQz=?2@>5bL)|peD{xy&zzR zOh(+#RzBF;CL|CmLPcKZDe73IkyLRX}Zb{u2SZj>JECK!Mmwy6yX{5Sg!CLmwZ0d5oE#v?A@odnt9vaX3M(Ppu5~f8ccA3Ca#C zN&IGHKTmL3O1gX&(VXRH9YL&qPv7+^Vh?TT%Dm!>1u&zt7EGLeb^k+W_*QoizjY<{ zHW~YgX6_Fi1uYAsm2zjZPos`X9%?eoSo=`V~QHX^DQtu;_BY|{5L68u*O zgw*}w=TG9iUHW}G40#q9C{rJ}Iwakj>~Z;_S9GFXL|1_K82|7^5ZCETUBwr&YAB=8 zas92gt2;t~hk{(v5$uz;EL62-s(f73u5PvHXhP4@SccagXQp(tD`8|IbMttx5|P(y zo2gmtX!LeA#3fXsns2y^tj&gW`So0};6)}tV~;?_-WbR*RUh$oMN0fVQHa^2Ng)0n(m3+7ZaX? z!bm{cGJAvBSrO`2H)}-pd{v>KT1VY=woBe_$(QF5u(rMHq^~vrmW0&%FtYax0V%x1T$k*iEDSoHXx+ znXPhx`;8}zGhju8VSs|YK{#Y*>2=Pg0H1ohjBTkvK*_-G)U<|@(^kl$K#di>fO)pS zr%B@+%r$6_$gsq{p`(rub;JVU8q!N=9@@*F#m8)1U;2l*HpC*<#RUx8Omh=KG2j9X z;J9foz;fZcP~==-3 z#5e+m@EFcrMyYyd^g-PNvy7I9%3~(Kker;j;{8Uv%*nkx!?%Rx2nxWt@@wXrCR)1^ zDeqo0TG3mz8mZ|Bsivnv7fyDHpgnu6hn^cQqo@OesJcf<(3sVa8lG0#?m7rka`r!p zok51eQFV9p^jJbXHXoM451*Vsfx+`QM<-n+**q1&L@KFI?a-?RJ8d_3uF3;6L>t6xUvbU|3G!_YuQL=F@;7g&m zDdL-;kAC;p4S+;!P0m7RkWUd-^!DeiS{>_#mP~-lUDVrTvgP-rSoMWRAFq|&mFuTN z1EwEfklHqJ6s7r@;}&k6?}hbQ4M8j2nB=z^iC$ECWolZ*ncb`%R$r2`1;(G-=<)BL zwAw%>nhXm0JqEqOK*~iZsG}DA;FsG$=Li1RtZEE@Tob8c5Di)<3Fs6LVlC5R>f>jl!@4BWu9$RZ{=bG`gn~3j16)A(>rd=9|$S!R1 zl%+FJB0A6_C-+7M7#z>U#&4wg%Uh21NTigYQuz0Wf4=s2>{*LVeZ*&DI%^jztQ&Q! zLRDewiK1vI#HG^-_=xAWJ%_0vx`})kQDfgpHMCT|W~P@9YAX|7y71Qa)DMLi%G+9R zmLmXoxA|g)64s=u;6~+XHaq_wKcT6NEc2C8YQt))KG~wJZo2%wPfLfS(rO+ZV~1nk zh4!GZt5WX=`DLLD1dqZJiYS8W3EiU;7Zs|*t!N#tx&&P)3qF>AR?_yHDx~XJrR+q= zt?zO5@yRHD5>oZ(NG4A6i}npdQ=Sueg(>QjT_UF2kzX}VE01k%x%&4z*1N}H1eK|YChX)1-fBBxkD^7e3yW{?Uvmj=v5O+&g+9Rn zm*$lG0{FYs(6Hd?34Kw8Qz8fsE;m{04M~Da9Z%SJq6u59|2NHfsR`|{P59A!K^&VL zb{OsNO)=MQmY3pV8S?$h(Vc(=juHCnarz0J(G{ds73MGRCtO`lK zi0rK;fq%Z7Z6y*e$Kk2s7>I-(t9-q|{c{37WG_p8c87Ri;id`6oke1TkN;TuIw#Tk z^QXME?+GaboK%FE&70P1*lR?z1X_sH2m}&wI{$wN6}b~Xa)m}C&qn!DaBP^G`-hyV2ZAt#Q8FyeEAHi(cApED#gZ7|A*OJ5A? zhJDlpoJa;&DZ-*qhB%4_aedq+WmjPbJJdWLv{qde2?iA9)2Wa9MVByj-PuyRfepDy zIHcqT;NXo`50eChu%UYmpNr+ZJF=A5DIh7y!a`fk%{d0jWh3>=hmo|~${K06i@@=J zl#+i$-ywlh+#!VDl=Kh?q29-g(AVkC!#;&po%C(-<(p|9`VUeDa)FR;khLL&Png`J zS+RX{y9pGgk@u(q`l^l9)@hCPW#FLof2g5vvneppBL7yIu&!*2>9i`R&lq1UF^xeO z^3^XnqT5vNq|aokpvx<>(&+M};n`d6D3zT)aW;4-FG_K%%9l zwB>_@@V zGT4Z8S z_xl7FWyfN_I)j4Kwp=6BKC`|NC&xRuTp=^2GZ+yBT6Sr89{W~NkH@fRlzSq9@;{6= zM5Mt-I)KX#*1b`nj9eXrv_|JN`A2*?=tpnT5y$Y<^P|qB>1bP#1WNhq|B<4XSdj#g zjdROUfV>2$t&er2cycM;h0lJMOQ^hnHjdg<5DIy)*=0ffpZYx5wRXptWac3`Els9@ z+be5|h`&k_W*o8QXTOvH#P)1@1&IHra^KG@gZzhDK0(hAb6Etv;rbYNRWNMNtp7ka zN(*a3^l!EI_pxp4{}zd`|2?&!A;B7oIJC`6TcPZ!gp2IW8AnA#LT~+NdV}!7o;Rtl z=Ak*56yMheNOsJtm-*bYli|1F*Z-AcI42JNqp|g{72+A{M4{wJh!=!Wgm3Mr1!*`} zqFLlLu?z%1PFJWVO8mEO8Z672S4j}h{%sS9RP^DiTN28qGqd)b&`8FdXC(}ESdn;mj- zbg8uHrL6>zwN-rRtA(fBcAM&3*~HWfFQx5;23~Qb*%z31Gg$X`rduF_+*2cg0im=6!BGU9-0!)R$uu(haG#7HCxxfhmKVv!gMOUK!CIo#bk})n8r>XUt7CM zHC!sAc?6kgLJP2$#$l1CL`efeLz;T=RaP}*#eX-Vr@2%~ec*jkgL0V&rkittW^x8w zil@p5@SUTz@^py{6P85hjdbllBuka+f#|j`smmy{=VWVtV~P^NfJu+oDMjrVUVVC| zy{qTV?$(2|9@L%aprg~01<4Nk6WB7u(LCo=pf_bCIFNMf?sxzVEWB7qlDU)Kl=kA?N7EA|b2;8cMTwEAAoUxM zuPALqiR@|J z%F+yAlJahcccHI2w>gVT2PKuQ-7PU$VT;D6hsQA1-YuUSwOV#KOoEl?HcPTUlS)y? zPx4e9MHrGlVaBD~{zz5z&cD z(vL+gXuj-B?f76%UbELBZkP#4bI?}TbZ1*mP7l`#d(9`C!7TtnQ_6e+>+wH_6{0ko zM#4qDXk!KeWe@`ngR-ww39loXmg{3g>sAf7EyS3mJR}xFCL& z=4daz|H!jbr%`lc5+amGVT08zaSbEw^|lvZbCEVXfGj$A)QYl^6Lv&1k2LgwLy`fz zWnGKn;;!Y=mBwYZE$P`geR)PF(*Rya!2n*8f14|8sB*tw8SCA{9It zKQ;RvQSY9&MO1iIzUK|de)S&)^wxFE`Wh85H5_a%VSU_p&SmU=-)m%V^1YZ&Y1o>G zmkBVE-NN{|yY-xC&3Fa8ofRx6P){p>We_R4d-TW@rH|Z8WSX#6?R&Mm6Kq6`M_M<$T-P3n{Kx)d=xVX|7)5vlH?+>T-XsY23A z{DB?^AU2KVy%QFY`tl&%q(AjhoZ z5?6lCKkm&c)D7Ty{TB}ZEmP&n^u(0iYqCtIlq4U5}UsDV5M&H zI)%uxUDT$wETeQ4BF0?AupolX(NO)HlQ#dyDCGwFd2W;y}UHaWBw<*;-AN+Obf!d8OQd6H`Z7A zp8NWo=vd^sg*D$X{wup#d^mUpug%(r!mk>vW_Hk#s^&pBaPJN>n?(R~aKrGk2wzFD zeQEB6_1If@w*Qb1S=1PqKA*bs5HQ$aAc6>(Mo%q*tredo`n+=>6En6$%B1!%t^b*8 z_vT^916%HVgvEU6n!Q;}K~R|iTC~<%;A0JUQBt8-%}cIpZhD%S3&ZZE7<}cBeNIDh z$+1WgE$n^rG964=KwodkPXQyWpn-b!^zw0P-Mm>#V@H9#C)y$mzT*?wD+x1k0*fo&Uev;&rS!+gmL7)ar0j) z9rtBa5zIOWyBUBr6p#nc)HQShm|t(r_3oQK-E8~z4O@4)T;y4WH_w+cZ}2iApEPeQ zcwXf|7B)5&OdNw3-DP1AC*8NWEY9#SqDj3^Fdh*o{9xy;;Xx;;vFJ~0$J28JuY@o%)61!2?8}YF_{cqwVEp0D zwEv>uCfug%V6Y9aerY-e{p@pH!^u$6sC1DDCU5izws%=9NM>o;r3f7>O#i%^@p(OC zZXH_F(Y(Jk`^VMc@>$>Ll$aB|OEiV}abV#3iOE6!3W?{RV@z`hHX4Oyi4INM-S} zUKiH)*s3px6LyNKx(IKH5udtO5W@;@9^6|;CM7W(dV6?7oc?{@=Isl-ozy-c(-hmf zly!or0>(H;u9asv_v#6O`610c;Lh560#Gq|^Kf|ho`dVnCLC#-uMc;-asxsW4AVmAzGYp}EmR-39 z9p~PquDMmuN=E(Q3$QW+sxsE8dcwRpm^d`o%~S_G=w*bNB?C=AzbYv24Kcca3+Yj$ zCCvaZ>oR59CV(OX<)-1=3@=Ald1^Weg&$FLg95-Nv@YK;1^JmzTizYu?>3+Jk)r;L-+7%Jf5< zlyqJcEHa^E-&b{rn*bICebOBbdsa4l)T2Z!evvaCqjPXUBQhiE`WUS`O&y=mG>+VS z?Of5VJfWx90vV34{Wr+-fvImjwD@YcekLoMB1|$1oyAQfJB=M_6O{wMle?LbLezr} zltgfRcbuloFtqr>hl>M%VMndbd~wHkA@^rXCJ}y}d~|%(#Of=88j>5)4p>l<&&T1V z&En(I-I-xrxB?{A{10;5MK8EvTj7(*nM`o!6*?5ZJI-j*+AI1+Xx35%qpn6*|AKfof!qB%-;!|q8 zcd^cSaSg6^xQOc7t(QH7r{_uD?_KZS}Xld9S(X9+5KSD6Dgy> zE`L2YZCmuw_}-((OfXkk;FnubZlUG-e3-oi+LV2UwdW&(-Wg0Q#MI=+ARlCDOu00q zsu5T+(p_cjTvVX%e(2?I4-1=x`(XkiA;Hj!ULnjP)24^^mqOQa5U9bWnB|&@8=Apu)(! zIe-$o^`4NU_}k=6Sp`vR3YpE9we!Vkt@2;tdP4$^?Oig90(k-jj#S(wwQ4XzeH!difPDtaC#uYN@OaJ^ljuDsaYBZMO>PnhUE$Uz4p)`45`Z@nF_o20qtKFEiuBnPqWQZ(lB-#IdyE zm_ZklGEApkMyL7&HRd*CUnCqmD);d|S^S6xdi&%LNyqloU|yg|SPJC&ee?E$tPC;l z)z@O&`5p}~nKmY5)sYzr85j5jb@sl6SCF?Q(RacEuo!iH_dL}I9fU!(qWr7@mjec| zmyYSv>uA3NE#Ob-i%(mL!&apJUIV43{_RUm<50aqn6mWNb< z0l%ck4X$qpSggzr9z;X*4fZ}BJvtUNJUJ=e!^yOXn>-&$N?2w$kzab@8fOrp@x4Y@ zSlNbWBFn)II+zqa_!-U~Eo;CnF$P8q9mg+fS@g)G*koHz9 zF>jHfKpE>ilmrT~SK{Lmsuq-Vm1elQG1Q)ubo{+Mp*7B~_Wnd(O?mCljWG@Q*{==0 zfYr;Su1P;}zl+oA77yj_KcmN-IH8|nlCz$Hr8rSuTt)VJ8U{H0tfbJ@d)#!q@a*2I zNud&@mfaUYA#`=|L#AZI!Q3EGsXseWBDN{{RYs+0z_r(%<%PAvQuI0gcF_eO_e{vc z6ch<#t4a(OQ?-+YFK1YX8depXV$-v5ywXE=2MSaK)9~UyGYoTNBlL|?q8RZmO1B~m zSjOmc6y{xx0{kf={kfLm{xz)LUV%N~2(hFS>Y$KgVH>qV1}1lxbk@upM>WZr6jhn8dJBJ~aak!d zb%>q&_Tq-pBqsB2H~$W3JaLqICt7SgVUobaFBX&9*XTMtdk)h`IGsLD`D1oWW;%0p zx$Vsocy_pP+#;#GSF<=27>ftmuQA7ewZP!O+iM%2X>O98BeW3ESYW=|4|8qtq|RWW z?+Ui&5mx$wM(G3Ry>yc(A!-7%U(jK9KRlp-3xN$#77yMBFI8F>B7gBu72rG5o2c;Q zCxhU2Mv!Zq5WKk!rPr(bz#)9=1-eHb)#@?-h^Wcqi1U75gZ!+lG!c7LGnYGU?+3jq z2@f-qSSEXSS)m1saqHiAdisbw4fq@B8(-Eq;4+HzF!!n{t16tIRuMK2j?M zV=hm7^>78ydM(GiniIfrMemZspmpku^(*DfG$^0sHhd`k{nSV3716Jd!XC3~#6?_1 z=8Lgcw(1vRyUZsN{S5u7UhSYR(bsHg53dC*O`C^=Z4|dn#_KQJFx>g9A7D(SOP)SJ)!rQhyBWL_fhU|%a|4DORo*& z7r!+%RyjSUM`g8Scoq<6R&0qHUc)weniXuMUsj})4Hu;dkcq>X8=Dq=cQM^Ixx>4U zQeiNgi(j{@XY0F9=sL>r29f;FJHT$>f@DGM%)%<*$UFUG1v{cOCNyXqP@vrz(Hv=_ zU}wLm?Rfi~CC5TLNX59K)}OWtm1o}Ny&mx)SLGJz&`R9T{rr9^lqnTOE?5)2ktl7E z&*3(`22T`?_yt<4vn$sv?;H#X{ruy=S^~usx1{^a{)@|WWp3VZtvV!reNpYLoxON+ zo2gI!-12skSX4{3#@cn!tKDv^%t%r2EPNH z%jkmEVuG`-4xsBJYAb!ON78dYB+@cf8H-70{Um@pO~6-%tjpDv^m^XoV9?K1_UaYw z*r6~{gtF6{Qt%;xH-y)kjJu@sU_i?*FQyINMf6~#8hV#gxNO7YN0F{OY8}{?`f_$k zoLORr>r=Oa211tQ9_v5IDTSHyTlsF|DaQ%>p@=k}Loh}E3!BAJRp;Df5=jHD`(5y& zMI|JP-oGQb+ZtB+z7I8h4Uy3qoW9UPh!H~>m3p+#ByZa354HgT!$AIO!Il1}`XN7~ zuvULqZVh$DW(pIWB05-zJrSt44btNk&TP>Nc^&5C`tzhyZBKd9<2Eq)=5M(->4rTY z27JML08nkn_C|SPt?8u{@h=x^ILxg52VC|}Bb%vj!Ei?=%jeASt%nc;_MCmg^#e@_ zO5K%u_z$4rzPC@gqmW^Cd4>I#=opQ&p{Do~UjD(_A98UP6_2erC>P)VN+s`Phze`& zTy@1i+;;}uJKh5^AAU(>GpRF%4K_nVT}oX=4 zdhGji^6nQC-zpZ21We##)YP-ONLE&J&onGs!x{hHX9ZN74U@?4#~A=2HtiANq7P+x z`Bf&dK1|70^oGs&&9|&y1SRh|78&#jQ&K*%+Sb6h@UPLw&A{Jq9$0zV%^^#~pbxXlxzW{Lu`Ko$i@c4bzR`cE7;yD^v<=2L+2Sn68Hva~DNp|`XH~tCd{tp2W zXHtPz7aXQ1@|B)*nd7$!VPVCT!n<$6Y$W~(FGpSTdL>EnPgwdNpa+j6jR+^ModoMh z7(GrA5l;r6yltg?Oo-gw_)iCK@Ngpbw4Q%M(f>Pv-QG0+C!1cN{yRkdH!1yZ0_V9U zVdLksfTT70w(o62kAChvIpQm;V6X6{fk$1VnN(R!4NiHhQ)8Dq-HD+Q$UJYw-63@fvGZ?;*MR|mxX0%_hXSYK#lrI7^TbofwK2>x*q z)&?;;EC-e!98ekhdqVvvNe5H3g^c>e_|Tmr_I|l8y;dO-P7|corQhZQ51*hIGW#jv zQ6xV>n8A~tz^x0OPuc+YhTu=D-{C@q1|`OWSg)s;y@`9t6>a={h!b$FflcFLmCL%Y zGF#nvCy-I3?p?W8*C&;y9QvMDTv)rZwd|oy)ka_CHBajVo8;D9HzK2vA3d+%GKhTj zOTGNE44BoeOuteLN9#l6%o#JJH|m8t_@MA*f)4`oFnYi?s(6! z3s0ZDRD|n|U&lv~x}fk@{#6F~Yivt2k#PuGcx+3VoY}KTa1ZHT)(BXk#PY#@93w0_ z+W50zvB5~e@*z0h1?|0;&^C~YF>cg;>z&ASC{Xmg1zu|0wWwa&V3^EvP%QI7KU@5h z>>9gt@GOdE`YS#P4uZOwCOW5jiH3rTKOQ7fFc zD;LB)YYV)jeuCH1qYMWyF`_5utF)~VwGW)&LDokSC;f5jkYqn z#l=snjac9V3is_&CuhIUG_EM$j+KoBo6#A6I(HlUP6Ri`v6&@J9}duf7iEmGS^(t@8FVi1xtD;-PFgQFfFRm&BmDQjDUss6H>Vo!l0R zhQ+R?TWiq@pVDeNqvwi6MvDEe*?88TSBj+M=y$I2@{D9M!(lK)8JFa1ppk;^(_hi% ztI()>=o5*e3DC&?kX-UTKI5C$21fZ25b~h#0FJB`9C~KL?0EYB{~wzM8pl{P%hlIRS-!4EbOD z{`*+H!4q=jNI7w8@nQdzk|vf-fiIp9PJWzbg_HPp#0Tbj&`1K@E2n3f{=R2Mj-R_l z@Yf&O64C|FIv(_FG8ajQB!Uz&!0TRJPsCbp93{3`l5)4~;y4V$DK~|}R9`;nReU^g z8B8GgVrh{^>CM(?82NuCaqZ{X_SM|r&u9OYoHwRBlX*{kE>bU%Ea$6#uTs7?Oc%oS zDO{NP?=Izi8o-HJ1m;}9I&7be&g*lO3gN_b_5}zjbT68&E@tZwuqzQ;*7f@zI-v^+NC_Phdaoi%FVck& zP+I5^N|3HpK{^;hmrkf6gc902`1{@a%KY!0cW3UKH^WTkoSePSIXjzO*7~gP3Q&O@ zui^nGCeiDvy4J_fWpzyb!Cxl~*4${|ZE>s%3Rt z^Kd*%>cHtLG5&`Q51M7&W6c40k%~9m)Nq~V4?VXhQ`dGWWKW;690DUrRJqKlT)^Hq zaxFwtmav$kX%bY{e74%g*UW!uI<8sE6gWIY_2(6p@7*`m-ZLSq#uj#{D2IPi^0iAe>M|VgjEAPsDMN5^7Sx&ljuXWJDqY%VhjcyHh7#nGVKg z`G3?sep>E(Du7t#PGR4?3~-1vM|0~eCIoC%2TjQp5yI4@Vv(V+~! zCtXolg?y`7Sp@@u>hC-zVhF;f{&L+XY~GiEKJfYoF;*VrJ^o>{F?=)13Kg)_%Vyh1 zduvjOg%jUlz{2Z2#N%HiBdo^4i9pXOA+uN@#AXABh%s&fBLhb_;)a7JkD%iWL69!R zuW^ntY_q;;PTZL>bh*^3lxWR{xXx5&#xjQW1C?~vn&!kUxC z5Iz~V_WeSmnHC*rdEwNCyiIWI>7Ekxr>1=WH6;mR)!!q?BTFj|K$hfn({h;X3F1Kd ztbg|5*}?&WFmy0`u6efgAZW!4VG;DpD+72ES!rEp78ky*|54zHcz193rV#$CQn~CA zAxe`Nl6Y^^f@Th>vH#lv&((CC1QD^{DE1=gI2|uKNc5#v?@?O zRR!ltjQ|2YgqR4LEJBD3Jo>tl&e@Y#7keLFRpouwe(g2Lez+E-TzOEh)L<(qhy4wKY54! z((LBVxW8~yDzcF4p**y!G6VTK8)(UCR~ytcyl=*QOU@WGkkDqu{JUQrfl z4NMPKl4pV~7y#unbM%BZ!sxt(lO@Jm%P+1_D%8hP2>n`hTrt1+p7?^M``06O@P~-f zNqc;2b13&!NC@@|O?VpCP!-?y@5k61D6)AA`9H<))kD_t46(5j@>VI2IncM6a!L9* zHbv8?D`cnbpeyD9z|IJ|Gy_D^sYeuHJLRnyF>v9%2c`DvHj2>FueO|H(r}Hi)65w$ z1Uhu2MHCS$d6M79O;2{}DP^F_Qbc99SNFQCoHh(VPHFPOfB_fvFaZK5Q&g0HRY~bk zpysQqO9|&GvP%_AYizF^b~qQxTPAo1s2h}je5MzYBFw9w_h2XDky0Y3zWg&B@a}TZ zh-@rYKf@&h^;2vCi_uAsQDOtZ9x=se+f>k$X23n{C2+W!SN6@axp#8dVGa#P28ghj#)0wia|@SmxRQUL{iZo%`;%uppHtt8`DGWj=c38+I&Cv^cXxk{sU)&`~R z6j<8gVxtZk;bzZQ?>FEdV-{oiJOyU% z)3oUrl2(Mf0Ql59+T5lTJDb7}xqDc0k$oN9sg>CqmEy@`HOm>6)Usk1O9CJ+BVsoeZ)D z9iNX1A~=xJNT7`(w^4qXoXlSx-g-i+$)uaice*^h!^p1&>zF7dQ!Ip|Eu;Qvu;(Z{ zYbuUnEE9#K^y8NnD39E_u7WN)y==f$P-?lMZg>8qPuj8^GuY=H%Q`+NAO24{07RAB z914Y9Tj;ux<%Q10SjF}W;;qA#1mH|x?RL2wOhiES< zw6M>XkEjzP%en5SVPV|W>nPY9(2Mm$fRcUtf0tZX2zs=D61ue{2I{cCbPs(uoGfw2 zu@(L2TW}Hr#&>x zni#m{uTOQLxq}t#y}KE_M~BlPenvF7$j^ZtE@VcJr+xE{eDO6e0lQrWIW+s59HX4c2kP=V2~|X`j%14 zNM7A<@AMG;RBP_loekeAI*MU|k3XY2Fj_IpesLtJ8T+zO|8PX9By=6+xjD*!*nu-m)iIiYc>@c zys&}6DsL}6TG6S%Bz_H7h6+=dw#eq@BpIK+UB2hB8`t;Ka;Hkac>8aNRl6%`YRIq2 zb#Qxt)}F~zHK|=Oph@=dS0ZQRX5z(`&vfmgjm#+8F#-?LUE|Z!Jn}Tph3!5nW0*Fr z(SvvA0+9VxPL1tUZ0ia_PaV0nTE>$Ch#^KV#sm^Fd{x2@5EoliW`qq#&g`?TPb!!F z?xD-lG*lTm5~-Ar(qo6%iD$ls_eEfB<4NUkbs}lgJ0Is#N^li%VS}61^nE6&MT`?q zP**X1h;{y#LoyspGlxm>ltxKix>G~m@8bPz6TSd%5Br;Ib!#r*dd_oG!coKJ@h+Vf zHh*)B^*9_`Uz*<=IJmZVOgTqp7s$O?k9o~lcMttVLW0-E8y66_&`Q_7ys*fh@K%rI zksK6`B8BLl7P|HfNn~(A#f0c|!IvofL`0r{8et#HNccb!kojG~bM*dH!7TJWRbC$n zlNfS?%f?nIF+Rb+__mQ5!d{rcq_jZBmS13VcK!tJWYbUVeErs>^+qtZK(BbNrg2jR z8GQfFjBZM$x#!4N!#1p{lAiob;S#7wM8U$sMnTOQmF=v_Hum6tJ>*7Nj*tcdbC36L z%2i#9lK39F4@-=)OLj>+|LkNh*kEyixt48Cf|x;m)+kXr=RcUMVc%SZ_^!Tt*Xf*` z1od9Je3Jt_UoRhaGH*JzR&80&?Y0W#w+#~~2Gs8UR7r{ozIV&$=4o) z(IQmzZ0?g?soU+oKx}FqB~Ssj8Jo$}q|-If@ydzQ!#yU@{Rl@vJ_DH4n?B9_xIfM9 zaayk(DI0m{_~E?(Y`(HE@4Cb8|68P~ei6c`tTOegrPu z+wFTAnoR`7EFRsD!PfUVB9&SlYJ3r87Df7rG}crBpQ;|i;-~Gp=#ZG@I(DSJ<8u8* zv5%WqmBxh$Jf*|4z=SDHuxfpctV^p5t6{=bwUxZ6ksL8lO#xm`_76w#g>0;S!o?zc zdS|7Xbrv>VkRsVZVeH%!n{lHBv&b*%g=f(I#JAtC%Zhmuo%$Q>7RimaSLQi#EVgG>W@B(seW6QX#85ZmZcuQUW6>25AUHJV4u+=*vS_xI0t zG*f{F%qJUgr@)c`Ms1%M)HryEp+=-ObN*yAe(J%M$E>64}uk)!hvSr z9{r%fpwaQvDSJvsDxA#tw!!e!Lfz!l0=?*gw>-{y;~mZ9TtjXtEB<6LS>irv^T%ao zB@?$eTECeo`KV2})0vroY&|?Izc53t6qoYOL&6x7KQNH5!{`ZCfa*2}5D<>?in_nr zLCa&Hh|;d89=2heGgoGIVl|k{1p3cwc?Rxo2b}}*Rph2(Y8-rJOpSU@jh_S6YqHBt znxy=9);<8hD^t^`hUDjEkyn0oEmjWXvd7D`L4fcjMIiHwhMcf`(Yb7qqJyML{<8HA zZRu9M_Ri(C=o1KoJG-^oSk|2-vuFo8&UJ}+s@_H_^+u|V6ZZ3?fwNyMj;E<1K+9_6 z&*n_w)R=0S7#op7$Tc#Fhf8v%O@8>5SX$s#6y#?^EP=ayEN86e6VuYdCf8oT)xH>> z+BLL^Ywjk373h6&hGSD^PzgfhXl+Q)P82Y$No(8r^=IKa1ZrD}b@eE2lKjUjY zT9%z9@R0)DhpCU-cYYr(A@2U5I>)$!eA0ep};M#G1j`i4;(=r;& zXz`sT<0V@_8$tto6=#ddzu-+{|KUwTAPu;|Zl8VR!nBCRjj6?;tOxV5gdj+V^pQ9=~89^Rlhf zb#gs|?~HICEjBO%F;Ct;fR<@^%`oXe>FKETPL9Rxl)IAfca@Njh3=rlH~B zQqH+$HJHXL6kI8JRd;$Ru$W`AjLjGU#Vei95XnRF=kL#GDUF`7 z!{y0FCUhO!Z*%m5&qnUx1&vruAP#(@_uU_rlTJDt{p>|v+js+ED2Vd!x`aB#IGrzT zhn?DPi)LaohVR)EZquRgpHZRdTmLYFyRwFybyJVkT80icke;-V1x~*w(BWjS3V*e_ zQrA(Mz*mmDRU#;rRZ*R`8^&oI=vl&M%WneSA)Ht51d>Q-kUe?%wmtuRR1-OZsFt2& zcTYT5UwInjB2uSijT2oXRg|#PK+5+h^|8C*&bK2?$o0ni4d?2OqKR;sLO_|z6*KmBWvG^dQN z^ow0eA6XHDd#CueR5p35af7fE3Ry7AXgY1F0!d~}Y0~$GfvY}YelfrXPg`n6?*L-ZJ zJ@#Q8jw6{-fc~fhV;kRXc){=L7@LCYr-My~A?y8hUZF;0@)U=ba!eBiT}p1sn!Zt; zk8QQWVuNos3sOXa$qtD^L0WPmPWWoo<*#H+TXwCmvX#;D*qdV?NhSh*_b08j__@E5 zPI(n~^0ci<`2jTNn#gRXGM^cu^<%l+-RB_WqAFt0S?WQSYgK3b$Z_uXv&G_%KcQwa zL>{8-D13EadTC3S9|aR#CLVrX({eU3kk`H+l9x$p1`bqxC>wZY=0edEcjk3#lDz_Z zQ}&>F+)01_V0KMffBWb8!a|Bc+Reqcr7O#X{0#;rXl@nCC`r~pIQ#YZt0-9W;JP|t zY^|$#5_T}@&h98Ez3OfxHS?vQBjy?4T#38;!{c$O6a9JxOXrB)5&-8Ry2mY=?G9#-v!+sdxb|1CGc5VJR9Vvtf5xI0#!+Ogj@#{Da>@3~QsC{(^ZA?pl+D-6b> z<4mE=PW#5NSIW?{@KWSLQsFS4qN;AKT%Z(8x%Qutszj}ArDb0a15K$OVQt|o5mL$y&3 z!1!8RFuv7XW1MBTURJPol5u$%QBPvKcYGl00FWtC{f;0dcZtic{hCGwC5kyK=Sk@L zdWDYZv0gpm8;Yt4>+A?pHTx6|TQezv4~`~HiyH{&gwVaRHY&4}*c6Z10uY^jub+#V z1C5$z%d>_wliSTLm$yZYXF|Oe42S?m=z zB1?-?m{lLG;t;;--;znek2f-F>gBnVjCvx`9+ra07lj;cGd12`l_pNqH#G@Rx*pVy z7Y1Z%oSIInI&H7ZP{?r0XmZD#;})vVXR$Ca2z^N9u2kJo$6Fxdx+)n)KAKzoUdPFG zue}_?Nj@_raLX7K15SDQIK`fEVwq?=m2vQOUQQWbaUBmRV9=~uLsC_b`RzBBfZeEf zBEV86WIKxPP7+Tz*q09HSuf`BRoSqCtd~F<>&oFkH7;IT` z)`pJEM3b+6&^Ba5iKyrj+lW1y)s*wNAq>r2t3k%d_&62~2sm}$hSl*|=01A#V7-6Y zgb1@V(ns5&c;}WoirDmNCia=35Hi6_xs7uby8j3jQ^@d}KFDckiuD<=WQe217?%V; z7Fofixr|u%MeK2V84CJ<-yb&LJwPyi`vQ)hcou`(7NFhTo7^JlHdD`C^{l&;;6^Ty zS@y<|^Mk%JaV$MR<rL-Ab@5WmJ=O}QkOlFILELd!Ss5+WdOMNE_gYA%GilPizi1!*pAa~>yzvlKXxid zU_OEWF}1_{ab*#*{%JDH=r@7<+!8Di0yORHF%oYW-jaycek5Tb(-@DwE;~OlP*%;8 z)}tx0@`D}r0I`Y53Iy+6q-j!yeJ-n4q_*gN$w;+NWn>w8Mbk^)BMrpbUy>ESVFy|Dpg@0ar* zCUV&W1lPU$4|Q$O4I&>BI)d5K_pRwfNFGEoDrME5bk?oH&8k)#V?nYB*YVNL;6 zvqIgW>E0{M04m^B>58`esmI!@4jrG1FSF!%gsdnLx35lNSk+L>u|_J1-&8gQ1dPEL+jh*8)FLf$d8mWOn-xe!sHMqhfp|8@bhYJtiac5U9H0}3DfpiW_nBY=vlaG@Jn^6 zgBv1t^B5IyI%g;!hD~^pxB!=6mo>Wgl)u9zIvT=-Oxlq*6e`nOkG~n_T8Ff@VI8{G z-0*8#d{Tp(ZzD_4tGFS^Ym)fQo<0wZxBJEj6WtM_4Z?BA^7gc1n+h2T>obpHD^`yG zUQ)PgHKkuTS8ZwE0DgZNB1Fm`;1&Dku|fN~+*6R2e%y+{U0zYSbnO&#;hbz|dnL_t zmt^egNJWWim(^<7^baH5X=DNQ*s@W4T*h0&jBXbj`PJVKb>I&puRNrIKhpgrBQn2~ z{^T(l1bd*-my;n49jdyc#_i+j+?m<1#xyKzqqAl?l5-eT%158$_x2kX#K`ZXik(RR zQtPJ7KXH^)C=ajR>NWKN=s>Gf&CpLZZ5-F!vup@!V>Rf_B;gQ$_y#!5o00~ zI`H!6qDQTAi329gEy7XTO~vFI8Gy<4S!bhK?P|3L#k7PypVny#4WBcabdR|&41;}otv6S;@+ThIep^q$)r-SI}~l)O?MELj*=2y8 z4y72TOLs8LZA$^cfPes0l=|`mD;?_cn_QpM(@%3BQt@h29UE3_Mjb*r{wO$-Nf3L#4wK}wX)|`X?APV}EvY}4=9a}Xgh{hlywF?F3Da~8%c-&{GYL%Y$YGD8P*8_$ktx0W!bW{ zV=8Wwr^NR4=KEw7mtg{aBTQK^+oE`%_my6Z^u zXOb3wz%-GkcOVOlyYJ6o-}1ZDMUMvXLECk^J}jRT{g2!CpAM6hZ7>$W9@mY6qHy6Iuh|yFqAjP&*vBaMa!2~qJ+-8jpi}d%)zm05L=+KMJalT{KqnfkO&@Sp9T_+I6u9Ic%XoXf63=rTm`=WBGzvtGTP9=m z@yFsh(O^>D(P$Vb_dd$qQpnRt(8EyP{yUajpZTV*{FW`C;nol3rzh(|JVdDw=Q@78 zlpwAY_Cul7UfJT8$w+kes#xf9Aa0+w14Cbgiw;fxP46BqLyDuE9BHtGs=EV zTp?%}Zf}2`#vnkG+sXBjh2I#rg&!^j)x;q%UPIfpw)zw7;r?w^By79h3d*P5Nn`hS zZT62j(bAv9nZ(VeS;}2l7gN_Sl=M&pm6YqX) zz@-Lv<-#E4Gv4=;NxLM9i#GRXP{Tu03>>7*e{EWB{?n1+kz^%Z3XZ?qa%f2hOq!9r z2Pdn9?+(_}@NLA%^z|0)_J0fg|J=R9@Q*Ud|Gi+qe?7Y2Togh)1Zb;~0m26WzWP@? z4LzV$AgAyCZyE&u^(z0TRKmX$HTZ9@(B-y~DgLNM_wF#4byF15A$Bf^klNV)b>2lc zum2c>WC&tSCH-64flVF?6B#TYIaAP~?iDy0uX7l9@PczS2G}KytJ*^#gyy{vE7GDlZ465frJGPv+jM!b!9?i4a zZwau8fT?Y?Wui*On3KvIT?w7o_q7CK5W)-Q_Sxw+WYP$T=>uG)HPyDG)k=N|Zk;RP zFyXcL@rzROnPG(rVK?_$UY%wWsG72+v#T#F;xtAJmd@G$`^s0Xz8Ai}VG;VvN#&oE znuqN?dhJ_WLR4kA?k zh1%r3HL0<>WejZ!Y>|CVu<|E7$8#yJYY-%qiddOwzP*Gb;uE!O=UAS{r=1Yl#N^o8T5;j!*B3D&9FE;Px3s_`+j6Xm%c z)00z-WEIzXlQZ{XO&*!6naZ_d?9q3fAbK#NuBY>q$ISx@f=yKD&;5nZ$n%Ys|(^YL`?SlPnDHoqv z&$F30>b#*kDBULDh(TN{MM=VJ+Nb%oK%?@lM*`l%{bgBv^YBc!bf7t^j@N`#uM-2P zp5;@!dq|^vZo~5>nF~j%z66M5RJa)0OCi?BF#Z~0~{e7lsNc)1NjVEn!>3b zX1AH5>=7OgD}QMKCGAobNuRy|fO96HoB#kk`@0q5;C9sNJb_3Ewce{;KM@2GOXh() zi~@93Byx0weypLpr5A*fo|3AImkz!D8|_S_%%BhRI83*e)~Miug%~8EaL%zeCD%Oa z^(ykqpBU9oe%!l*zebd|>e@jJ;0_){Wk8XR& z)D5leHS#}x!7VXL0(Zkr*z(Vt!OUn#3+_x?U})g_liFC{aBiiBy03gDZs0yHy&NSg z=qQQ0-%lQt$LUfDj9^CmXp$1;aXg{IYv0BGgT^f=q{<3~i(!3ius-b9saZn&t@mNogDqP~e=#E?(74 zZ5RV5%)WHMIN&9kFaYowc1GpirH3E4$NTbfeOh(>rI28U=c>{0`fSMUN+hzqihf}} z<@)S~9nZCX|7)PnVCM$Dzj;rMH-?82wCn!Vvyftu^|u$oG_;fq;lc(pn2K8LjcFx6 z)tJ7MwCAwA?jyU*o)458SKoB)zw{^_`bStT<00B*cJACcwcoye{dW+-%XH)2R*s|r z6~bq)%eM;0zLTI)Axp=VrBX-{_*Y=P@SjPydyWSMp1$02{{2;YCSLuq&?XO>)rdOY z9$Ixrlw&n@o6VXx7MNQB1v%pSrvFTi>pvIk`hW0kBtkubOyeT6!-r7`oej$bC@@hN zxqivT#6vg|EkkrKazC)w#8Nh-u`y&^Zcn+#U+AHS9cLT=NqrA}C0M02r(J`+n*<3Y z;JU7E&veIASOp{oOw`aEzs<1J)lfzHt^C2I^hswedAfCwLF}6WAgfIXJ8lzQ>~G_M^l~r^c%@O+@r%Y zm)=~q-0T%SAWe9D{k0Zwg{nwfpz+swfEv4Y+JWd!y@4i5jhscEySuROJf5 zzmfyV0{~$5zjnxG0&N;kKdv#Ht|<3#05mEGRM1#!*1Y`n&55`b4r3sF!G4Bi6s%y> z-*wA`>c_Tw=Ljwx^$PHMf5}V){(0ds%`c&3dPt$?_Aw_`^7w%%8G5m-CRwM>2N%f- zq&ZX|4(mi<#vkjVd-G6L@u7%zNEOb#*ZgIWO!}TJN0T*n8|R@ak}pJs>SJdW$qQEB zJKoA28kDpJ7bqrD3>`fe3IF=p9U!0GC|S{&pahy*;!%2eqs~+FE|o|fU(AC)*$OPa zlUe?qtpJ?-Qmr^FBRbXOCtEzA{^_To)83g*ufs25aj-WoJ)x{o^O_Z{9aNH2N7t0q zzg(SA`^`kCsq#nqi0#*Ehbr-e#*$~RS+C>7c=SRlWVgrvv`Qp4U!seQB@k%&QgTO7z__i5c|#^j3uLy{g855!`dPdo{L|CO$ll*VO?dX8N)8*wFzuv ztX(wV63awN=42+~LgJ$|l3FqcP=3Lv=^g(~5F4Pk2DBF!gu%_k<>Ncdf-x?GcZF&a z8{X$)Y>|w0r}R}Apn}hU@_R7iE3$ri<2~ZjF4(LC=%0HjKx18(dAsCuf&s55ZR^!` z_PTy+e(s{Ub)T2oHU8`V z7fF-!9UCfLBy|`5sxG(h`{X{5cAy$aospTyhVm$o4uz{QQp8|6#|l}?uA;Tpz^g#6Q5b|q0E;r`pw%2*rnS>4j-%HV612~E6D!y&`-k1jI9hJjqp!? zferw`+z{`kfy*CUF1C0-A_XMD*bqOyj|Qk1V!wXT*^?c^<0nv;%NIu%R?nLK5bXSw zi`ugQZ{>D*6-zq}2haf9C-WD6;VxNOFVS#b4d6GMJt_oEN}N!I^U45_^vPb_J@i{Z zp48d-*KStkciE$^RGLY5iJcbjUmwv(H^Q=RZArTA+9QrE!L}_l;q(i>8aVDsd^hya*P9%J zQ+t>gzeW{zI``vH@U&w2E1x$ERa(snpPQ||IeQeru#jt|X5#j4Vk}R6<5M6sQB-fQG^PbNZN8i+6&l_F0RKS<{ zhc6)O(&Ro)|4h3+MauoK9@oTplaKsuUId_i(oE1+dPFw-8%+dzjm}nv)aUJ3+~XAwHcm zPAWUc@>XxWdzn*ZeJ}g$(G)k*BLmv^(GLC!>N#x36Pm0mm zy&XrCix-Cd3fTmx#dTa*0tK!C!oZcuQ9hD4twfE}icJWOX7qz2Y&)QKY9_kqLDc}W zHsjI3=sAJ30lR4O(zjdQ70yennD@Oaf|RwMM?zW~d5YDg;I<&q+{5PL7mU=QeXG^1 z64e7?l~`*6RZKorU1(^aN0%Z!nHcR9*WoBO zwB#I>JN|P)soIA#tL_HSZRzwQOCRRg))t`Mtl9n3>xFVZJk*5pT3NrLuZN6mtH|rc ziN(8o?%Mmyi{lg($h>qYy$V$rhq;=W1dR4WL}PmHFoHtvo_ z8;!3NXt5{V7r-qvfq856Izbx=TYiZ9&);jPgh^$o!-p69q-Pq7#K-|4o>yO5iaPsS z24|^$!$6#9TJ8Y-P6|N4qT-4_)TNofPW;(g@fe)kO4{=cEmYeXoFifLeX#K9ssyR3 z3l&&fE|~J2C)xFWv9=Aqx9Ok9M^gN+Fzu1GJMzXx)h`<&LOR*B(4=I8lPlsygx}i! zkoB~kPCx5gVv$=UQhk-=&+yvSiBKH9(^XLEtx2p(%b2}Lhuz-S&gDb&u68GY`KMZ1 z(ZLVDlf~z2{9sd1o=Gr;>Wa4`IGu)fE;H-C?%aK&6QAG`WsoeP8)d}KNGA@KB$==2 zk5*mg@?O^%*ZcakpfHGrmYjriqFUb7I4Ww!Ta`8oyT?IiA1umt(D%WI`UEn9>&Kh8 z9bD15FS!?+?v>cSsMzHjMR#9q)az_f1|+0G|p-p)#z>|Vi8h50_BiYa{g^MtK; z|65_%ug3-3vTtT}_7hwxg91_7Kig@4W|Vb^uv!ormpPq!WZfET?P{=}-Xx19win zoK|DsGYNl?fPp4sIr;Z|+!bLWo$hN9xutRT=|sJSX1`#RlHEsAD3_%xrql!W6ZGHf zRpg+Y7Q{a*fn1XX;~$agvYBL#U4u?KMwRS$p8BYL?Fmt=noH?BKFOuXa-#&RLZ#@g zE(qGRO3etqbV(9^MJnob@1Lzf zs1uPj&!Qq%FhwGyMRxa6l-kK2)31_ki)CW?$o zO2kA?%FA>@-v_DF9+v43vOR8VtZt5uhIdn}{H*N@*(+5Xw;5@5eRzl2a9OEt%mfnH-dIZm?9Y z0TFOS4!7M<;C%ALJXpYza2xg+RM#myZYHlKU4VA@Rd_N-$VCtS5Vgre&{!!X>i}g* z_{^w<0hTEW=Gx!J7ZsrF-Q&i6<4i_(j3J7@u>8q=!*!gae>q;en3}&>KE7CPm;tfi z0Q3#aZa~^%Ae`g{ApQ+3D~L+2{#kGkVJ<_Ws4gl45bi(aUjJE_T;xFdKZ{4N0&!v` z?}XSW!Y_d@WZBJ$!ikl(GTQI`79Q2c9^4>8{Txh7y!$K@whZ% cbF#Fv_W6$sgehm2T)d!)g2uD5r)F>d2V=P{O8@`> diff --git a/docs/images/providers/dependency.png b/docs/images/providers/dependency.png deleted file mode 100644 index dfd2f149874d8c5d3e391c4b6f52c6f7f8efa494..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42660 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 P?+>Moxk9~kE9k!frZ*Ty diff --git a/docs/main/changelog.rst b/docs/main/changelog.rst index ba3196e7..83459780 100644 --- a/docs/main/changelog.rst +++ b/docs/main/changelog.rst @@ -9,8 +9,9 @@ follows `Semantic versioning`_ Development version ------------------- -- Update ``Singleton`` provider documentation. -- Rework ``Singleton`` provider examples. +- Update documentation and rework examples for: ``Singleton``, ``Callable``, ``Coroutine``, + ``Object``, ``List``, ``Configuration``, ``Selector``, and ``Dependency`` providers. +- Fix mypy stub of the ``DeclarativeContainer`` to specify the ``__init__`` interface. 3.34.0 ------ diff --git a/docs/providers/callable.rst b/docs/providers/callable.rst index 9c82c87f..e0cb5089 100644 --- a/docs/providers/callable.rst +++ b/docs/providers/callable.rst @@ -1,69 +1,20 @@ -Callable providers ------------------- +Callable provider +----------------- + +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Function,Method,Example + :description: Callable provider helps to make dependencies injection into functions. This page + demonstrates how to use a Callable provider. .. currentmodule:: dependency_injector.providers -:py:class:`Callable` provider calls wrapped callable on every call. +:py:class:`Callable` provider calls a function, a method or another callable. -Callable providers and injections -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:py:class:`Callable` provider takes a various number of positional and keyword -arguments that are used as wrapped callable injections. Every time, when -:py:class:`Callable` provider is called, positional and keyword argument -injections would be passed as callable arguments. - -Injections are done according to the next rules: - -+ 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:`callable_providers_delegation`. -+ All other injectable values are provided *"as is"*. -+ Positional context arguments will be appended after :py:class:`Callable` - positional injections. -+ Keyword context arguments have priority on :py:class:`Callable` keyword - injections and will be merged over them. - -Example that shows usage of :py:class:`Callable` with positional argument -injections: - -.. literalinclude:: ../../examples/providers/callable_args.py +.. literalinclude:: ../../examples/providers/callable.py :language: python + :lines: 3- -Next one example shows usage of :py:class:`Callable` with keyword argument -injections: - -.. image:: /images/providers/callable.png - :width: 100% - :align: center - -.. literalinclude:: ../../examples/providers/callable_kwargs.py - :language: python - -.. _callable_providers_delegation: - -Callable providers delegation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -: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` providers delegation, please follow -:ref:`factory_providers_delegation` section for examples (with exception -of using :py:class:`DelegatedCallable` instead of -:py:class:`DelegatedFactory`). - -Abstract callable providers -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:py:class:`AbstractCallable` provider is a :py:class:`Callable` provider that -must be explicitly overridden before calling. - -Behaviour of :py:class:`AbstractCallable` providers is the same as of -:py:class:`AbstractFactory`, please follow :ref:`abstract_factory_providers` -section for examples (with exception of using :py:class:`AbstractCallable` -provider instead of :py:class:`AbstractFactory`). +``Callable`` provider handles an injection of the dependencies the same way like a +:ref:`factory-provider`. .. disqus:: diff --git a/docs/providers/configuration.rst b/docs/providers/configuration.rst index dfa20539..43fd3ee3 100644 --- a/docs/providers/configuration.rst +++ b/docs/providers/configuration.rst @@ -1,5 +1,12 @@ -Configuration providers ------------------------ +Configuration provider +---------------------- + +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Configuration,Injection, + Option,Ini,Json,Yaml,Dict,Environment Variable,Load,Read,Get + :description: Configuration provides configuration options to the other providers. This page + demonstrates how to use Configuration provider to inject the dependencies, load + a configuration from an ini or yaml file, dictionary or an environment variable. .. currentmodule:: dependency_injector.providers @@ -10,13 +17,13 @@ Configuration providers :emphasize-lines: 4,9-10 :lines: 4-14 -It implements "use first, define later" principle. +It implements the principle "use first, define later". -Loading from ``ini`` file -~~~~~~~~~~~~~~~~~~~~~~~~~ +Loading from an INI file +~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`Configuration` provider can load configuration from ``ini`` file using -:py:meth:`Configuration.from_ini`: +``Configuration`` provider can load configuration from an ``ini`` file using the +:py:meth:`Configuration.from_ini` method: .. literalinclude:: ../../examples/providers/configuration/configuration_ini.py :language: python @@ -28,15 +35,15 @@ where ``examples/providers/configuration/config.ini`` is: .. literalinclude:: ../../examples/providers/configuration/config.ini :language: ini -:py:meth:`Configuration.from_ini` supports environment variables interpolation. Use -``${ENV_NAME}`` format in the configuration file to substitute value of environment +:py:meth:`Configuration.from_ini` method supports environment variables interpolation. Use +``${ENV_NAME}`` format in the configuration file to substitute value of the environment variable ``ENV_NAME``. -Loading from ``yaml`` file -~~~~~~~~~~~~~~~~~~~~~~~~~~ +Loading from a YAML file +~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`Configuration` provider can load configuration from ``yaml`` file using -:py:meth:`Configuration.from_yaml`: +``Configuration`` provider can load configuration from a ``yaml`` file using the +:py:meth:`Configuration.from_yaml` method: .. literalinclude:: ../../examples/providers/configuration/configuration_yaml.py :language: python @@ -48,43 +55,51 @@ where ``examples/providers/configuration/config.yml`` is: .. literalinclude:: ../../examples/providers/configuration/config.yml :language: ini -:py:meth:`Configuration.from_yaml` supports environment variables interpolation. Use -``${ENV_NAME}`` format in the configuration file to substitute value of environment +:py:meth:`Configuration.from_yaml` method supports environment variables interpolation. Use +``${ENV_NAME}`` format in the configuration file to substitute value of the environment variable ``ENV_NAME``. .. note:: - Loading configuration from yaml requires ``PyYAML`` package. You can install - `Dependency Injector` with extras ``pip install dependency-injector[yaml]`` or install - ``PyYAML`` separately ``pip install pyyaml``. + Loading of a yaml configuration requires ``PyYAML`` package. -Loading from ``dict`` -~~~~~~~~~~~~~~~~~~~~~ + You can install the ``Dependency Injector`` with an extra dependency:: -:py:class:`Configuration` provider can load configuration from Python ``dict`` using -:py:meth:`Configuration.from_dict`: + pip install dependency-injector[yaml] + + or install ``PyYAML`` directly:: + + pip install pyyaml + + *Don't forget to mirror the changes in the requirements file.* + +Loading from a dictionary +~~~~~~~~~~~~~~~~~~~~~~~~~ + +``Configuration`` provider can load configuration from a Python ``dict`` using the +:py:meth:`Configuration.from_dict` method: .. literalinclude:: ../../examples/providers/configuration/configuration_dict.py :language: python :lines: 3-5,6- :emphasize-lines: 6-13 -Loading from environment variable -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Loading from an environment variable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`Configuration` provider can load configuration from environment variable using -:py:meth:`Configuration.from_env`: +``Configuration`` provider can load configuration from an environment variable using the +:py:meth:`Configuration.from_env` method: .. literalinclude:: ../../examples/providers/configuration/configuration_env.py :language: python :lines: 5-7,13-21 :emphasize-lines: 6-8 -Loading from multiple sources -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Loading from the multiple sources +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`Configuration` provider can load configuration from multiple sources. Loaded -configuration is merged recursively over existing configuration. +``Configuration`` provider can load configuration from the multiple sources. Loaded +configuration is merged recursively over the existing configuration. .. literalinclude:: ../../examples/providers/configuration/configuration_multiple.py :language: python @@ -96,12 +111,12 @@ where ``examples/providers/configuration/config.local.yml`` is: .. literalinclude:: ../../examples/providers/configuration/config.local.yml :language: ini -Specifying value type -~~~~~~~~~~~~~~~~~~~~~ +Specifying the value type +~~~~~~~~~~~~~~~~~~~~~~~~~ You can specify the type of the injected configuration value explicitly. -This helps when you read the value from the ini file or the environment variable and need to +This helps when you read the value from an ini file or an environment variable and need to convert it into an ``int`` or a ``float``. .. literalinclude:: ../../examples/providers/configuration/configuration_type.py @@ -109,20 +124,20 @@ convert it into an ``int`` or a ``float``. :lines: 3- :emphasize-lines: 17 -:py:class:`Configuration` provider has next helper methods: +``Configuration`` provider has next helper methods: - ``.as_int()`` - ``.as_float()`` - ``.as_(callback, *args, **kwargs)`` -The last method ``.as_(callback, *args, **kwargs)`` helps to implement a other conversions. +The last method ``.as_(callback, *args, **kwargs)`` helps to implement other conversions. .. literalinclude:: ../../examples/providers/configuration/configuration_type_custom.py :language: python :lines: 3- :emphasize-lines: 16 -With the ``.as_(callback, *args, **kwargs)`` you can specify the function that will be called +With the ``.as_(callback, *args, **kwargs)`` you can specify a function that will be called before the injection. The value from the config will be passed as a first argument. The returned value will be injected. Parameters ``*args`` and ``**kwargs`` are handled as any other injections. diff --git a/docs/providers/coroutine.rst b/docs/providers/coroutine.rst index 303e420e..3db7846a 100644 --- a/docs/providers/coroutine.rst +++ b/docs/providers/coroutine.rst @@ -1,72 +1,27 @@ -Coroutine providers -------------------- +Coroutine provider +------------------ + +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Coroutine,Asynchronous, + Asyncio,Example + :description: Coroutine provider creates a coroutine. This page demonstrates how to use a + Coroutine provider. .. currentmodule:: dependency_injector.providers -:py:class:`Coroutine` provider create wrapped coroutine on every call. +:py:class:`Coroutine` provider creates a coroutine. -:py:class:`Coroutine` provider is designed for making better integration with -``asyncio`` coroutines. In particular, :py:class:`Coroutine` provider returns -``True`` for ``asyncio.iscoroutinefunction()`` checks. - -.. note:: - - :py:class:`Coroutine` provider works only for Python 3.4+. - -Example of usage :py:class:`Coroutine` provider with ``async / await``-based -coroutine: - -.. literalinclude:: ../../examples/providers/coroutine_async_await.py +.. literalinclude:: ../../examples/providers/coroutine.py :language: python - -Coroutine providers and injections -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:py:class:`Coroutine` provider takes a various number of positional and keyword -arguments that are used as wrapped coroutine injections. Every time, when -:py:class:`Coroutine` provider is called, positional and keyword argument -injections would be passed as coroutine arguments. - -Injections are done according to the next rules: - -+ 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:`coroutine_providers_delegation`. -+ All other injectable values are provided *"as is"*. -+ Positional context arguments will be appended after :py:class:`Coroutine` - positional injections. -+ Keyword context arguments have priority on :py:class:`Coroutine` keyword - injections and will be merged over them. + :lines: 3- .. note:: + The example works on Python 3.7+. For earlier versions use ``loop.run_until_complete()``. - Examples of making injections could be found in API docs - - :py:class:`Coroutine`. +``Coroutine`` provider handles an injection of the dependencies the same way like a +:ref:`factory-provider`. -.. _coroutine_providers_delegation: - -Coroutine providers delegation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:py:class:`Coroutine` provider could be delegated to any other provider via -any kind of injection. - -Delegation of :py:class:`Coroutine` providers is the same as -:py:class:`Factory` providers delegation, please follow -:ref:`factory_providers_delegation` section for examples (with exception -of using :py:class:`DelegatedCoroutine` instead of -:py:class:`DelegatedFactory`). - -Abstract coroutine providers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:py:class:`AbstractCoroutine` provider is a :py:class:`Coroutine` provider that -must be explicitly overridden before calling. - -Behaviour of :py:class:`AbstractCoroutine` providers is the same as of -:py:class:`AbstractFactory`, please follow :ref:`abstract_factory_providers` -section for examples (with exception of using :py:class:`AbstractCoroutine` -provider instead of :py:class:`AbstractFactory`). +.. note:: + ``Coroutine`` provider returns ``True`` for ``asyncio.iscoroutinefunction()`` check. .. disqus:: diff --git a/docs/providers/dependency.rst b/docs/providers/dependency.rst index 4bd9bf2f..9ce3977b 100644 --- a/docs/providers/dependency.rst +++ b/docs/providers/dependency.rst @@ -1,43 +1,21 @@ -Dependency providers --------------------- +Dependency provider +------------------- .. currentmodule:: dependency_injector.providers -:py:class:`Dependency` provider can be useful for development of -self-sufficient libraries / modules / applications that have required external -dependencies. +:py:class:`Dependency` provider is a placeholder for the dependency of the specified type. -For example, you have created self-sufficient library / module / application, -that has dependency on *database connection*. +The first argument of the ``Dependency`` provider specifies a type of the dependency. It is +called ``instance_of``. ``Dependency`` provider controls the type of the returned object to be an +instance of the ``instance_of`` type. -Second step you want to do is to make this software component to be easy -reusable by wide amount of developers and to be easily integrated into many -applications. - -It may be good idea, to move all external dependencies (like -*database connection*) to the top level and make them to be injected on your -software component's initialization. It will make third party developers feel -themselves free about integration of your component in their applications, -because they would be able to find right place / right way for doing this -in their application's architectures. - -At the same time, you can be sure, that your external dependency will be -satisfied with appropriate instance. - -Example: - -.. note:: - - Class ``UsersService`` is a part of some library. ``UsersService`` has - dependency on database connection, which can be satisfied with any - DBAPI 2.0 database connection. Being a self-sufficient library, - ``UsersService`` doesn't hardcode any kind of database management logic. - Instead of this, ``UsersService`` has external dependency, that has to - be satisfied by client's code, out of library's scope. - -.. image:: /images/providers/dependency.png +The ``Dependency`` provider must be overridden before usage. It can be overridden by any type of +the provider. The only rule is that overriding provider must return an instance of ``instance_of`` +dependency type. .. literalinclude:: ../../examples/providers/dependency.py :language: python + :lines: 3- + :emphasize-lines: 26 .. disqus:: diff --git a/docs/providers/list.rst b/docs/providers/list.rst index 4b92eeca..9ad4ece4 100644 --- a/docs/providers/list.rst +++ b/docs/providers/list.rst @@ -1,5 +1,10 @@ -List providers --------------- +List provider +------------- + +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,List,Injection + :description: List provider helps to inject a list of the dependencies. This page demonstrates + how to use a List provider. .. currentmodule:: dependency_injector.providers @@ -7,28 +12,12 @@ List providers .. literalinclude:: ../../examples/providers/list.py :language: python - :emphasize-lines: 6-9 - :lines: 6-8, 23-29 - -:py:class:`List` provider is needed for injecting a list of dependencies. It handles -positional argument injections the same way as :py:class:`Factory` provider: - -+ 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 explicitly. Check out - :ref:`factory_providers_delegation`. -+ All other values are injected *"as is"*. -+ Positional context arguments will be appended after :py:class:`List` positional injections. - -Full example: - -.. literalinclude:: ../../examples/providers/list.py - :language: python - :emphasize-lines: 23-26 :lines: 3- + :emphasize-lines: 19-22 + +``List`` provider handles positional arguments the same way as a :ref:`factory-provider`. .. note:: - - Keyword argument injections are not supported. + Keyword argument are not supported. .. disqus:: diff --git a/docs/providers/object.rst b/docs/providers/object.rst index 6599dd92..800b8116 100644 --- a/docs/providers/object.rst +++ b/docs/providers/object.rst @@ -1,14 +1,17 @@ -Object providers ----------------- +Object provider +--------------- + +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Object + :description: Object provider provides an object "as is". This page demonstrates how to use an + Object provider. .. currentmodule:: dependency_injector.providers -:py:class:`Object` provider returns provided instance "as is". - -Example: +:py:class:`Object` provider returns an object "as is". .. literalinclude:: ../../examples/providers/object.py :language: python - + :lines: 3- .. disqus:: diff --git a/docs/providers/selector.rst b/docs/providers/selector.rst index 29867217..f7b0a9e7 100644 --- a/docs/providers/selector.rst +++ b/docs/providers/selector.rst @@ -3,29 +3,31 @@ Selector providers ------------------ +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Configuration,Injection, + Selector,Polymorphism,Environment Variable,Flexibility + :description: Selector selects provider based on a configuration value or another callable. + This page demonstrates how to implement the polymorphism and increase the + flexibility of your application using the Selector provider. + .. currentmodule:: dependency_injector.providers -:py:class:`Selector` provider selects provider based on the configuration value or other callable. +:py:class:`Selector` provider selects provider based on a configuration value or another callable. .. literalinclude:: ../../examples/providers/selector.py :language: python - :emphasize-lines: 6-10 - :lines: 3-5,14-20 - -:py:class:`Selector` provider has a callable called ``selector`` and a dictionary of providers. - -The ``selector`` callable is provided as a first positional argument. It can be -:py:class:`Configuration` provider or any other callable. It has to return a string value. -This value is used as a key for selecting the provider from the dictionary of providers. - -The providers are provided as keyword arguments. Argument name is used as a key for -selecting the provider. - -Full example: - -.. literalinclude:: ../../examples/providers/selector.py - :language: python - :emphasize-lines: 14-18 :lines: 3- + :emphasize-lines: 14-18 + +The first argument of the ``Selector`` provider is called ``selector``. It can be an option of +a ``Configuration`` provider or any other callable. The ``selector`` callable has to return a +string value. This value is used as a key for selecting the provider. + +The providers are provided as keyword arguments. Argument name is used as a key for selecting the +provider. + +When a ``Selector`` provider is called, it gets a ``selector`` value and delegates the work to +the provider with a matching name. The ``selector`` callable works as a switch: when the returned +value is changed the ``Selector`` provider will delegate the work to another provider. .. disqus:: diff --git a/examples/providers/callable.py b/examples/providers/callable.py new file mode 100644 index 00000000..40e0d363 --- /dev/null +++ b/examples/providers/callable.py @@ -0,0 +1,18 @@ +"""`Callable` provider example.""" + +import passlib.hash + +from dependency_injector import providers + + +password_hasher = providers.Callable( + passlib.hash.sha256_crypt.hash, + salt_size=16, + rounds=10000, +) +password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify) + + +if __name__ == '__main__': + hashed_password = password_hasher('super secret') + assert password_verifier('super secret', hashed_password) diff --git a/examples/providers/callable_args.py b/examples/providers/callable_args.py deleted file mode 100644 index a4292de4..00000000 --- a/examples/providers/callable_args.py +++ /dev/null @@ -1,16 +0,0 @@ -"""`Callable` providers with positional arguments example.""" - -import dependency_injector.providers as providers - - -# Creating even and odd filter providers: -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 range() and filter providers: -even_range = even_filter(range(1, 10)) -odd_range = odd_filter(range(1, 10)) - -# Making some asserts: -assert even_range == [2, 4, 6, 8] -assert odd_range == [1, 3, 5, 7, 9] diff --git a/examples/providers/callable_kwargs.py b/examples/providers/callable_kwargs.py deleted file mode 100644 index a6b89990..00000000 --- a/examples/providers/callable_kwargs.py +++ /dev/null @@ -1,16 +0,0 @@ -"""`Callable` providers with keyword arguments example.""" - -import passlib.hash - -import dependency_injector.providers as providers - - -# Password hasher and verifier providers: -password_hasher = providers.Callable(passlib.hash.sha256_crypt.encrypt, - salt_size=16, - rounds=10000) -password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify) - -# Making some asserts: -hashed_password = password_hasher('super secret') -assert password_verifier('super secret', hashed_password) diff --git a/examples/providers/coroutine.py b/examples/providers/coroutine.py index 054173ca..98767295 100644 --- a/examples/providers/coroutine.py +++ b/examples/providers/coroutine.py @@ -1,26 +1,19 @@ -"""`Coroutine` providers example with @asyncio.coroutine decorator. - -Current example works only fot Python 3.4+. -""" +"""`Coroutine` providers example with async / await syntax.""" import asyncio -import dependency_injector.providers as providers +from dependency_injector import providers -@asyncio.coroutine -def coroutine_function(arg1, arg2): - """Sample coroutine function.""" - yield from asyncio.sleep(0.1) +async def coroutine(arg1, arg2): + await asyncio.sleep(0.1) return arg1, arg2 -coroutine_provider = providers.Coroutine(coroutine_function, arg1=1, arg2=2) +coroutine_provider = providers.Coroutine(coroutine, arg1=1, arg2=2) if __name__ == '__main__': - loop = asyncio.get_event_loop() - arg1, arg2 = loop.run_until_complete(coroutine_provider()) - + arg1, arg2 = asyncio.run(coroutine_provider()) assert (arg1, arg2) == (1, 2) assert asyncio.iscoroutinefunction(coroutine_provider) diff --git a/examples/providers/coroutine_async_await.py b/examples/providers/coroutine_async_await.py deleted file mode 100644 index cca13c26..00000000 --- a/examples/providers/coroutine_async_await.py +++ /dev/null @@ -1,25 +0,0 @@ -"""`Coroutine` providers example with async / await syntax. - -Current example works only fot Python 3.5+. -""" - -import asyncio - -import dependency_injector.providers as providers - - -async def coroutine_function(arg1, arg2): - """Sample coroutine function.""" - await asyncio.sleep(0.1) - return arg1, arg2 - - -coroutine_provider = providers.Coroutine(coroutine_function, arg1=1, arg2=2) - - -if __name__ == '__main__': - loop = asyncio.get_event_loop() - arg1, arg2 = loop.run_until_complete(coroutine_provider()) - - assert (arg1, arg2) == (1, 2) - assert asyncio.iscoroutinefunction(coroutine_provider) diff --git a/examples/providers/dependency.py b/examples/providers/dependency.py index a96aa58d..a1114cba 100644 --- a/examples/providers/dependency.py +++ b/examples/providers/dependency.py @@ -1,73 +1,50 @@ -"""`Dependency` providers example.""" +"""`Dependency` provider example.""" -import sqlite3 -import contextlib +import abc +import dataclasses -import dependency_injector.providers as providers +from dependency_injector import containers, providers, errors -class UsersService: - """Example class UsersService. - - UsersService has dependency on DBAPI 2.0 database connection. - """ - - def __init__(self, database): - """Initialize instance. - - :param database: Database connection. - :type database: sqlite3.dbapi2.Connection - """ - self.database = database - self.database.row_factory = sqlite3.dbapi2.Row - - def init_database(self): - """Initialize database, if it has not been initialized yet.""" - with contextlib.closing(self.database.cursor()) as cursor: - cursor.execute(""" - CREATE TABLE IF NOT EXISTS users( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name VARCHAR(32) - ) - """) - - def create(self, name): - """Create user with provided name and return his id.""" - with contextlib.closing(self.database.cursor()) as cursor: - cursor.execute('INSERT INTO users(name) VALUES (?)', (name,)) - return cursor.lastrowid - - def get_by_id(self, id): - """Return user info by user id.""" - with contextlib.closing(self.database.cursor()) as cursor: - cursor.execute('SELECT id, name FROM users WHERE id=?', (id,)) - return cursor.fetchone() +class DbAdapter(metaclass=abc.ABCMeta): + ... -# Database and UsersService providers: -database = providers.Dependency(instance_of=sqlite3.dbapi2.Connection) -users_service_factory = providers.Factory(UsersService, - database=database) +class SqliteDbAdapter(DbAdapter): + ... -# Out of library's scope. -# -# Setting database provider: -database.provided_by(providers.Singleton(sqlite3.dbapi2.Connection, - database=':memory:', - timeout=30, - detect_types=True, - isolation_level='EXCLUSIVE')) -# Creating UsersService instance: -users_service = users_service_factory() +class PostgresDbAdapter(DbAdapter): + ... -# Initializing UsersService database: -users_service.init_database() -# Creating test user and retrieving full information about him: -test_user_id = users_service.create(name='test_user') -test_user = users_service.get_by_id(test_user_id) +@dataclasses.dataclass +class UserService: + database: DbAdapter -# Making some asserts: -assert test_user['id'] == 1 -assert test_user['name'] == 'test_user' + +class Container(containers.DeclarativeContainer): + + database = providers.Dependency(instance_of=DbAdapter) + + user_service = providers.Factory( + UserService, + database=database, + ) + + +if __name__ == '__main__': + container1 = Container(database=providers.Singleton(SqliteDbAdapter)) + container2 = Container(database=providers.Singleton(PostgresDbAdapter)) + + assert isinstance(container1.user_service().database, SqliteDbAdapter) + assert isinstance(container2.user_service().database, PostgresDbAdapter) + + container3 = Container(database=providers.Singleton(object)) + try: + container3.user_service() + except errors.Error as exception: + print(exception) + # The output is: + # is not an + # instance of diff --git a/examples/providers/list.py b/examples/providers/list.py index cbf33bd6..1d2eb474 100644 --- a/examples/providers/list.py +++ b/examples/providers/list.py @@ -8,15 +8,11 @@ from dependency_injector import providers @dataclasses.dataclass class Module: - """Example module.""" - name: str @dataclasses.dataclass class Dispatcher: - """Example dispatcher.""" - modules: List[Module] @@ -28,6 +24,7 @@ dispatcher_factory = providers.Factory( ), ) + if __name__ == '__main__': dispatcher = dispatcher_factory() @@ -35,11 +32,10 @@ if __name__ == '__main__': assert dispatcher.modules[0].name == 'm1' assert dispatcher.modules[1].name == 'm2' - # Call of dispatcher_factory() is equivalent to: - - dispatcher = Dispatcher( - modules=[ - Module(name='m1'), - Module(name='m2'), - ], - ) + # Call "dispatcher = dispatcher_factory()" is an equivalent for: + # dispatcher = Dispatcher( + # modules=[ + # Module(name='m1'), + # Module(name='m2'), + # ], + # ) diff --git a/examples/providers/object.py b/examples/providers/object.py index f3fa6693..7da9cb26 100644 --- a/examples/providers/object.py +++ b/examples/providers/object.py @@ -1,10 +1,10 @@ -"""Object providers example.""" +"""`Object` provider example.""" -import dependency_injector.providers as providers +from dependency_injector import providers -# Creating object provider: object_provider = providers.Object(1) -# Making some asserts: -assert object_provider() == 1 + +if __name__ == '__main__': + assert object_provider() == 1 diff --git a/examples/providers/selector.py b/examples/providers/selector.py index 9c3036bc..7c7c17cd 100644 --- a/examples/providers/selector.py +++ b/examples/providers/selector.py @@ -19,10 +19,11 @@ selector = providers.Selector( another=providers.Factory(SomeOtherClass), ) -config.override({'one_or_another': 'one'}) -instance_1 = selector() -assert isinstance(instance_1, SomeClass) +if __name__ == '__main__': + config.override({'one_or_another': 'one'}) + instance_1 = selector() + assert isinstance(instance_1, SomeClass) -config.override({'one_or_another': 'another'}) -instance_2 = selector() -assert isinstance(instance_2, SomeOtherClass) + config.override({'one_or_another': 'another'}) + instance_2 = selector() + assert isinstance(instance_2, SomeOtherClass) diff --git a/src/dependency_injector/containers.pyi b/src/dependency_injector/containers.pyi index 9c2798fb..62117b43 100644 --- a/src/dependency_injector/containers.pyi +++ b/src/dependency_injector/containers.pyi @@ -24,6 +24,7 @@ class DynamicContainer(Container): ... class DeclarativeContainer(Container): cls_providers: ClassVar[Dict[str, Provider]] inherited_providers: ClassVar[Dict[str, Provider]] + def __init__(self, **overriding_providers: Provider) -> None: ... def override(container: Container) -> _Callable[[Container], Container]: ...