From 76f2b67d38ad3ab6634f0a843d029d40f9889301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 14 Dec 2018 20:35:36 +0400 Subject: [PATCH] :memo: Add tutorial for body nested models --- .../tutorial/body-nested-models/image01.png | Bin 0 -> 40992 bytes docs/tutorial/body-nested-models.md | 213 ++++++++++++++++++ .../src/body-nested-models/tutorial001.py | 18 ++ .../src/body-nested-models/tutorial002.py | 20 ++ .../src/body-nested-models/tutorial003.py | 20 ++ .../src/body-nested-models/tutorial004.py | 26 +++ .../src/body-nested-models/tutorial005.py | 27 +++ .../src/body-nested-models/tutorial006.py | 27 +++ .../src/body-nested-models/tutorial007.py | 33 +++ .../src/body-nested-models/tutorial008.py | 17 ++ mkdocs.yml | 1 + 11 files changed, 402 insertions(+) create mode 100644 docs/img/tutorial/body-nested-models/image01.png create mode 100644 docs/tutorial/body-nested-models.md create mode 100644 docs/tutorial/src/body-nested-models/tutorial001.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial002.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial003.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial004.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial005.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial006.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial007.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial008.py diff --git a/docs/img/tutorial/body-nested-models/image01.png b/docs/img/tutorial/body-nested-models/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..f3644ce792ea70e1e1f701c99291aaef7e83172a GIT binary patch literal 40992 zcmb4rbwC`;-euefngo{wcXtgi=pey^hv4pRF<|hEJ0uWvkl;RpI}Gj;+!=h(VVis3 zecyZgzWsK$|EZpIQ`%K^&hMN`@H-_L%xA>U?%cV9DJKh3y>sV&!JRvI51-rv{>4`B z=LL}5cb1S-fAZwX%%bvd;3tlY)O!~-dovezBPY{4Y8I|8E~ZY#Uk0Dvx%2vt97tT< zV|r)KUr)_Eo$sooMIhvJ%c6`bhq!kIX5|YT5;N*F-olZ0kL#cw?jOwT>O@!E9_?^f zG0j~DdhWH)$)x+fI?ey3R#r5;`E6IJii^E5V1O{kSTMeVho7g2R*i<~r-f?b18VxG zTLRw^6c5@8EXLHK87RXyVgs(lNP+Hc=VHCu#F(fkaiFeu?zjim(%-$kd5ykp(tjj= z0ZZiQ8J-!m?=p$KosVnGmvccB$Y6AG{5@l&9o0_On3$L6*JED(eM7n0+YAm+n&te^ z_XO+HX7e?R1Z*~_5JTH#pUsG>j!crcrWS*sxiPYcJyzxCWINYqUHK_ag`9r-*BS7$ z-z`v|s^Jf1iO+jTv{=X146DZ0!29Em@7$?TYnQek!4^IH9ZdsPRaI?S+%NGvfm)n? zkps*AjA{*%>1->x#(nC>GvO*#9~Hb;jdEGQr`y+3Wd&+f6W$j*Uk9I>n#xtqPy&Nv zx=mC<;bB$3Ps~|2#66J3>%?@AKTXL%CkU`%_E=1z&e@iIZQp&BPflSRA!^qjH012O zyzs)0Jr_KU5yh?dRQh@teGk5%ODm2?aZv+bpZcd|D2aF*76`cP92PNQ<^hpf! zZL1O+O_Y zu3(6lZVxZdWlmjQF}IeprrJA=JWYoc_rxtLA>kMS!%W7aLi(;H`bpc(=iAR{)}jj{ zw1Xs!H8ro#re1+SRO2^Cv)iA$z15B;#zaMj6d97Dm%Zo7buLB^!%AUmMdR3k7R}2K z+596#`T3PADJ}1Ex%FM3nc!Pu9Oq>Zhw1pNv`ShI=&%aHgCj|?%ge^4z-a$b8ohVLk$yJ{z6&-J%<^CJ#djwQ`Rd?jU8X%!AnFO? z=U%os%;^$-_UJ@@X@#o2RYi_|F)#B4DLE@~w^OUjAU2V8vX9Z~sA$;=_M3XddZ*7X-*vEzF=vL3 z#>JPtHjH>|B^+ED)f=Wt-|d3R?f6N9!h?8qk>klS$+h&}sy*Hl%oH62 z9eZvz)BBj*IJb(&5Qs;b^diy*Le0-Bpi85vCA|Bjdt!W4%kDJJzVuNr{h)!$pweNc zbk=DoW~p{^-*it|-FF*XMPE~-f2sx14rWbi~iykjAgKf@Fbc8d_lk=blFmqk$j*&Aqr zO)g}K+;^|rHQ%?N2k8>Z;NPf%y23CX)785_LZYCCFLo$*q^XM{Oev*w4YT;|dUP?t zu>5#op{zy!dgT873HJ>)T~^kGcR#YL1i!X}4?+}dO+v~iHMI2J$rSX%3#0T87;k63 zoo@AI4|eH}tn$&e?|tJJOTo(&NHJE`VPl=CMB9=nKc76Y{pM3&R{5I&D#sWEx!}^S z$d-sOzoA?U(i6=sCsPCHn6oHZbrP94<&e2$C5HAx zoxKo}oytVpyHTKw$`Q$i5IV{wCl~D%cA_G?48)k7O+9StxdeQ|m3z?lICju~XBqve z+)!2_gFJuNf1U4|4$_8}gwKdY<=4|iLGX~CJAO`$rkCH%T{bK-&M{HJ-U(t=9&5Cb z@T0A}6NBIQ-3li5$j*8q1n8FOH%f(kK7T?i|KfG8IS>Vwlutsm=!l@mQ$w7F#BZY& z2cKa-y4XuS8qC>wT?N;JUx1b~WvL@xC_+GemBo~cRg;a+(jw?6P16I9-V5b+1_l`U zzvg6+IKKGO#!!4#F7Sr%SjH~k;YaPKlAyzE&O`T0N|C1*4XrIFvGS=n!62j5Z%--l z+Mj;>NbAiO7KWwRZ$-F4k^M6^02CV^E1z{=hK{mCl$bE{TfpXe3I4Yil8usl%Zc7L z@pi?(2Grq|!|#$yqB%WM?%%o7l=i}3?j>FE;<`ho!yM)%vu311mKtZl7t&(yY8D6d zoA~T}*$%wYYAa!5v-yuX_8omytz6bD3bQ{cD7~hk$EIUBN|CR}Hnzif&Q%+RfUn?p zL@=CSwS4GD)MNlSni4lcPCK4gbX3esB;}>->(iyUihEUabDWCea-Wl3b!?i6Hu($& zWO9VqoeXFnG{CGeCL8^tO?#+B7FR+{cm;WkX&8utWB82mS(R`eMPlO&{qDk{Vb&uh z+B3xmt692ya9HY*`9w><6)d*nJT;v{Qbic%)-!4%2TL5(Za4vIgyWBVNrjxb!l;d7L}D#*LJZk(vRXE#VdtsO7j&C&PJndS>GR4rO7wYQG>6vN-V(xu3#NS<}I z@=;@8YQ4GHGTVq9s+!qy=PZtWj;J? ztNi(@3B8?5uI;I=7V{{!>sB`?Q*4pT zds2eFdpLo+ni)AQ?^$154OGYG66h|HiCT5W4+Ry zt^{AncmJ@sEqr=uE1FtxWWjkOPOHR0Gw{>&id&-C}N<}F@P-M|1a${bS zZ=(jiaazS=cp1M>lVaT)v&^u9nk2DS;PSu3|CKyF`pV0An-(7<0~prX;LMsm8Y#wRgY}n=O2F*7Gn;zmEu%){HoDq=iAu3nOsD64fmn}Ai0fU_HmaGhE4Flc zeSHgt`WQoED1a1LBYB)v{)9(wuO8n1{-2T>xy;Hvq`v!HwkC9BWMmzY;lI=ttSox| zv$~pK^%3ybpJuqw^4Y_QiG=lYZ=yv)4?G^!7&F2;qyJ^K1JN6K!=l(N?XPK3U zlJfHM;^N}&?(Xb_3UYF9D8+H4Wn@$wZ(pdvTt;R}g|79dRDWy_dBvouFu#0s?zTG} z5b|eHirjQmRQEM*U;QN1rWbpA1I+2$68|qr33#^Ezus&HZtt_)A6{ao%5La+q`JG- zVOXWjj31h>;JK|XWyxMSw&rZO^a^9b2f5BBT7zT%9LTvwzkQy3?tQ98VW_h$SM_n~ z8xluGZ_pkgh z_x$kyqmmIbJI*N|N)CasHJ0Qvq7pY={JHO~0QA38?R3?+U0hG@dpr~y`!e2CMn*=T zbz-qKD2pI<7!S{KWq)yq$*A8NAwp8a+b|Mf4$U^~SV{sfE$XLk$gL zWnJ(JIENcVK_I>rUcLvvFV}vR@oOb_C_JA=soNt-viQfaHRD!ta_NR-Gf-)K zr#phoIPHan!vt&_6kxD2nIlp-aev}`bF>_loh;dDW@%7Y1*;WyK6Fc?iG*C)rT}R8 zx^j(-@m<}y8adFWj~6Q(;o2U1YV_5|;(-k z&+DJNd<~V&WGoomj&;)JWP0wczpHpsRLqVW)sQ#z9_N=Ec+4sZ^rTK_dwXUsMmv;k z#)w%R2UmauTp(CXiJ!Ap0ySi#qTJdpxZ3>uS=M*N|Ei2N%b(j(dw3FkjpWka*8J5e z=+<}!{Ukd)oG`&G;Yv&Aw^J`Me`e}#_nrUKwqb7C3 z6v@(M@5SYXF!qcWB+#l^Od>Zq$B62`P!Ek&X__dC8iBo8aigl+-_4Uwv6iSf+m(C5 z+Y)o5s;VBFRgv$X`G7=~SyIMyvd8yVPQTqJSN3G{m*w0N5Jx;0)hVr*3N=sl$C4Ei1};^AaP=T)+K;41I`zGMa9;>?g|+S633j6 z77P=(&>8&largqEkGe3--__MB(ywki{TN>TbL&TEJQ*iS4|e|6TS{C=?$ElQ2ECO_ zqQ}LVsNhh+n^@Nj$c*1VMMA(f*^yeX@t?e$T?r zLBVuIv)tG=oH54oBp8$$mi4`LZ~r0W-rWTaJ)8%&iXEE`wpPxs2uFpDT@`XF{>bXz z!Fmx@Upc1zJ}TF&&W6w9QP*VY*XvF%yub&WrIMYI;m6nP$Z*481+cBUL)2Dtyw3zNpkKq>L(Qo#b}S zsGL&$LpN`&dy)2|38{=(U}5taPE_YS8RK9c4cYj<)S~XbkS=jDDW&K; zU=HscpWQ;8febM*5s~Y~APRC~;w>cdrbmcAk{+?{V%lzc!B?hBi- zQMdNYS8<>{B_5zXkX~&A_g`ylK`{l$)%26vU*XWv)^FatL` z`2A_i_G4C=)}Wn}z%scMcYX#gt^U3z3*?cV%aW%+W8Pjhny7{}@{ALbdoHXQejkgs zP*ojKBcH2LmAXbEMO?p<9C+QMMyNW2+GHzD+mqIfUu76-#+R&RlhSEyIh~(v-H#e0F5jw(?N1f^0dB6Atxd~IEie&Y1TJKl3rE zK+0QQ^wUR49G}iZWIbrE{nG;CkU0Fx z4h~OXjFUHDZ0-c`RZ|hQPSo+|$K;Uka57?IVhRd4@IA)KucEK3yS&Qo+uxw$+BDip z#(iZZs4~3W?Pki?+rsUrKIAV%X=_(yWh*>+JeP)F4>w^92x!5BnK;{eItd3{k$W45 zTdt*Ud>R|gDIO%zTkAqzK&two%@HD?d(f753)64 zW35C8>-(Ni-XxY3NFYm`G6~y_E}Qg0j8;Zp@Po?HIzDGe2ic5*m=M3WSf{s*2u8Y& zT0Om4VaY^=tzn6W$SYBFy`extv7yGzMFUj-Y)AFY^w8{}rez)v!IQ-gO;cvBhtv5V zpHh!)F@@H2k8Lo!VvZAu86Q<7GbgPEu8kJ}6wR-aHb$6s;v5?DJ!?j{xVQgf9cco~ z&w>WGtp$TFULK2mdp2P10u+LilQXk)js_fWVroi5N7vcb78VgvH@62&h0IyLcmTEJ zIjbv_yt{lA6Ax=JGpavtcUNA#o%l@?(iPJFmlwC!yT5oqcAwNOti1Dk0Jo?c`}Xcm z_3N;|g1Ae!1>U*yza>a5hP_3&e);YKAM9YQLyM0gv83Ow7wlfagWsK1>6zU;s+oeA zgD7%@WL#azAj~^|vp7q#Pj6MlZ>3Hl)a`5=O{2TNOY{R-T zJHs4bRaDm%7XY;WW9gMs`9%ls3!4&p;IedicJ>`$T{Vs$v*td5C>aTzF0X49B2TNZxAR9`}CyYMRo0-PJJj8F_>v(NJ zyw{t*!3UIc(;L~wNCkPpM?mz@SiEVPMFVPz_h!SYsKnkqC|E@+xj>*CRzOAQX<(Vf zF`%5({vt&6Hziu#qeGij6qahZvrTxd{*HL$Wk6yV}Mk>3g$>*$`rB?^Vi&hF7 z7nXQJPrknK@`ypxS&DeK9mjM2V*+Kbmd^?gSCgu`gMaG(ykA=RfB& z#Rpi!w6b>ni;U;DD#4t?AKMVv*E>j52#GveCE+ayB;ablh7+|vgv`iC)(@L14I&TD zAwJ|WQd;kt&7D@T460f{ZTVongw3*--7kqxy$d^%&9poYaV?ed#Y=issYiZISlTAD z#{b@PI;a)UlX;x0Rvy7>Xs7fu)XBD1yre(2^vlAs1;@C%2c0eBdV`l1U;M!=U6a@o zt7L@!Dov9QSI+7A*lGhpUE3^gs()>badMNzk+XSd`kgI3OOeH|vgv|?BQ@elX2qPw zoWh!}4_E~~U}qW-$Sw=^{d?2k(km}T(}%ZLK+IGEL|AbZxJ_X}hr;+0N{WgZ5YMW| zG-Bg5Mk_CuvZI+|Yi=sdt4a*vP$nOhiI@(u@On2ad98JXw|Vc3cMDikEE>miV?GSD zJ%hOJQomlCY$b73&XI|Bu^eL@o1_!F%&)yzRhBE?I;Z&Amzvm=!w^dGbZ_>egNvk( zt#MUEeDt!;^BTMQM$-G;20*?RPl3)wXEB*C5Xl)9j~o^*jF6>PwkRlRo4#3R*95|& z8e>Uh=*^81&QbN%kodrm?t~3SrlVY}g5NtXJx-OX22dli@%j7&`jfF&I$MQMdY;jW z0QHnA%{-bYaQ4^I$~@H<=V-!Wts8XmdwT47|NH1*c2yD_r^6gDAUc7{4w{{Be08(2s_eA;~J6qQd>%-CKQ5(~?sH3{s zZkO!Q)t&}TXb^f?^XrOzH#mS;zW(h#r%S-IBue*V-sWaakFLu1W__g~}Y zThk*^Wxv>&Z1Rh2-97Hz&FGyr+1c0MuKMOzvTgDGa)aT=&1C2GU32&!iR8iXo?3zH@woy|6L+N|w`0*U4`SL8YAn(&>oxLVDUF!}W_nJR-np*Edo?pv5g}Ov5Et`}I zM~u^2vvVnPrTOb?<}zy;{>0rG-y|+Ltat`*pWNAh;8T41sGQ3{?YkKSGO-!|$Tla3 zRk>+otfAFQ^dmHMyr(Y3I=Oxp_UTp*IHKnkTmh!zr@Z!7dRsnP+O>mD3gp%n-nW#C z`m}@nAvA{S%a}isc||{vg@nESKf-<{w3Ymm3*V^lfNR+6d=H{2pA{gQ|4@)@VR}bp z&5~bPH#ZU@+X0^XK0}aXgL8Uu)pFeOJhiUtoz8dFt|hAbUzKRn>G`K*+3^y-{d&vH zWMt;&iZ(5l^AI4|a`Uq5BeistpvDVu#G{4CzNCW$Cow0oa|^!o9G1Po5s6A~8|KOReFAcH3uOR5<_X}|D4c@_ht+$-d|-RtM zEW`KIan0(j<%ZQGo2mpD0IUXUX)7BoJ(7ZL*22lLp`0Wk+_VXCjXnYQ$B7%&@-@v( z&8<&#pJC`Q^71ItYW$c`ugX8c;Bq9=UfHjmcH7y&obds1;nUXJ7(NtlIF5M$&pzz9 z;lBkptPDCa6!I7OvL5Jj4L*|42{w8xi_14q^2-hp=9F-P`>t zYO0)+ZT;IPI?iK)U%Pwpme1s$jTVl43=KnFh}``g)19M}z*v(H>4kb!&3xQC43MH+ zT5;OjYAJbpuQVDO5kPLpF3J@ec{Q^$Px6(p~dDlK_UML9J1J1?<|B{kVHt&Ula zlT*-Ti4lufajpD$ZYKe{2O@ryL+d9o3Zf^U!ZPe;kq1vxIl*4%_Z8aM znMI+u!+3CZ868ICB1ReQsrwK1we9mqha(0 zfy3crR4V9a#bu!UX+_&A0z#NyRmgwDcwhN%8Roh3E8L;E@wM2O>gt6WN2>XHNowi^ zp*{X{vTE^HZ=<4;e_k|KYtdpg+LOGYJox=);{8P(W-r&s3w$$?_XS|G*&9oghRqJ> zhA?~XXrD7aDOt~vCN(Uf*V7=WyegAA)GMv{x6P|~D{$}l8vQCM-71gZD}qDMuOQIk zfTlG+w6IPA8Vg>PudK3gHjQ!`53F~eX(+oVnXkhd2OTGtFOzT!1>!UrV_Q+H_^S?} zw$<1bC4?tFSrL9oW}a8M5=}ynXPjHnk2(ckSc*|~XGUuF$bo9aGWA*4Ed(_fO1{E* zmUd%~k*ky@2t*&cy1I&nRzFw!-^ec&EMacLsD4Bt8ilHNr<|7rdFecM(J(XA!U8?X=_?Pt)i)1nl?g-&4>2SIG|MeuWp+u5VuXf&-4Z*rJ=WC<+~iV;zBla z%SmJfueSLdx`k%}dTC^}5=r29^$7RGRRew8v{U}_o1|T5w2WU}xN*l7g^j zxThhs^4g)}|V(LORbS1}9c`@VV7W4!G^}u@W}H1>vs%jEnLjEkYBK z9Vdpf_yjah_6_gv^#CEnv&q|`Apes`&2<2xLs?l_=D9ta9kHiMmdbh_z5S`)q0#2_ zMGmEXC9K(1<~n3^QSl;!-8=o9lPUIAd+?F^2>-&1MK0{I|GQbJ@K@M3HH+hbh6OX1 zHxF+Go>{pAl+sVmoxI*q6q0WuSvc=juxVmhh9+JCHvl#aO$^2R^X`9RSO1_~NG<5R2V za)aWzKol>)?k!Gli7gjVZ1o3J=S3q0g`lXL+O%1`@D1`J!^Cjak#WZ8eAR6193w*- z49@l%XR7=Fgkr_T<+9XjYAg-R^X7(z%}OgO6N#;vj?SUNG(dA+>ujS3QusxXCC+Wa_m;${Y6ho)1G>`w_4RN!U?*0W=R9t9=ukms@XtA+A-8z-@ju}OffuZmj zOrVf?ATEdF#n)4jv6;&bdZm-E8Z@<=n{wR4>%QyZBK24pAPy$zaXZFE=kTza%&ZVL z?Uk#a;K`0}{@Ng5#z-LGA;!2jZkMma67xh{%i7nsUPvLVZdkoP=|qF9x$8)tB)qm* z-Zv&iHd9YmMI}@7*N;6VsJpb*e@G7xArOF(K?R@;d5r2z{D(pcu9aluQL>ioJTJQ- z5ZMKjp%+mfN>~a?gF$TxyX^Rk5J+k`%}71&Q|134RvuI2@}a~jC*WWRJ+xWX!7nrc znMId7tVdI>`%QrbQEHUYuWnuOFsCX(&1!HP;5Puj(@7bq?*C7|GcK8t3@`R;41?sA zKo4^tKcdu7xH;&p3qudJnaUYoqTmRVBHd>4?a7m+l6#bLU_*oQgPG3VZ8tS~7b&;gH2VDi10@9?ejpwI`olP-c-?8f$We+1`EL@d+ zcMZ6mfLGCa>F|ewWtPe`AGs(qOHNFoe%%5cHWap6VxOL?Pj&u}F??#u!y5gnqm`qmec&)d+lXP4LOb4FKJ3mssD{Wp~xGZ-CbD348`afA0JIfSeveT z-@5XzHX=$y*gkh00e2M8N0&?PzYiP%cJgY>50Rruftv-8oP6J$z-RRdFKbOxn3%2u z3nK2|#;9p(cWGNQ70mtc@XWbjgw;}PP1eG`;uoJAgs+8mrf!zQOf*DqX5~*(gsS%t z=*tuBg6cwwP|(YI52YJyqo5Yc17$t6%r3_nIY@Q3if7(u^yL*0KGJp?n79 z(lu2uvaS;r=VkuB1$xdddiU;~-&il_YTbvq?2u0`Zd~ru#pgU zyjs5Ql#=&SU?M5s<(Y}ZK6xxU2}4M2E_hP2M(6!EYzp5wn^q!%w_Hf!rCW8C;4+V= zRiLcPZq=oy{+>yQ+FynvNl=)e@(ZL5hg*%WsC&?mu(3|=hJ~F)rQj^=ZPT&^kB~$I zqqCQlMM=92288;eFpYdkr2RheRn_Qtm5?yt5i+&qbUQ0P=vj91rKY5`&z-`5 zo%yNX=7h;bFdaf&DsV$RnN`_M+}AfE8w^=8<>Xy)<`@3_p=r6S(ygYLDk+>y zXwrY@!_6P;)7~3rrIOc@eP7xhs%e>AV()BbyvEamJCcF*PSZ?5<>`1)F!EVc^6uGF z$B%^z^~n8v`n1C0@e4PtcQ0E-6Z&xzSA+M)$>P5k6inGz&FW}Z@yf8)UP$}cp7ck& zegFLNY!xfTKYG1rXrbI3;pXakevKAzUNbQ>TU%eRuCBhkMwit2|0$JlAwS@$j&wXO zl#Ej0I`BYz*x5RMkhu&3Ej<{jp~nke260g0I=5?3fBU{bF!g>Ci4h%=5Y;bZ7dof= zedM61pZwMXRpEL8ftWPJV%GUa4UPYrSSQFKF#G-Q>I&8UatU@qhBO>}h$+p4;7H8! zs$SmAX6>615Zj0hC1o=*NpRdCBg5nwgCx0U&KJdjVoO9yDJDFO>e;(NJI9wq1&ZNH z2{X&H_LXku#l8e|w2|NcOLpmW^x4=Ll|@Z%{Lz(@Q$FfktM*ZF?N)b*ylB&DUYPT( zOcI+komC&sREL(Am2(GZ1V}|(gb-W*W+Z;<=KgrU6xggF@S)csOU+*&)7fJ`f9^nv zYPyd-`|S*z$?u5SEOmu<6s!HwY}PE-?&4n=(b{Hr3H9K)_8`~v;(zEZJ1l;udR392 zb&O_CW}&pP00XtDoN@4jU!N+ak?I9w+EY_H*YPc1;zJbs)3@i~!Qk1>HiOnpw)s!{ z-UkdcPri6G%b~J$Z~^Xs<*p^elr=xAuBP6kTaxqP%O{GiyMS`I$E0(%b9S(NaBxs9 z5!C*-Z!0S9Z{OA~iHSfh<>4GxXRp8;cAg!ge`h`d|H^z4yZ$@oqjkONKDdn0VQzMi zKr$Ndpqj7VqQ_Xr(bq2I(k+UITl&n;>dPazy0oADTk1nsZ@HYFC9_`VqK@PcV(_~k zn&2#_+G>Y`(I3ixYcI%Hh*4r96zaoHN>r7>%uS-a=x|nmwV!S653}<#gis$uTmOkh zaQw3GIXo<^tjDW`}A837)f|fyYD|mHFwK0A>E%hboo=s(7c~3!a zg?z1gvAT6AuNJ-{D=qU_e0)*AN{@h2kF^UU>&lVzI$cckPTZe#?3ixcoP~Vn+!*1S zinp{e_`ycHiqciQFAhxMBH*p<>R7AUe$yvw2qDrWX8RviP3E>f+&(=H7q>IoM8#{lQm}gkgAmMArFbJycm~<6=2>8vk=yf-L z@elYflDZLE_q}?h+b{L`A-$|#j5O{#1tiL2B_ZC!AqN*Z%?=tl^&#uLi9cieSS3bk;LNsIc^ z;;RiWMLtA{v_91KjGc^L~3J zB@aS!@_D%b&3cBv-({S#!KlTk0Amju*S0EPhsp2KEwXo*gPkugiE;|Wtuc;!Y-h7t zZuVN^SEU&GpkB_O-HvIoML7EOe!vYEr~&cl9?mHr6WE>pl|hEdzj?|J5?Z z*XGy%aHyGI_4oFI<>kv}b^$r}>C>m?h;*si+Y*1DhQWbt->LR$0**fEj-dL`cZ*zDN2`|J$mksECLNEp3Nc`NMmk zcXoCX6B9pwzN=1pn~z;4eeo5${d|Ln_vv#iETC6z!yYie2>8zK_IZuSGBSzF{DC+j z2}#P;(Mop=Uhso|TJNwhF-w_A2nhJj%_Srx_(`SzS#8k_dlwgV=$I2JT|zH~$M4VS z>Ey8_f0kH$JESVpE~#N5rE@UaSUL|Zp3%U*GS8{$8&Hr8`gw>e6 zurDd9JZt;zZ}uG@Jf60Bt>5#5jhnJ;Z6Gmiy9F%t!s{UC_DgA72o*>hppuDDxJgP# zKuwuvNM*fY&9!k34%Bk!ralun#Wz+9qEp}&pfA{|df;hG+xg5dsP+d8P`Ws7CrZ*B zrHPei1m>kpj!qT}P8{VE@r;?>+G#S{=>LO{3e;g;U9pab>#6&EwLfb2keFwkHw6U_ z^CY&k_WoeDeK!&zvvM?Ard_0Ag{f?Z9dMuA{nO+h4*88K2}FJp9m%^K1gLCOV@CX$?p&AG0w<#T!*f!Rbrlr zdB<*CGjSYRnV=f(UhLU$-D?Yfr#q2B`X-C8SL}o8kPzf|#Hn zad`NpV3?v>by0u(mstrOWh{5ae;??L>_C#7{oB7Qr}_p-b^f~IPb)2D0ucN8q<9eJ&ix{wdb2ir$)A#Xan1K_b=ZmV&{^nDQ4qB2) zF#RG;^L!quR{;Uqai-D}HuW8rPM(@ko_-MR!2%jhT@OK@iHb|vC+F9ne|cz(kv>O= zkolh$gT*{fS)XE}O z;*NwR??ypPo_SvV>Lf_N+Dg~h7mgA-#5;6Jy={hVQj?Iwla2)ea*_l zsWvy71-I8AvALEMlcH?Gp2HOb1j4KQQB1AXKWVe1es=01Y-ok_!sa^uSrhw1nYH*a z9cy^x=1JRck-uh1LR|dqH9j>(RP^W{9+i$=T$)>xigZg@&@vCr>h#-CnM?-V`q2f` zRP;d_fU~x^b$s+b8}y!3>6j}9PY9nc_U`@y>Hl26PCK>Bz$szwT6%yC)4cVwSaB2Q zx01h2v;>LL~!lw91betC-kPUWUncC5@$kOvZ@+ObMFCR$?1n`oqrJx1YIJ)F(iQ`N>~K zk`)i)Q$d#h!Af%8EG|=Bt(TC}?xOFf8VJ%gO1-Ei@YKNcG(4*&SbVtFNTqwIgm4~! zJ4Clm(H$yf%%+SpEV0~nvZ4K-@zDy)c+(8Oi_PNV;#+6ow{*Z7Am|wi+X@B0VgD0k zyjM4tjIICXdDWeE$CUl*W@$>p#=&hBcX+rO%jQ>ONvvxMW&v^cg zsRz_oNW(#=DS>C{hW8}Wg>#Qg2f}tRfN~*lhnb|K?!9`^+I`jxE*Mq-u*83wq1p!7 zAKumrFb|or-lC)1SO2dGpWMrdYYqCBfX2fY6CM3PeBVR(@^m*PG4XBtpCE%aL{32= zti$aE9^QDNHsG^An)gPY`@jICaDKFY=_C3#QUFj>&d;B19UbKS4sUV3y`x__@lsP$ zQ~3)h)MoOa+#MVoe0+R1hqFP{QL=l$X@V@7$jsT>IyyK@9b}OAnv~I{dwiU4@Z{j& z$nZJr&Ojg2{f!F%q@5_{?`LPX=YKunPbT0*{pO80bSz!awP)4o$6vVMg_QMS>osaY z>=ub%o&tUo3K6g4-_2jK#jeav!72DaL%~_0K1-o!t=i#@M%@xivo`A zRQYVm%+k`*(a}+R-)-IN>ud7J$FBeed*@RMeTbNEJ!;-ttMGkPVxq@dUlP!Qy_srd zoCp8t2E^Iz7~OGzCjCESz<;+7HDSIWX;fSQ7B_5><98AgEt8XzpYK1$q7eQ2Yypw~ z?LiE{PP02#kD4qs1`ZYQ@$r#jQ3$y`|Er!e>}WF+ljqpjHvn3r%>=^3j4wm_`V{^? z*#L|MAoH4i{P^(#0TA2KQT2axGU7~#o&AsGWX6QvV0s>&lXUOB;LuRXzi``H$oNVS z3%Xx$2yTPy0OI)*AO6qD0!gR}--^w-??C**x^OiE zdO!rWo_=O|Q%@2A$TevZ-7~Q#_U#yEzDhRY?O%)7#3nBezb1I)2;1*x`IG5Kpl;8A z=%rHHO+*Ao^y_1VsN95J%?>vHKe33Nh#m#1TZ(OYF(&g=EUGwAMR=6+iBnN}R%lyUl^)qJWiej;V zjcd|4vfHFgEmz6+u$wLjn*#QAORxr6e&fj>SnEF|RunvSy;X{>oKAM^zbfRo7wnp4 zIk2+uh^^uB2<3%7xgSMn)?H0-UE^{fI~P^e6mENFv#&mDnE!G9a^!(r40$d1x!;MF zSYa)f*?Qgn@W3~NhF)Oh`2DD30f>yHig=H2y7(=VES$AmFI?}rOa6H0?Om?`_`XX! zfkQ67qK4cT>~u7I#wQ~T;FqP`J~;?K8!hAgHfH67wi2H=l4-TC89evS9BOiRH;Uum znYhFz!IuKEYp0^A<0YCM5NzJ_^JJc&OwGc%#41p;>PFumoi_tFBmUgN)>p)@E~JB_ z6me9V+_$#Ku9MzVouiM?K0Hpl-Xocq~^2~3C8#H?)G`A z_~7b?{u+WgLxwQ}?ck;DH{4i8DCoJBH3!QXP%{RB)+6{O!J4$R*OvU2G@az4LpKgf zqvyPA$V;Mt0)7T()Z2WVg|dwX>~+|k)dC*y+zPIM)q*mNrB85k@liuHfIv#_v`WlazR{5dMY z@aWm>n+fF?=)=(Y3879U=Ys_gCj;Rjn}Y;X>gGjv>r3=fMj`^7;q&Gw|2N%Dt@js* z>NtxpC)me)yV*{x{m7lgXkFo9ciWhlJ|TRjahal{gXU;u%5kEy)zMtXP!z3&m{p5C zITssCqxZ2JdVzX`MMhi4q{+YIzq+fI5jmV0L~y+#g9^JkimEcol)|`~K)sL_6h`C?|8k*4tLpmGm40I~h~ z{{lqTqKxdKJhrmBi}Z_KL%Nv^u52%Q;p3S8q65r2@qh5T4luuCKjmh0PSh2x5*R&EyaUKbtZi zz(OB2;ZmA8UflQy8ttcY$u`p9YvL^rtTZuDQ&Z+7O}Uoi}ASD~>k;ln3AFTtvJ{cZ3csU#G5! zdE38sp?>WrNP1MXLYVpVz~OgX{`s4)<8ab5sA+FPzvbmf?drlB{`upZcH%9%tsAlX zkIUlcgwB7~w6(->P@u08SN8=di7Wij^YW{}vf%D6Ep7X1+0sS<+3w7`=eb2vq>PIj z<#8cdZtk?!x~fALq6q#G)tdGA-ZE(UtG^(RFVO+WV0bb}#vrM|+@onn9=))j^xol& z6nDsDqmf*ydqI}wMPn^rpG>Bxc?i^wv_9DOwL6&o$7Ghgf@ zvJo>~!yBU1wwd&|ayTqL7`fr`;l;zuj+T0UG|0uI*+1#_I^a!mNZ>kTEw%Q{-FAH) zE$V~vXEV53xRya59radnm+{zl zw?9|A+kg2Z-!-V#Jt@p2HWD0m{&nYc+_{3UO$z%N1XTiP*Xf0^Bpd9 zNy>(yDpu!*<_`YOtLfZ9+tx;{I`{1AxV;c-sp_Sw!lHOhm*xaY&De(l>IN@k7~yd@KE_wNu6 z6pPJm*e!3_?&7yZ`c9#{>gqVBHcUP4+?ft7Rm&{mF|>`*(fhG-|s&vGfakT z<`TNG24~lG-npZRA2FWu5ycG+Q`qyUhdEesB+bEvtbDoNd(_O^PSj_+Fc9jUNz#Iz zb>J>rx-WQTSSMTGu&UkcTFWW12(O!3KD{$Im-i^hvasH8;$56+@ou2PG^SO{;h>9=y03pLDeE+qH~xD{l}O zdH5jaXVRBrSI0*$PeC&XG!>QSmH7^aIqx`tF|xWginuot`pX{4c(~0w}I#>vnJw2#{dGLvRQ#gG&eyEV#=+aCg@r zAvnPa?(XjH?!kjQgS)&#zI*?=_5S-FMHR!$nIpZsckkYNt=0OyCsA{3Ap8LEBbV6s zVWwAyikXOnIpyY{wxq`nx}@#fGc}Kdngp{rj2>GZRzrsBRD-3~PutVYRIer>32(r9 zO>l{iN&9{VP!|*$uafGtauy7GdV{sh#ZfA zI=ZE>PSRee1H=Hf|rIMChr5=GO`d_zNDg^H3P`?Tx)o}ZV;njQy`u#1Z` zGdP5VnsRdOo3=zmMCgQ^Oq6bE0+dTHzM!nwt6kJ^88^gip0+!w$a+xmt(|IatlSTM zE4baM%}|&1aC$_Zr7+DE*m-5K&5&GFfwt>qiz{NM!Ow0?zXY2%xJGy5Ww}crM;WudAwwbQ-w;F;$h-_q(>nR^d;vS5t8Z@1__u5C{9y!pb#9(Fa2NIY%A3vtZ0 zJH?mL0qr~AV_yB)q&C!{Bv@|V`um*t(BjJZZywYd^${?0LMZHxLEY?a!<>EGN~w-*j{$??*q? zmX_kR7JqqMaY3^QPJXP4_BK;At2{ccPruWFls>M0{PKbEmgvfPt)W4#(PgmPl?>#a zp1*lU^25P~xPELhr%Ao^0D8x>$j^Z@=#|3j;!r?EWZ6@b45OadXhe9TWb&JsYVJez5jW@+IT(Rx2zS6UYmO=a`=pBFod<^t1x)a>L zFM#)-zwi-xDS=D5UG*Iqc&pe32_%c1-D5P%w=s;eR%6Jx4F~${L|(L%*#+nGe6A@Z z4X<9mns*euyu6MI^cQV~@9!g9>E`i!_q`5c&b7v8{L=4u2W@Bl0s^QGS|*DV#9KL6 zbD)k;`uWDY#$p108_$hU7w!I)!=OYL9#Rh^-rvig`3)uQoPUJ_VYKgGk?(@L43z-@@DJ~) zCN{%m!~}?Y9XRz%{wE%JRo8gfu0ySLmu$ZVTMKj1i@DxQ0Yb4!sf6fk8;h zQN$gvAn$6opcz>2t+*+0<*lnl9mQcE7M2Ak<&RJ_dtKig4n{tUa8wB2b4$A-u9uD* zvsGUMn8}M+H6w)V*wwqDJHC_|w{OQft4~c`QcJ?+o<#wx;FNU}4DQY$8si@- z-oN11d2zoO@9^f~&+hl2q0QBVKQZ@Oh+syJL+{7S(Bllf<}=$FODqLVCxH?)2>0LX zajY`}Su2SuJ-zZF;ICZ%>B&;Vqv}zZj;_11cKpW=uY(7JQNpG}t6&-|M|*s@`9ReB z5+}X(|8%4~sa%L!@^y+U^IM6@xETJRVgh}H-IH$KRzU$q#@05!A%mZd3JSIqos3`d zyT0-foBZuxC)OJQuSJJ+FD1s$J72@5IQ+cBHs>s>$};3Uj?j z2n&kTWA?Uk0n_a`cRdFoz**)fG3f*`-VBj~KDTb_-oIwZiR)7|hn6wH1d#V9icV6% zM%mfgDRlO|E)pRvP_Xe`Ux!_Uhpqi{tt!xvQS*h*2SJG?A&lTHaoc(X`DAoe;GYfY z4!`bpPfOTu8iM)~?(ein3kY_m(&Y1mFy6N5y@40{qbmkndu-Ae>-KT}_wO-dHlKHI zQNI@#(~HOf?itkfwfrq=4**Q)4J9x#Gjn^mbqEzb)1QfaR2`WS)OG)&U8Jm5t3saB zA^JA)tilOJKC;4Y7aU6FXoc#a!OHRGMLA8vpjw*3k6^H6AHjH<9-^G3V>uHIJyjA~ z(2}^Bt$|KNAUWw^ES29+bDSNvpoV5V4WuQkFIr7{r4R}C%am$#d7Wpor1!=rL`6-) zl|1WH07+*!^cV>PU0qVpP^!Sn^t6MHtCbbB#$rLV_8j(`AZ6!?(cg9*6Aoz&$LN7P zpMun0#`;g?>i7p^J}o|w;B7<`MblB?(nPByiT=xHBVf2H9_LzhVisYIeK5{K-!1D~ zy$5e=$W$#~VHHXJy$dlE4X*&F`n6L#D8HEASQbyV7QGhm3$pf7_}d-EGW|Wg{<${M-(X&{IY}KW|=h^8GYc(`9Y;JC@uC7i=N%76K<0Qln zRo2!nncYuLPVVgJKt=S`Wbk@V7kDf=j2YR@Q>8t4e@&kEiH8MD7=Z@@IqQnQ`007% z&VXY7(#Aylaz;KIhVv(ZT}Qq;hBIr7h+EfD`6_HPH4l5H>MKy&dC(W}ALnb8yU`Mw zO%8fr{9VU-;>iPExE3p0z3pGs``|omk}&Ix26KBkvIi#(NzMQbX}izTjdxC!K~H4_ zK;B!Bk>Z6F3w7fyiBgBI?o!2>av|lgE{BWyt*7M@lkQpA=jLE~4Dj&|Ni`g zIJrU_GcY&ja=OtkV+u&Oq`4tASbdi6o3bTiGE07D z3oT@s^2c&SbJC6EUZR>qC+@(iNN$};&m#TW09x64MNT*v4&=Sx>Zx@{*MV@au|A(`9svP@>sa$xG7? zv-8LP-p`}RsJpXne_<+L;e`*U+vP!&rd+gg;ohC33{3I}IS3UbRoj=vK6nqWiL=C} z(ykA)1M<#51tA8(!WrC>?AXKB!4fBKMpoofZ}t>8&`wmbfIwt9O2j-O*Ol_s2zEYs3wumW7Snj^4$M{P&~D{`2mHo$$F#jb+h)<)HLzy2=Wlz zDT7=C!YGqhZNUrCM9#BRlXsc91=Q^P8Z7t=U^cDW9feRRTP&2#R_FtGalb>1r!|2k zfFK3(e2pYT3*b6k9pG*(^lFSuoIUQB;ohoxG5QLv7X<%}Y~k-%<;%JrT(!nw)Yep1 zri|)OnV46gQNo%X4Hg4|c55kT!r2$!AdaWJM-WhtC*0~@KZe(C|0&)9-zuc5g3(M0 zcGB~?`%wdZ-QlJeyQyDO|0>{O4HYquClP7bLP^fP_XX>mp&!?uoqvKD5EE@OiMhGC zF&n-R1}b9b%uH-XURW5KhQ`A2v30p>(X^?Bg#}C-+rw@FpNEZOjhp&?Pm`)dsY)y^ zw&aa=Cq3DqH0~benx6k0&4;l(ES7QN>4&f;>*3FdEjj~|rLU!!*uXUwBNok^#+K`) z!vU%5RQI(qr^9fm|2%Hze+G+HgwA9p59?4e zzkh{dOPKctSbyLCclh>im+O~eEaSNHkNfpIdQtQE{;wzgcj)#X4)O2TKgxVZYTjl3 zuWrzFB#Eo0rUn>B07Rvv1gH$y{XgAcI05)*tvi^VogL9vcOpw1$P(-x9rf^3{e9MS zv0x6}4nHKd7643{pT9d0LkASrmX?;JrKNLrwE%xkPY+CguFcxn@?1PTlg4cInqlnE zD``?c;&f&p^tN2&Bn}sg)HgGuQwIOj9#uoV_J@P9^y}7~v!xILm(#3I@7wo8|N3be zyL&#{jUWF0{=UAQA$Y973e^2%O{B=?Z)2Pzhgxh0goTC8%*_1yg`ckoh(Lr-hyJ}> z%GNbce0@FF|6E0sH1fa9)RVa~Ky{|o{ib5vxT?0+$-jD!RY36Y-fGXsv%YXkhriVrxE{{|LkXKFfbjV*l9e?LYI~|Ag-UV|%85S)0w2 z_&leV4c`K=nWLj4xp+|b+Qh_!MoODL3t&q(SJ#$@ON}DSe_F$s&v?HyAwkW`%F4px zFosU$=-LkuT{B_BFEak;2(~Ur=D4c5I_=NT)Ikj%C4d#RORY>zJA(ez+`{)nu;P(G zqcGCZb*lgCO_zHhLTgQ-7gtwSW@e4ntFX#{XJQOj_xSK}SD*vT znO_zt6@uD^hC)O$i`A?50J$ANzN<^(IcfsJevNxR_v^BHmz4pa?*L4q2CJ18V9fs8 ztopqWpa_K@DvAN`+g?^(olRYknJJt*`HDBavhwWqVjmdM|Iy&DU%v+88jy~W5fuh< z^xxoS=EFaI3pD{i^XSt54JOi!x;Tqq|2D+Ghu{CKg#OoX`VZ55w|mGAXC!us`^tM9 z^rK(M_H}AOSX-gttv+}qkxgxqhYxnRPdhCmn;ce$xKa;y{4}Bcs8NsyA zy2V_%7laZgT^Kf1@$|&NaTKmW8a3wEokv$5Mx;iCbZ66Ao#l%rE_q8}E^A;{P%a>? zkJ}ZD=rKFcCbtw_MyRL30FhbUVdUusLbE41fl0CW?P=;@OTIEbly!O}5K!%loP~tg zq?b0u^35WC&|-Z$+v2rIv${z@RvSOzZBco)Rb~tkiM0!UCBFpB=7!eV`7qT z!tLAsBRH7gehA1-9336Wt-yGG(o{wzTx_D>S1b(MtdM`3nDD#&lrDeOghzfB;#%KX z659-MD;4Xzj8Vg6yjQj{w8l4YKAsg0-w#_ZZ$tN2KV67JH;B;(usFOpKX39l0<^;x78azv6tLKDySEX^O9@j` zn@r+>1yI$*p<1tz0m8Lqtg?^rCsY0CQeQqdUgKYdl0g-ZlyWd2=7-69@S#k!0&z=; z`A4eK<=CHIiU^>#aPeiFbUsy?kzd`0azxXOEu%wm=tQ#LRsD8Z!R$86A5_f7@(R&$ z^eyAgkyLD#8)j7kxaTSbXERDhpGfJS-h<#he*JvSO$-8QuRu<@LB?p7E*EwtD<3~O z`FTNit==A9sS0zH5ZevMcopw1p!?uPoc;2K2kA|wRt|o-6p;%45#Q&}M_abeqR}mo zUtf9`ar^yL24&L}l-SP?MdFrO4WUXGD^}jZP34}NH&YK;XIb}kfdx}i6YPJPaL09s z>%rCrf{bB9-FQg!{--dPaP_702O+t@nX0}znn|N(g1$tSZ-}=eD7XbruAi6PuV68o zypx{FEL#SW26Dc{g2#-m`A5f&p7O63B%5`%qaF~i#=<)97GOXrkn7W4DY*lgQ&I*u zLq?YiJtuAu2!6{00~s{`OZcQ)1*9{uNTF6q2?9|MtUE%C_aR+2TWcRiFW<1+A+G#- zam$)J@N}!OP?iwGI=8)44=Xd`JZ3ifZZ*emKqv~%7sLY6K7+q)v z(pVl%d_>+AYw~Ma3H}$SXbn+TUrm!_?_4Gr6m*f%A%!6u7h*~qO&4YgtZc7dh)Lfh zSVFhdD@-mXf|=-f>F5~hH_t`~8oo1hCgYNN_~Wf!=AK5eW<~EWPEFOJKJ;X16@vst zKV^UK2*)G18VvnF73Xs45s-Gks=H(K=S?M)Rb5_C3xqXxa)Fy>Oe69BIRL6 zYZzhD<63}S^3%yE92F$K)fDl{O`)$vj0(j|QyCfXF1Z>iy-)VK)~_I(+I0tB|=L1EQ~VU0Ha$Kcjwyt7PF+!7aEx}E!QqJo4kURwK!~8SgTfR4$)~EJA}c>Jt0B?Jdvx8-olkreQU5VJMwxiYrC@Tp z*WjH+za$!o5{&od&PV}HZUTzdt?< zOnuoJy@)>;AI0~vSV!9Y38XSl%_2Cd&9XC?7 zH+`rg5hlsNWNuUj10r04x4g}1eJW@gTlQ>_xBocVO3718?Rj^F(3)H~RbtsHFRy9$ zs~sg-pB7`XN0ZT{X~Mm@u>N8qeZ|t^wpsYw#r#V2VQ$Q!;@u`|@u3lxt53f^|4`iL zINK*H3s;awA!qAPj)h*`J_Vn60&1Ngy4LH%34g~2|DM~{)Wan1WH6_qO!6j&5`Di4 z8oz2Y6*{)(tp<-~)RRl^iEwT8F&#GBAAA@17RcWzqRl-7NWLuqjKXyJ{Gp+t#ib=+ zw%3%EO_R?Tb)qwO%+2XWcCS_Ya56G%l#Li+NR$Gm0&+M-hCQE(!>ny8NUUx<2nvSP zK{pd%$nwzt(VjB(5UWN~iA?nZPOpKl|qmccwIPuhz$DI;f6h9sJOMG~)p zhShr?)xGiWT(^B~#`M;~0hsIB0nLw^})#H3(!ZFybuUBOeyH6uIz}h&5UYI)4L=b1xVYO@-+ss~*^!5S4`4f<1432R4>NhC%9(gpQ2k6a_L_fV z0bqhyr@3qML>%Gc8$Y~C>V^ebU)ZG0lB_7t6o5hAF;P*|X@5R))^nae?CzPPtGh@- zYBDOhzIdz@Y1DJ8$`nezwE=<&G+5C9xE2thBVSK`?IE)TB)q4Dul!IFk6|% zSUhRLCH2=h5%b1#>^cZ+L37DlSJs7&t-;bU=)@(;wIhEbxH9JF{hePoml^ zf(mnEfhEWuMFo0$lBt+Ff*AS@HbS!c&jv>@Jjm{-DVv!Xj6i%R@)HU_XLDl-ExI%S zD-uVd`4Pp%^gm8sZ&dvN4oRj$3q%q@+wK}pJs5cDP|r@Xr2G0XaKO}BBVkVUG?YY^X?Gy>;>DlF1Agv=5=K$2)K6gV3xmk~(YOA)h5m6jkTRp7TQm z*5E(!U%iAtZ1*A`VG8RSo9o@02u8nyK;I98>V3Xh77f2i@S{;>c8biTn6%4*CVd+> z)u6ZuIzf3NqxLZxF0Z*v;x(9##Iuvavx(eqWKHH3MK{Wp^oBSq(l0t=tlOs}1bLUBTvV-gpup(j%&BdT4F z+Ykqb2jfvgubvKa!VKL*t^b>q5}<3Rk2AgeubBy8y@`Sn3@lmqXG>+0xu<7lYKn@? zrzA_cotwBRd6{>Hwhfe0DU_DjtX8fPbDI&$PXN&G zR>N(9)av-R<>u(72EUg>zc0Cih0D9CZE)& z@Wclnf_#j_RtIDHEjqgQD|_f=B&BwU-YD5m5+zM;scXa+0*@4r)^e&Pknonqhmf87 z1aY57Kbo6U$PoG#f>p|Rrg;&aoHg!6ZinzqH^vq&cD-{9!cJ+8Bz`wV&elZ#-Mt-EwWjy0>bvVETq%Awvz+eM#>TmKp=$Y8|Lp9|HsNe}HC0tkAlC{| zZ+>y}8ngW>C@9$4+A9AIV{53WToBCLYP~HKsEP97$XQ~VSrO&^-&M%2TE}^2ts~`T zFS(TlwRi|!WSH~*Re9e7Swrh@PydsPtm@6qrN_2;cGl(fjw3G*kNhj$g2z?X#C(h29BD%mOc2<(At>-#(twr72=Vh6N++NE!j5t10BBI?s7Yjp! zJj_gcwzgCKOYsom=nCOBj~+*E(wTEQrmk9{>>`vh%=)Vf}R7C z|8J&63fcCC|49W_>{=hC)xI?R5+REO)!FTa^(oOSF5L4zBWoi#GLn%)RCQ4!8>#z< z=PfQ+z3a;-05(q}OR=n4}4*cP|G1^|c>%n5n*>Ck+rhIJ4UqGFChp8x8 z%{!N&kxioOOS%(ABBg{MJU9PXLZH3d^!wcjcR>&?)%$_)RBJ2G7q6#MYaokQ&O|FS zuYoM@_)dEBpQ^D1YyD(u)&kq@(eJ%kiu!FmzFwN(!&NKQ+nYj?@82!C^6KrRuic|P ztuqDAzEq;pPhe7f9sX=8tB!?xtGhGshKt=5A-5`qihP?beB}k@&gToNmYZ*$`+^-l zexdm=nfCS5%eH&go%NSgHx7Nl%ZgQQKVGIQW}Ln(cibpV>n6B7`fS@cxL5+2^i;2E zYH)m~hluQiyQJUwb*ppHqq8(dvh(t>{`8Uu3x7w$lk%goJ#RR48abV6&Nu8%GIM-u zB-zZ!NGvi-^#cPveRH{~-Pv5F5ehskck=SgjIz9Z#{PGEof^xCqg$!lYo&pUIPIgdLIY^)$w&QLkzPAfC#=L0Ok{0qcg}-h8YO`~W%cZZ zS&7u6%0by$s!B`L*%o$s6L33T_ z4}_Jqa(Q`qeqLQhW>mwFUbU>PrzfYWsVOtFb6}vL)=BDUSEQ~e;ms-RU`iI;^pbqZ zhx-Pl=_?^2J57FrewG?Of(EuF`pwXr#FD*l91oS-ak3MPvu1br98Jk9PazJr7jsdx zUma)8DwR%I%}YvoIzQ$X-pbpmPTA=RpD1iGmZkI&8!7H~t@K|$Ot9OxFV67SGWm7; z9DQHHxAP{bRW+4r2?tw(M1gdzhA<#wk3w7^E?R?m=4SuVlmo$dM~B|_P8V4y^Z zt<%>;1^QFp#MUQ`1RRjJ^^eb?A*T*yM&U@(b`IilGb`k@fTrf)Ty+a5N2emUSbaT}OeZG9sRAc){)%z9U&J7p@PmGTSS{N7;s&YN`m?I=JFEHWFyKoxaqQ0Ri-N z%dC;br~<~Dn=GWSxjfQD?rF%jU?tb#m4oi&EBf3Z7S_V7PIh!V-;OAiyE|?*Ur{X& zCIP!f`*<_X4yVp^un`Q%_>$rYs=}U=uPis`6_S?qXRjlYWJL*DVVm!JG=<*3J538> zq2_hSE-j40CJ3Q_W#nkE35~i%ONLvKiTu9!nB`O{;^elwYW!m*-l5 zJRj(3`naoBi%-*BH7zO?2de3{W8AzeBDUVk@Vey8zWT_NQ&V{~Q9!ccEEGKv26RBE z_gFtLgvpS^$9K5{X?$nz=eVs|SHMMH)FtCb764jarqaD&o*m)H!9%zz|n}UBRwAWyg zCN!huozZ$qLklk1Bpm}g#bP3SaotWlzd0W3GnRoEE0`9Kik@>G5(o1y*d_^`w5Jk>VvCI)-`L$k2{w%G zSOmlC%3d`cF5b0D*lV{LiffGK-4=BAq%J)SCxl9hxNQ18-SJv_4LCivomEq8z0%kR zmln<4Tp0Wr4`7HrJk6IQH8g4|TDq58-xMs_56#tp_c$W%njpTd+G2zT%Ir~!X7j|? zWX!8qddhV}TE+>mPltnPXBZ3Ka@@h<#he6uTDiOrk!GfQ`t{T6r-2pwb!VUFxa1jI zK$M=}Yr5LQA`>J~T)cq(r%-{IY6FKMQC-h%Lfu6k29KK%$v`IqOAVs4+^!*0SK}n6 z@9-d5B5C9YCbqp^Q;AB(lg_a*bYbDU3Pz^fTtg9;s%T`DCldo(&*}$By!^?4yYDkE zO-~iT;5kN*{)?TRY|OtaxMz;!k+WcrJ+*OJWjCxe$B`40l*J@+)sm60vfU)~C#&DyFY zwHMQQLcJ>k2JMBYF{k^P^=-M`OVeMfw50#g)4$H+-Ad0hA4}8BQj6X4%ml?u~rh&y0iUy5D|PL%eb;Zb7c2^T)@> zzoo0A3#hpO^c63!d;9^@xrOg~>GetJ*J^C72?1@+zw#gDEb+j$E zS+YjV!>$=LxOR9Sc4C#a8VlGp^QVI@wb?xit`zgTqeEqoUxB>KE>AMqakO@y+MtI8 zrX?6xpmVl|i5#+orWToqKq1nqp5n+zz1fn22BpnC51#Kwzl~Qbz4Liy6y=v4lpL#p zs^Nm5`juVMu!X?604~MaQK3Y#u|j2}6;6=}|2#z=WPF@fk4jBlX-lXa1H?q$%{|_X3&+^{1Iaz! zhBL+7!tlW{692{QbUXXagjAJj>Z%|+qgo3dxJuY<)F`j&i)q_k8WWW45-x|6#eBn8 zi55??UMsVnUse1&Kxr`ti(Ws8@Hsc2l^;Ip-K$aD;N85*|9kEmoq*ntGDif0vEBsR#qb!fz0!ic#7ir#$*;Xmr$A{xc##wQ+G2XT z!n%S2s{sgPrtOTGofDInfTK!@SRp@J1sgl^o*oR{Rn@bpw@(H@8u`_xYFfJ~a1MIo z5Fv_^n7&UAv=VAmk>a0N==(R{fYRuP`PLO?Vt04OGW7E;y)gs8X=R4(qWD<#I<^tWG23e@*;>W2qq ziWFvQk{?7CW@$Rc7-+#o?&Gm)Sx2Yab(0GyPaf+?#N5T{P?%{mcvd?F$rq{YueoJr zE<>th;XA*hSWJwx1jsKL43t30Cc1sPD}n~lf8a->&L6Q_MwAfNl;r2EmbgeNc%9^c zbfAB_h@ro3)x`HgO&W0MVB0{-ta=&BVs)Hz;ZQT80uCb>)NzT;y^eGqE-ShhL~O-@ z!?15pg;OVBWJOJrOsrVjifv^qvVw2*PmumB2X4+oPtzBd$QsL;5J#r~ryu-?rd43$W zevWZ9qEH9R*vwHs26ogC^G=3UR)h2te)~C6{3NjDQap@jf4)#9ueqv+o}8v33&?x5 zt8z?SLtSdJL1Tm_G=~oRZu@X<<}yEK*LP&K1PAcMoy>CL`)2)O%NnZVzpd3>cfB25MFa)GzLPR~MfHx9 zhU0hgs9^%J!lo1ml!Ah*DDprtPK%8{VE@pAg21%t>I*L}fA{IjJv z&35V=R(x}bNiFyFT#SW|Et6CFAdoRb)8b`JGS!vD0xW^vw9Cow`@AmWw>t-mJUetd zHlown$#jXoNF;t|a$6;4&BfifLXsQl#TnhD>m~}w*Gv0z)h`f_)vkJ_W?vVz-rnU! z7r5oO5V-uADGkdHuOEY|tWDQl*nZL2vqP1bGsBuYjVEV^|B^*nc{(qo4fS{Y z)5I}*DUZi?%Q)iA%9}@{C#fqn)+L|!+HUNou04BAnQ+~+;rlruj$p{ljZ<*KpjjCU@@ss#ry;b}>!9y)c*bJPYRr}v%PmQOauh398CUj67c z$=GXe&K;);%cuKSMcC1;KrbC^MBR%MQ&VeOy{z4DD~^|F%~y^l}IiBhtVW}$ErP$HmgV6q%IL-Z}UALuWBwc?&-PHM5Jd7C?^ZiXe5x~VAu zP5BO)53rh2+F|H)#Vn73*@{)`dBL ziw(9N80fr0qvtK*M?1e=Ul;(40V=b#t;ksUB|W?g4(LYA$4^>x7u!UU70wNVb@hVd zcS}QP@Zu1GN%qX8UoyL6PF`P|uf=wwLX*t=xzgvFjD<0jIFrp!h2%yOSAIC~ncKOH z=gUDso*W(wNR#OBZa^n`aN6E&`>}H{VP-}8)5;j{h7D9+QF;66Fd(|i$28V$EbWMB zNxlIKmBEQ{L6weMwxCH*l!}Wml1p^Ou9345;PahNtL0Z9fsk=aJXV5pG)fM>o*W$B zF=SIU9N(g84DR9-wEA`>FFT)4bh0<{-_V$BGS?@YMf4WCb&&R+6S(=R%iHM4IEqS$ z{)~lg_tx)Xf5Onaltv;wUQ@_uc6nb7#PRzhyDQQ11+XPcobcx4P2(jFmI07rVM^JceH++h}9WoVf zGSs#;6?a?Ww6Hifr$=2UBz|6BQEt;_2_QA{!V#I86T*d{5kPt@7V*!xa(QwyIU?(nx3hD~LJX76ktswote^8g4b!2Ik z?7y}0V1kg_*Zj)9NqSg_*w9~hQz4*m64rK`#V%bZf76E^sT(>=NMxmYcfNK;`0xdT z5+OV0G`mU_yDtP?KxckBe5_kO-%KD`%N>HOGY9aMNM>VtfrsLLsW?5QjCxqE zay(H)uiCn3kQwkqgbeZ*gG+4C#IM5izkSJ8QPyg5U(tfEzUiP>{Hh#y?-0+!kX91n+y7v1upyhmo*%>#^C@&%S~l&GhO)~U3~D&=hz<;L5~ z?Ui*rJVIUD#gS~$oBU3sLakW&980$OhYtFPw|HcliG8qI!3{09*QAq9tK4vdV8uGN zpkdf#P3_2=rEu`W$`J$(kr#VP%+wEwjA zL{=%9FqPg$a{edw^3`Felc5|ZYKWfU*rdz28OvJz2kz{jL8mO0NDg#NKQ1?jB||Z{ z{3pejj`3Ej4TW9PcICYrIp{EeWR5+M%;84vKjk?3laqDy`;}|6dQ)xPfQQOulvvnPtDFWD20Mu~VcvSA0JSAQ341gE`>QrH&By9|^smSH|IWGqfgS9i1PUEDZ z;SF92{Akc~u5axiXs+TZu<0&HN%4{-a}V5nQX7n3g`aU3e5mpkBBQRspW%kX)XA|y zG44d3g_TFLIkM1VrymLpPmHS3^w=Ab_&Q;PFuFex%%R8^5{iIw7MVBnTWTDc!Klao zp6hFI$@?vtf_9mf$BEv!35S|9F!S*UFOa;RrPgfsx;w0ON&=G9HC|7Ty~pc4A??J_ zo0{fOMVgL-VB-D0{mQY><#+jU1i$S%$TX{|I3Vt0O89RRAnL8s_;`XL?^-alJz)>a zLo&pEdQibP4^JwwaZra|zCOb}QFkP2xwR)Yc=kdHC`0+Z8?DE@_6{SRy<`cPyg`C&DE#5h?R`K!|UX3o)NnG3c<8$$5=XD#;RmfsjL|R;O=_Zy<4hTdN zBK}E8al`ZY%*sNijzih$c#Q7Tro&pVmHvCJ!x+}{Be^*<2@2ZMu{Gou&$S>|EMof& zr2h?CbQKiz4i6vwV`N%AztrdyZn+DH>PcOWS!%6T&|c~VOp@qNLAuWn|K7)oi?rhZ zizG5TGm`>{-27PuHe6uPtUK3Rcq9E$j!rn{3$ zl>O3$)wO@#q3>q55MYjNBd@40yYk9FYk2+i#LlZ?Nw7VaoDYvQRzFz|X|1Dy-Yq4U zanwR%34Q#E2_CAxHnb6Sxdm5!8z;@Gan_S?^e6Vljg7|G-5%Ml5X{Ah+cL1CSNc`+ z<+vkKe*L4SDz}NtH$Q@XDolXNm%xFE5r;*xHEiT7DyNYY6+?%gLo{>ai${k$2Ge$J zCBEf)Co6go-^ts!ICIuOJ`K@DxB5I7*tkxN3>hD23c}8CwXU8vFjd@XJZ`FP<`!u1;pvJzz%6rr907npBecR0e)Dw z26#*He5rbft#j1>6?dqFayc1m<66%M=5rcaySO_M_8FfmQ;BqV2cY@@g%pZ6FGS>g zb0Lk6hY|vyvYHy4;BFan`e}>XUJYi*la&pU5~P7+Yrpnu3x@&Z9pT!x3kAH2aT^|KCzFFD7)2=rdGY_ySvi@?(Z#naSeY7jJg5Q4F-tGCG-P*A9C*F z0`MvnIHD&zJKz$4Tc;$Yo2Qiu43-@DU3ewg|HFxueiesN>g5!!J~?^T_O7q*(k|TV zQ92qj`Yze%m^Zj_kxEkNlG0j3c!to#mV1kbjG!h+s8gM*ZMg$K)x!N=eyjOjnU`JA zleJdttL)v?)zxtVGpnWU#v`(*EV|%Y!yNK%iWg^CM`klrHwm=yxCya1QqfkQB|i7d zUHjjlAG}A-03(wnWSHy9Ys&X%d+7XP`Z5Ngrzz((_+qMQ{!zkEyB-#igzosu@94xv zQvBYDXBsQhBR@4ddU!A{<8#Wxp<3+Pd8n-E`YhJMz79wv$lZl%BAy}J`*>s+;7jVRNMF2(oH^R*yY~mpmECc9k8X!$m zT>oDB=~q1IxbBeN9Kp*^EY<3i^HB;#4iJpK`X_u@EgHJLJ(#hl#_FG6xf>U+f{tp! z2jJ$o5U?Fsvejv5M(88U7axFah?>f*oh(d7!d@n*(+mLRK2$=?)}7BKoM5urj~R+| z`!6f52Cl#90w`Y}$;h-ff#jye>S`+LvSTaMAl! zJyZbbJb4Mc43fE6g;JBKFUx<~f**$MwkPKv@eoiDsZ<$WSf_H0}LbCRv7UPXCW;|^&aMg8BkN5^xQYHzJv*)7iL!>>Xk;&_-P`dwy9t;L4ZJ; zp7+H9w6*rirJU@yh?1PCd(Flr-fd8k-!-g&fPhtN+fKB>V3Pu7#Xjma!!!AbPobyj zth35w64>j|)zvknXTEW9UN>Iw%dfF3>x{xzmBs6)o%nBkpbR=RL1#e*>TvP%!gu(e zFC?PWD0k6LWh*tFcUB22Q_ z53GXEe51sxC2sq-RTV*Nd|U}MCT`eSkUxLITHvEPS0kj{6`m{pOpnU~03w}-r;+ML z%u1MbYHC)?&e{T^R0id zi|!Wr%EHM{>fO8QB0{wouM0Rn`QuFgeqC)|G?_oxgbCzQOb?o2yST|%LnY#kO7Rt)Y)5neBg_z!=0>tH@3`Eb(Ex8j%JQW>xJ_XMqCTPksNSep`Y9B?;a%Ood>y^uDw02?1l7=Q7 z^3iB30s+VIWaNZx2aUh6j7_nd^ONzLibeZ$eo}tr_~Z`QPzh4ZLpgvtN&S+u{Um>! zJP`q3#6r$cnR(d_?s?YU;@z=e1nK-=Jk_z?bMT6LC7=h>(&8B+@nmh~c9Qj`%VKFq zD=DI4dzWb2J7lp=FM*StU(6?f;Cb#ACh(tGv1)y|44b40y4^~&Dhncc@ulsnl}GaD z99TaZ(IgKQao;D#Fs|?o0QAe>5o0XU)(?VaO z+|OAkSlCcU;Uk)g<;u#H$dz?crAO^n&*W7_$<7kYi1vmzgN;A7engfpxRymgaBpRJ z`g}xk!{;8=x9w!N(wbU^Zx#f$pkYd~T+&nObryuNX2jU?i3TV-|NaC8 ziUc4_QcT@F4M5BU{&&}>=fYcCya*Jkni;lKmzUohL;rrM`lY?Lyssa@ULj+ z1)67sME0{T53o@>puKkmT}h3JVXrd=L;(R&K43R>j>N;`)z13*db9xFAV}b*?8ugI zG$1&p1HdkDapM5k1t3=ZNlXkK*a7ZLqt(+xPHw!gv}JF5`)bi{^qJ9dHo~KLKM_q= zyFqT^kCEYNw8qK>2QC;RH?$mAGu6j0&YROR4*a22REA|G-p{Fz`H?6lsZKukm2AKN zw5r0d#Gh)Wwkf)wr{($y)^JB7H1-EkOqFc7h1EZbR@g&&CyveAdO=!+eulEH5g5n_tvpm7)nPEq-cxn!SpTn))+k6gC#t^V&ZrCnqCgEsW74vJxxD zilHW;G|W~%%bYe&r2CWe3sS$hxGCBAgxLR6-I+&2{q}ua`6VT?MG;cbB7`D@Ut=pv zvdb`2S+lQWH!UVR{VGe=vSv?XEHN|4E`-L!$k?-uu^WT&Tz);zIrllw{XF+M_kZ{N z;ScAUYtD6jujTW(zSsNp<`&6J!;$iI?-;NmaA$9bN-8#*z063ad6i1a8c7HqL%(mI zEr=FEL5;^Jj4Sy%v*cYYO6zbx6SbR4UQzDqMp(annbKa%3JyH|cd&1y@jHEPRr`=a z2&;&QNQqeyasJXKrd)7+>P6u>mLkGEm`$I#AWEl%8xk?}tVB^W+=<;DUGVv0RgUI+ zcH^U>8jgClPs*>JgS*QLa@bAJkb276ojqONnBQs1JBV#?k)K&bM@bHCpDmTx>#$9H z6%(T_p8DmX%vC2Kz>V?E_8mh55!v3HIo=XH;^5%A)Kn<2-T|`nDO?L}{v+F%#}5kP zq2G#m5PEvtJ$ep$cFpA<5Y9mumNMHpdBh% zmU@zi1Su2A6OfBOcRZE0w!{c~=1#{VbmG`eB?xTX<7e|S;149)r7KZld16{DMG12c ztZf(Q?BxyQVk4f~OBWn;vk+}&r(Xy>ze2;YqBxE0zR%r0fdVYKi9uEkBa9_wZf%A(2|w_$TY?;@9DC-zOK+BPCfv#@-90$0-0FXAJyReSQ7B zRr7oqevv{^p;dhTOiwU}aY3$FReONlpg&I^ZCRonFZ{FICcI0&Q9%wUOW`5wreN{< zFfh|_SR@$0hFhpX#gRS3+-7OXuiS-qU3bUgp(xHCmD-FlJ|?Dq6QF)$!f8If! z>tGp6KC?{h@Ap3F^2ipGRQDM-nI}|VEy2IP@K)ag-(?zB(t0pQ($DF2JjTLI9Z%*y zeOeC;(v#Xw&d%-y6Lt&ITCm9bI$TeV*q8T-h5?#i4sZP*av_1=N)Tn6`e?v;B=VB=UxIe zg*g0eSV?UWf6zqr5LA8%bPdxv5u_OR9XK2g04KL^w|(0nxz)M?!47aZcX4tux(r-$ zr7H(rfL3^-@?L)^%_DHKKp|>4+x+hFHE-Xvo6D`4!o^$=8cQ+EucvVkHWQPwTqSy>6Puf6>yFj-D@>Xwhnb*nig}uT z(7J9aH56-_J9z4TIEx$a1$Nlm6z+Vsm-n5c*kay$ri@QItmuQF!c<#atX0#Ac`^&k z6SZ^M?>6S#oGGHS0S|M%9$WrAMA_5JT(8}PZdrn@y<89p#Jy=MIKPpAU*9&s^w`+g zm}re>6U8y;^G}{Im6$1KOq6j#rupmWBQ}bHy3R^=PrXBw_h){vlg~^+JlQ`0j$Xn! zP+sLD9~tPX^&)a;1tKTlq|w7YOG`5=%=o>?a{W0WCEXh~r7qoH-y#Fme4+W&m6;^s zNRUCm!@()y<2IeBcJ7Au!Bhenb|&eR7hEbvM>jUQZRDj9F3{#tj8ql65T`;hMKSXEFq5RT#GHaIJzXLR<9Vt5fb2wlVI5zNi;memx?gUMPuf+_ z$jdTH>=JfOnXr~Qi)Imlr@cUNZeSD}jYUHwV10I;#s0ZuwI<4LlGR-ye#qJm)GE^r z)47b@%~0Jvu&RN~B!xq*1yrY@>@oM_RW>Z_>~djc`MmXxtVe2e^VxbjJLeY{`5;%| zxM4>ZrO+MY%id3WQ|Qxkb3-JO@-?w-Iz4XNDSc$qQqvb&mW?jL4ga_j=Ac1?l+n{% z34~Y&l0a-w6*1%OshfMBT6>+U(N1O9~p$@-Z>7P;B2qE@-Yzg89y;U7tqMmIm!v5zE_p415lD@saUQC0lf zpJGXh$d5Xg`5UwPF4`qpeyRUMHnrjVBR|I6E2nEt_n*jTdk|hG5GCrumb3IZlzS<- z*mZ96J8N}R>_;QTlc=&W|MQ7jRn~&%u?SHOJe#rNQ$Y%b$k-VR-(Fo^4X+GdGrR+X zjhyHXO_H)Mf7I++Rp25IwXrcaGaE1mo5M`@vb}dFa2mP$@Tv35q$=;O6oO9fO5}wM zz=cpq?FtA`zSJ2Tjb~?P2YfpKS(B2Il20uuEp^*i7@WXbY>Y%}4-W})}?N}ayez;W!J7seN9(ZP~2+O)D&?cGYx4D-*W$juzOz0`sa^78g+wa{F0KPZmk4$a zQr4qvN?0L;s8vr@06ic+mZ78nLCfrQYDgOhkXccdB_~<&k}T+u1j}qr3?GO*wMqmm zMz5ZBqSN;zfO>}v$I=Xj(-szzD=X00cv+{ z5@Q=|FuZ)#F=D!j)wRcW3PVSq9%gAhFtOh}4I~oj;E=Cz_N|Of3#eY)YF(*QqC+?? zGKeAEy1}!a{^{|pDrr`J5x1gJKPfkgBafW#*oa6{hHnHc9GrEXW|!3O3y5yKAS6j$ ziB0p1&pgR9+vRwb%{uw6p^4L9m(TH-JKHsm>eWo4rUohq?Vapz1HVSuE3B>+NVf1`9eRzQohP-oycf6 z54u&+?N-a#Xx)KLdYak}!h(iphXw}~fi(?ykmR|Wj;hz~I^KZGd%)YnYN_zkCuS-x zRXWVkSy?hHBBFY;-yj}I8w-cQRw^sy3y)g8@UANxbQ!@oZ!#Y*2KyzrYZowIQuX0$ zTPqwu9n8(m0pbEwJuzWZMM_700o!)Qpv&U?Jll~Y%PT8|#l>m-L;qmB;mh*Pg=YZ0iIJ8dO=Z($xET_We0L z6lR#ZV%*4*aq~5l7Q;zF2@1E@tx0@EL1i(5+;V>6L#~NKuNqepZxHH5=g@s5NjCeO%F^{%Yx`sCD(#~WKX`K_guBUVfgyCrsXM76ZANpBll(#u94P@<*t zLK$1Xz{ELy!{dQRWkr`gcJvpXmX%R3Ur)Fykorak52jDIAt&g#X^2Gj2_zuFkIl|r z3R_xT1tFvO>&Mg)Y`4W}K0ctwv6oNXV{GD)yX(Y>ntNSTeC^`y7+=LHKQ|fJBdZ$h zv^%P2kMgW#gucm^xo2-mP)Fjf>>@j)EOpl_Df74^!|Qlt1w%*KS>kT&C1JOQ0c~MV z#&keH!m4zvWto{!9T>w|-&wPe4K3&*lpx=SdIB~6phJ*KR#COo6 zZI)3yKbc|_YW?_kHmZPClnf>($7jWMOC2!!r;^}iCdbqUfwW^hZIO?QYmB0jTe=vX zA*>Dj4lFEYl&ONV@NqrJM# zPnL^tIL0rvz2@wARr&&2ZFW&LpC}Tr+J#?RUuWO`qKw#~L|z#939QBdEZ@4qaSUWx z)ba7Yp&>eOg2KFe_a|$)J6R1x-Ro=p2ARqZAWAvMICzpBWI=xxf=nW7baeE^3#~aO zy{rBChkrWdr%2V!gZTOkxO?{B?EEKx`xwNq5rd`)_IbyvpDmOXk4Y!47t@VWxr=mLL%7!7zgfDvqvaxKz}xxQLHB#=`RfYF7n0uTwt z5@h6y3`VF!bab??fk8Z|nnW=wcw-4lwn#=C&^vZcjwX8k{P`u6` z7I>pnSXAWg=jX=}1^SYy#cwBF&Y>Gnr-4^Ze{ZkM55QcVo1IkzBlB1PdJ$g$-(MM_$0`GMg|@caxkiHof~ldQ=XleRzdLzZ2noLT#Ip&t z?_T%&8FTLc>$eBRpMc!k++7fC`O?>5k@IjZ(;iXa5D)|98j$ literal 0 HcmV?d00001 diff --git a/docs/tutorial/body-nested-models.md b/docs/tutorial/body-nested-models.md new file mode 100644 index 000000000..2d57dd78c --- /dev/null +++ b/docs/tutorial/body-nested-models.md @@ -0,0 +1,213 @@ +With **FastAPI**, you can define, validate, document, and use arbitrarily deeply nested models (thanks to Pydantic). + +## List fields + +You can define an attribute to be a subtype. For example, a Python `list`: + +```Python hl_lines="12" +{!./tutorial/src/body-nested-models/tutorial001.py!} +``` + +This will make `tags` be a list of items. Although it doesn't declare the type of each of the items. + +## List fields with subtype + +But Python has a specific way to declare lists with subtypes: + +### Import typing's `List` + +First, import `List` from standard Python's `typing` module: + +```Python hl_lines="1" +{!./tutorial/src/body-nested-models/tutorial002.py!} +``` + +### Declare a `List` with a subtype + +To declare types that have subtypes, like `list`, `dict`, `tuple`: + +* Import them from the `typing` module +* Pass the subtype(s) as "type arguments" using square brackets: `[` and `]` + +```Python +from typing import List + +my_list: List[str] +``` + +That's all standard Python syntax for type declarations. + +Use that same standard syntax for model attributes with subtypes. + +So, in our example, we can make `tags` be specifically a "list of strings": + +```Python hl_lines="14" +{!./tutorial/src/body-nested-models/tutorial002.py!} +``` + +## Set types + +But then we think about it, and realize that tags shouldn't repeat, they would probably be unique strings. + +And Python has a special data type for sets of unique items, the `set`. + +Then we can import `Set` and declare `tags` as a `set` of `str`: + +```Python hl_lines="1 14" +{!./tutorial/src/body-nested-models/tutorial003.py!} +``` + +With this, even if you receive a request with duplicate data, it will be converted to a set of unique items. + +And whenever you output that data, even if the source had duplicates, it will be output as a set of unique items. + +And it will be annotated / documented accordingly too. + +## Nested Models + +Each attribute of a Pydantic model has a type. + +But that type can itself be another Pydantic model. + +So, you can declare deeply nested JSON `object`s with specific attribute names, types and validations. + +All that, arbitrarily nested. + +### Define a submodel + +For example, we can define an `Image` model: + +```Python hl_lines="9 10 11" +{!./tutorial/src/body-nested-models/tutorial004.py!} +``` + +### Use the submodel as a type + +And then we can use it as the type of an attribute: + +```Python hl_lines="20" +{!./tutorial/src/body-nested-models/tutorial004.py!} +``` + +This would mean that **FastAPI** would expect a body similar to: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +Again, doing just that declaration, with **FastAPI** you get: + +* Editor support (completion, etc), even for nested models +* Data conversion +* Data validation +* Automatic documentation + +## Special types and validation + +Apart from normal singular types like `str`, `int`, `float`, etc. You can use more complex singular types that inherit from `str`. + +To see all the options you have, checkout the docs for Pydantic's exotic types. + +For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `UrlStr`: + +```Python hl_lines="5 11" +{!./tutorial/src/body-nested-models/tutorial005.py!} +``` + +The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such. + +## Attributes with lists of submodels + +You can also use Pydantic models as subtypes of `list`, `set`, etc: + +```Python hl_lines="21" +{!./tutorial/src/body-nested-models/tutorial006.py!} +``` + +This will expect (convert, validate, document, etc) a JSON body like: + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +!!! info + Notice how the `images` key now has a list of image objects. + +## Deeply nested models + +You can define arbitrarily deeply nested models: + +```Python hl_lines="10 15 21 24 28" +{!./tutorial/src/body-nested-models/tutorial007.py!} +``` + +!!! info + Notice how `Offer` as a list of `Item`s, which in turn have an optional list of `Image`s + +## Bodies of pure lists + +If the top level value of the JSON body you expect is a JSON `array` (a Python `list`), you can declare the type in the parameter of the function, the same as in Pydantic models: + +```Python +images: List[Image] +``` + +as in: + +```Python hl_lines="16" +{!./tutorial/src/body-nested-models/tutorial008.py!} +``` + +## Editor support everywhere + +And you get editor support everywhere. + +Even for items inside of lists: + + + +You couldn't get this kind of editor support if you where working directly with `dict` instead of Pydantic models. + +But you don't have to worry about them either, incoming dicts are converted automatically and your output is converted automatically to JSON too. + +## Recap + +With **FastAPI** you have the maximum flexibility provided by Pydantic models, while keeping your code simple, short and elegant. + +But with all the benefits: + +* Editor support (completion everywhere!) +* Data conversion (a.k.a. parsing / serialization) +* Data validation +* Schema documentation +* Automatic docs diff --git a/docs/tutorial/src/body-nested-models/tutorial001.py b/docs/tutorial/src/body-nested-models/tutorial001.py new file mode 100644 index 000000000..9e0fa4494 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial001.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: list = [] + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial002.py b/docs/tutorial/src/body-nested-models/tutorial002.py new file mode 100644 index 000000000..8f769279b --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial002.py @@ -0,0 +1,20 @@ +from typing import List + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: List[str] = [] + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial003.py b/docs/tutorial/src/body-nested-models/tutorial003.py new file mode 100644 index 000000000..bb539b127 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial003.py @@ -0,0 +1,20 @@ +from typing import Set + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = set() + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial004.py b/docs/tutorial/src/body-nested-models/tutorial004.py new file mode 100644 index 000000000..257928ef3 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial004.py @@ -0,0 +1,26 @@ +from typing import Set + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Image(BaseModel): + url: str + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: Image = None + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial005.py b/docs/tutorial/src/body-nested-models/tutorial005.py new file mode 100644 index 000000000..f5f19b390 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial005.py @@ -0,0 +1,27 @@ +from typing import Set + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: Image = None + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial006.py b/docs/tutorial/src/body-nested-models/tutorial006.py new file mode 100644 index 000000000..09d8be768 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial006.py @@ -0,0 +1,27 @@ +from typing import List, Set + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: List[Image] = None + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial007.py b/docs/tutorial/src/body-nested-models/tutorial007.py new file mode 100644 index 000000000..cda802d3e --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial007.py @@ -0,0 +1,33 @@ +from typing import List, Set + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: List[Image] = None + + +class Offer(BaseModel): + name: str + description: str = None + price: float + items: List[Item] + + +@app.post("/offers/") +async def create_offer(*, offer: Offer): + return offer diff --git a/docs/tutorial/src/body-nested-models/tutorial008.py b/docs/tutorial/src/body-nested-models/tutorial008.py new file mode 100644 index 000000000..34b868563 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial008.py @@ -0,0 +1,17 @@ +from typing import List + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +@app.post("/images/multiple/") +async def create_multiple_images(*, images: List[Image]): + return images diff --git a/mkdocs.yml b/mkdocs.yml index 30f803ef2..84107b828 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -26,6 +26,7 @@ nav: - Path Parameters - Numeric Validations: 'tutorial/path-params-numeric-validations.md' - Body - Multiple Parameters: 'tutorial/body-multiple-params.md' - Body - Schema: 'tutorial/body-schema.md' + - Body - Nested Models: 'tutorial/body-nested-models.md' - Concurrency and async / await: 'async.md' - Deployment: 'deployment.md'