From bd407cc4ed81b21e4287735b7d31a30a452e3a9d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 30 May 2019 17:40:43 +0400 Subject: [PATCH] :sparkles: Refactor param extraction using Pydantic Field (#278) * :sparkles: Refactor parameter dependency using Pydantic Field * :arrow_up: Upgrade required Pydantic version with latest Shape values * :sparkles: Add tutorials and code for using Enum and Optional * :white_check_mark: Add tests for tutorials with new types and extra cases * :recycle: Format, clean, and add annotations to dependencies.utils * :memo: Update tutorial for query parameters with list defaults * :white_check_mark: Add tests for query param with list default --- docs/img/tutorial/path-params/image03.png | Bin 0 -> 83992 bytes docs/src/path_params/tutorial005.py | 21 ++ docs/src/query_params/tutorial007.py | 11 + .../tutorial012.py | 11 + docs/tutorial/path-params.md | 77 ++++++- docs/tutorial/query-params-str-validations.md | 34 ++- docs/tutorial/query-params.md | 36 +++ fastapi/dependencies/utils.py | 205 +++++++++--------- fastapi/openapi/utils.py | 12 +- pyproject.toml | 2 +- tests/test_invalid_sequence_param.py | 29 +++ .../test_path_params/test_tutorial005.py | 120 ++++++++++ .../test_query_params/test_tutorial007.py | 95 ++++++++ .../test_tutorial012.py | 96 ++++++++ 14 files changed, 623 insertions(+), 126 deletions(-) create mode 100644 docs/img/tutorial/path-params/image03.png create mode 100644 docs/src/path_params/tutorial005.py create mode 100644 docs/src/query_params/tutorial007.py create mode 100644 docs/src/query_params_str_validations/tutorial012.py create mode 100644 tests/test_invalid_sequence_param.py create mode 100644 tests/test_tutorial/test_path_params/test_tutorial005.py create mode 100644 tests/test_tutorial/test_query_params/test_tutorial007.py create mode 100644 tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py diff --git a/docs/img/tutorial/path-params/image03.png b/docs/img/tutorial/path-params/image03.png new file mode 100644 index 0000000000000000000000000000000000000000..d08645d1c8c91da4920d18ca9f190cfe85e8212f GIT binary patch literal 83992 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 z zdedX}HvGNAs$iyk1ur_!FML2BXCV{-3QQxCWsdteztH8%!uhGK(xWAs;Q932*>=}k zv}fL)5UKb(4fK4~$N&Rd>*#2Zb{nCL1HP#IHRhqSqBTui`?-w{A*Hj89pD`kSGs9| zT%j-Dkp4UqvDf%G(3y@P9N;i9WB4Q0@N82@yBuipNrf+Yj4^l2nlrd^eF4zLjwl~#_6^B|Ymp!RP>R)7 z#Y}b=KO1+%?sS7(P>>nII5uIw3kOR!0_yT2iTqqAVC9`MCQ8R+IN1c}ZDC8Cc&bcy z`)Hu#?X5ly25{b#d)0Zq9&qh6WgaZH6y1ad-Jrdud)_3M<8{sKSf8kt*mPS}9vR+{ z%n$4no_$AhL#2UctQ&;Cgkiop8cJ-_4OHQAtxHbN#JS6giOj=B$#`7onSa8b;Zj{# z9(n)~TV-r-E~@%Fv%lwQ`mYv1ffOu{JQOqCD7ZVPm}`^HV2WGo^+rl`xP_Gudhyig zM~b2FH}-Ykk&8DLg6{Wjvqu~(baOdYvj|>bE6#%&I=g-XZgp6RCUR5WXF}^@ zSlv#^_PA;@`(idaHb|B2=?mHw<7txUGw)ZlTGp%|b$AdK>e-kx|A6$waRqtQ`wLqh zEg9h>-L=?+fL%rj0{h=U=j4C#*=P?btlf$kExw(%&d1UDu+*7p+qz56R@iWd{ikY&LxK(hRcm7;yyEjF6T_WmO1HV==_OU;3Qqgh z*=}Yw^UNk!w_zba;~*?}x*&Bz_kKqw`F2ua{~P-mA#)*=IbY$%Pv)y6bD5&<6IaEb zC=Tb4ilhs=DE7X6ckNqowpTf6wKN$FyouiG_PNS1?5N@9iK_PmVqH>)hdj=aai4sy zViUIinWdRC40~n2HhvZS?r04cDzPQWa+*H&2$q2yDL-##IhyTc`a_3tLvA`5&lls+ z;9o?9nhiZ;0i(J6uoydrYDk4&@~TLX^Y(6~@k$1$B39n=qpGf}i1t<>JtM{Xr;HI` z#8;dNeL!J8AekG?r(X%ou8gNeJHgIxNeOtKjUoM7u~9bA9yZ=;~pcY8_ZHk zgXA;;u8fl=LJIe<$2}j_-?A=mmCK=cpE`DL3lMH;?_F9GSXUN?rpxcRNU2)exfc(G zr%T@~AJH7h99|u^s?eQyHUxDYj%a#lO?wMWBYq`=4cJQ>0cogQDN4M=jVbR&m}|QF zmK;{I4}u(j2uNwSezon*>{UzhM3)6Q8Y{LfzQ|;$N)kteE#iFdQji%A^u(@Fx!-#% zNEE~2k!l;1n%VIo8=^+a-0$*=^7rS0Mn|+*HD*0UWtv}~v?uzeZfrLI`D}1!RiD_x zWPj$UMUY5xBqi!La@Ckzyq|N+zA7heb5qYMbJ`o+PIIb*d_|YsA@K4RMc`i(6o{Vc56Us{#mqE zLP}3=_Z>f)j$C2<)6v4fMR(Z&#-l{%F}-TYv-efmN>1D6%GB4=6|w3T;SW=k|MhkNwFTZ7)OeX)a>YbTnEnvw^D~>wM$ZNCxYuwUklf2xOhEf)S@Gf!`uB ziCwKW?h+f26wXXFt6(4J9m}n(0b!SPWh6o;il+mk^8-)R(~Vh+(gN!|t%2;(=4T5( z#}H9b(P4(GmoGhNYpnW^#5vdFGq<|dgIKb*#O7a+nJRZ2AI)Mq1?}a!^SOA;B@sRD z#wUKLbZ+2G@i(38^9bN}GkkIhqam4QB}I%D4H}y1E;3VnbK%ZZ-Kdw3gypIw(Y0Lm-AN?=0KYXMPOA%Qo4<(ZkdVQ% zZHU%yhm)C%@#G;6c!ywnShoF}t&DP|x3Cs`*hJm>)3N)~eAyA!)CFo=1Z1asmI2z+-)MF!gSDn(PSmsa^VL?w1_Fjv2 z?OLGU*=XqKF+J*knxhY>LI0)=#L<+VxAWPH&$Jus%fwzB#@2{|rU;w-P`O38hQjSH zqUu;u6|RZB#MVARA74xbuTo?smg8(`j4_*ynsteZ()cvD48r>kC#G1Sh-%e(!y-tq zg1(w2bPKGEYShuOfGOsVov)@7AiXrQJJk(B(E3Na+}bLcEkh)_8Q-WQ;fz7Jy)Iu{ zhCA6!2qmc6F5MW*cD6s5Gk^4*|7^I~3_X>*86so{?n4svmj?D%d2Qf4X8eFsrsnhV zNPR|j_a|YM?F=0OQF-nXPc1d^{>@FNy~?{=v=}Er0x%qHRB625#Pldv-FIjTs#4+V zbiiA>KHYA8oF!O#bVUFKplK9f-7LAoj4{u9_6oF^c+7c5cpO0qwr*mJyVG|UX9_>l zSZ~HM6JR^;trYQgc=N}OB%o|e)408>=y@4>3RZakOX0m7+DJ9R6Nw9pEXD{s3lyW^ zbTDAI=ko6P-a}9@DZO{kSN2;Hc|iyqO}T;OF7BZdpHmBw#)?kMSk#yiT_f(DH*)U8 zuPid$(~b~H)60kDu{=4ofWW{F2i~d$xyP)HnOb&;1O^S|ePFExC{rTu{}%ZFEdvq! z-!9NiTRAkfZ|YbTh*;TB)cfz%LEAgDk>&Br)!EqM9JGHW;vYsdr3=o6q&XY~T?w)wMLy&nfkOGz0{Hbuhnd=7WK;*!N;JUVnpZgY$c6lx?qN1P%^pV`X zhrnj}$=S|v84Y48QBH5PG4sw`9=83IJH@#p2(H{(WDJJHW@rzz<+kqqgfn$hx7%3O ztOdjPhY+iP`XZSwZhz=PMV&vYMElsKy2@F9BFP1?F&OvfJwZcsdicZ;4n@~GnoM}fn_{@OTpK_d_p5z59&G=mqhhXOavEg=BjD^}Pi=}t#_apvJ-%+dxkTEmw8Ux$TN4Z! zSx97L*zg%^^c~V1?KQ~noeE(KPDQTe(9ugylEv9+>x9qB2dbmTP)wtlyck-k=RWgo z+1Hq1ko!WK!+RxyrVo@xKg%VW6_&$9PZr1XeZE;q%dh(Yr-a|}j9)3e&O^h72KO!; zrOU<+n|||c9#=aKoJ|ZCAorw)sW>EDj=FEVr^*Mjfl=Jp(K_4zuguD|A(@|J>EW2pyN-{+HgB6-B5yXYwt z_#Ld!mNjiJ%q}S$)*rd>>@?*BI{_V;T%z&cF!J4^=E;g69QctJ3N3ZlRLhZK^;9c&}bUM}T8%_Hbuh^me% zuPQ~}*-*hemi;8qNnRl0$yhax-(S@R_W~g>c;Q|oO$%P{yzmLoMvvsv$c23F8?`^|weY=ak?j3|W(@zKb)!3-Z+?GW%jJ!-;!#rjRB~M#~@b zoCG*9GGOhy2Eztvrz6t8R+do}YX+JECwN4=%yHT*_dd2 zOhSI-`PK8rh9z5tOf^71_yf+9#-#$93siT-*o)}%pE(FFzd|+s%O`F#YhDuS_Apnz z!SClx9V77w56~T9u9Uf`T+>K-k&`NTk^*M!@st2J)V zwGv7E5dF&abW^CsKloLAs+0un>qrSFk(13aN9enIg|~$K%eq;b;OrkESh*Sm!8mji8dMe*y@mP^1#eQO-LW*QuUs~O8^Tvu0`}=QZAW(IMv(Y@}zwG*u zmagc;Y?An(5}=HIb#wduK=-On2`dMjBN!A5cDSIm&LhODdwfjjjg2=IZz>0?VAejZ z)kdlqiWyk}86R>ItT6&Vmi7F3~EFxH)&4#Tuyi45jR#m@4HZIY9%EnS&hkei^ zQzdC6AJC?X>^bbjW7W)#Sz@AL*19+dC4IrVVX*6+oQ_q#4SB>mSJ2^@is;ffKH-RUV*V$S-4%-> z)AsD!U zzmO25{18@qP9zAT_sO*7$BTFCF_x21fi)6Wdlar`(_R1v2g3bLFcJQ zOI!7+N8n0>^0%=?KBkZ@&h2j)v_%}~N1vm640{`B_az5NKPZX+Mhh0|#cv4#Xrt)< zHrc4^o`qqA&&6u{x|+k;GykeK1EH*jkj+baVe7sgT8eGy%ncbt4ZDX|Geoi&j38RH>*STgE7skB7aE5W<0=x**>0_lIGBV-3kB3m-bP z@b{;$e}>@i{iPD2r2eC8i4H?u{k^Ta%$A==fE=FIsca}y$Z9v}sQvlTHi$FI*pv&W zA{sbGppDFigZ_7e2>q_WZuzloPQ)rZ5PPIXKCsesqDA{HW3c>y)IS`$rL&kh4yC9t zKf3PQAUsg~=%W07;oy4OT^*nAP`K4aiK9GbYd4Jzh1BjWJYg zzQMDpi!VZ*Ke3&%zl3H0l@@`k9xdp7yw$B_#ha<-8w@}yu*yT0S7)rjp*inNA)In# ze^KFQvE4sv!K`vxhZOvLiN4I85KIR&U1W>`vv4{w$bX*^BmvTjo{x)FIiOshZ%07) zTbxbgiSaYl!$XqR+QO_HV#_MhC1zq%u`vMU66@n#YSbpao&YO7WS;oq4XqGQnLT&B z`j5`OWUGm-?7b5ki=bb5e1Z@%^ki z)oC!G2V*)Goz~LlI(pf)fVznz|SJ@6dT>u-V0@5 zeHLhyNw)PVB7Q#IQI7#f1H{uyYKrYUQCd;E?P>L9H+Des+?`B?m0yvHFr4N!S^ zg7@qBOz}-2B5Ym#-<`rX1@9xg&Vj5ILI9IZhFeaB{xc)5a z2ah&de-2qclf|4jCl6Dqc*OlbsL51Quk9C@KpqYB{@DWLpc#&gUFBW01?Jcb+Ih8( zV^V1k;$rH1T-^1orSf>(rk)WsN0F!K9zCDs)wsiJHJ@)M2g?R=h<9KRK;U zSAAE`uB)8J>XdY>Y3B=#&*f1Ce~t(!{6nuCE+EA*{*AJENS+uKuc>M8MDO`YZ{*xR zLYhMgm^3=SO#I2bm$^DLZZY)3<4Gc=Q2~L2sfMrnKJP-CV9fgT^g=`**b%PL(}~tR zg7iL}NIDvg#D3@4V7{8Lb0g9<)FW}P3!P+m+mUEA-SY>B;PYLdu+Q}FPK_bn;q_wS zDs!y1teZ*|y&sMiPnq`TvJFN7n7huY~#j`Zx? z(8-EK^m-Wb2O-FL+O+Vz2w2@eOj-XCg5Wp0_^?60wEr=0g+^QDI!jUlu)b5C+5fDg z`QET#qC*!knb4sMa%V(6JHl6LH=|ofZg%u z>y1m5K#O^cdcTjQWD|z$5O6_%AlHJ${O^m`vl6x?b=Q<`88#tR;WS^@k+59I_5T?o z;eYqy-23{Nk3Y=Ldh^zqb3qoBG8=kI@{R9=yW+=>XqAxUvY3#NAIQT(wnJ1q!+dhG z*t^2QzCmLBpl)mUfi{I0@KI87mGT0NF3QchLh-ppXs++q!tw`zwUN`!im?&#zm8A; zxX}MA7kAD)+K6;|Df#sQuLfUggq&xW?qvT*CKfG+%U4U;#PoT-K|9<&%p#I{W%Z^2 zI$-9m?lsD_*T-)j6EMx0-n}+XBL0c_oU;9Le=w=0LQcBm>+QTYZMzL6#6HMc&#!8> z(`sC~NDUHx{Zve<-<$tGPu(C7 zoAkj$;5+*X72)?gU;XCV%C#TW(WnLEhQHS-Sj}fk^ zjei)rC{)Qw!$x`q$YC*XTeu`LV$8)&>XBm5Yb3RSxC`h718xY%OWMp8v3+U??;RM~ zl#kX`-N;Z3M-;c~1^M~*u-{n1q7bb7dg{HxbnuQX>UYa8=asBpmx|YpzPP?~<<2|Y zYAedDyta7<5{qgKp4rY27QtI=)zy3W2!Y6~o@Ywd`BNM^UXW(-$*iac#KNJzQq6&4HiwY;kqE!B0p( z9IUJ<%EL_Nz7MiDZvhtVulVN6^8GOSNzqBK6@<*a3k)+3YM>eo*#F=T;=N%upCjpe zr`%0bvN7aXJU%Fu3pz6FvQxpbb8qV(MwV9PD20C-2T=TOLhsS`N}|qBuQY&j^*DgP zCJ{g;0}=8m`7E~)Mp|2nC5DYVG}e)M0vgv23^ijo|MO^_UHUXKw+Fl&Cbv?VR5BUw zM-(#+G?zZnChNLJ5XlF-~)BbRQGa?WM!-jpaz1K&{pIxx^lhTcA$_>tf1Vjl1`h7Wc zs-1fPqH^xRzTP#+4eE}>uf(qOZr;ZA?4gwb@W5FDPE>AH>n#dIAU< z4t1(GVp5-P`eLY*BEK#HT)YFRzq0eud!eH1_4~pPcy8AVO3lxqj|l2F%Rignx;&F- zWa_Ph?W#QZtchA^owsuFM2c#S$>dvap^UqMtkw2ftqAYtf22h&w-MKQAip1*Y|L2c z=c{m=Z2OE)m(cgskL!qcCaZTLM*9d#t%E!km8KQ-2#V)y+HQ6?)n#QNQZA7NDNf`b z(n#=%bG2nAM}Ad#rWV`QLW342h=v2I?fqSgCE9=U+}V7}jo$aMqgKqS* z(?N52MgA)c<+7w6O3gym3XC{$p-%=Sz6%?|D|p(YGZhWz>wH2n){b2?webGI$hknV zb&lLK0VIc&z6d~c+|Hr&rdO`(hb1hZiLXrOQ8yB!s`cqj)85@(bUtnZ!Ka5=L5YsY zR<=#p{0|%c+~b;ks3haMUt=gTz)DS)qYxRUTVYalbW{HZIzjs6FKL{b!d^;FYHXjv z!4PkcY$_@$Ol<7f^mN&qtEk7BwnIlX{@^k;(ESD~VY4B73{(B=3gxRwYU@`swt>Jf zoAryUssCyLoSg@ZYV@ieFVfAD)zlykfek0s1w}d?f)KJP>@BCNHt`>4VBY^TD$IX9 zMw&iw7eha{Y+y%M?*&UJy?vGMz{lg^ zR>Q=>dO-o#?_WhWkI=*A=H}H`EkB71A*wKfMDBqIhmw;+`Kem=-}c>{2}Hdrz3vAv z$H)hWXQsefT}Ou*Vyf5WeGG2>pk;dMY#$r&X6~#4?w_XA-Y|~YB6NBe1pW7vbHEg{ zT&0&~41;t$NFAG;cg8BkLk5icI@rRI2t)W6P~O!Rh(qg`dXlgaeix7Ym1zc|=-7a+?@C z*?yr*NRYRO%|j7h#)!s95=(S&lUZSbms{NAv!26ABDN9U&g^B&n10*5=(7os4a($n zXSnWM);kxwDE2np->Esy9|v$O@r9QJ-H?9smpmHYa*Sefdh=(ZnhS}Yh{wM#o(b^< zC}ojm#nxxP_;ANy8#o=Qu!1*a2@`T&!N$kczTU3?G;jYDCwZm`VcbWU*PW()@Yb^B zPG6C>j8Cb5eThZc`xai>Sv2N{@y4-Ayqf^*>Ftq{Eo`UU;=WqzHAwuOomSyQF{;2J z)pK3z_xjP>5cvktch=6mbd8M8k%VFZG~**ZJF%@`=RETUW(eXYV=O>a##qq8D%!FO zsnS@DsMnd`34@@dM+_oX%Ibik{E}EB7Aq%UH+{i8L=y08kj^K?Q-ZnOo+HgS?I@GY zb=(Xk4_o*C_gXo6G)tBo4?;U0z!R~0k2Q-{0-Lb&=GVY!I`7>l)XLqtO%RJvyv9Qv zsr&C}!XdlRG~f`LsFjB-5<7Cdt5Ae!5eD~OJMzgR(Gs!T z#x5Jb4~fO24nKQxZFbx7MOjF!?CR7|jG&*4_aw3BfplQ4|4d@v_Dfm#o9R(b(Akpb ziumCb#aZo^)y$$iqfib6zjuM-zPkk4J%rHU{w`cP@yHbHZ;fF(zXBoDx*u_5lv=&3 z*`pBDY){<;HDR{gefi~z8WeFT*{F1taPXdPB_z^ru_f>+ncDahA4{t=mRD#t^|s0B zjOdQ%89W=WQa`hz>cu1U3J^`oDV-0OeGO%Qd*Jk<7M{PR{?ZM;pir!p)stbs&a-g3 zg^nnEu0~g7R!n+id!nU+#q`KFOkHSj{_Ap)qY+IFjf{aoRD0b>yo%~CWar-wT?{-a zM8=;7HTdEZh4?;dC$hA1fwdoC@Qbuz0BR$HMw#43BOK3fUS-w4N9}Q<*K5>C^OjyttY> zSVL*{Re72$V692$N3`Uf3-aNc#$cHb&QNZ(9Nyv@A%qWf3>gntvJ(kp-~_RE83GIV zc^n0jJ4WYZ45x44X9!sQ9^QQBuJRDPFbJ!ge3`<*)Tv{gq|v?6LOTziEkTab5X7bu zYG=nZ77fqNw`011yarW=?$F|%%$=cqMsADLo{Sce5Tpp-m(_s$U6hN9 zQUQ-Pn(*1OVH2h}x>2l?>SNrk*toc!?7HAVo8s})2Li>uGQs5@oGRNJqbPn=oED<6 zxE!7YY|-?U%{wy}(73nNg7`Id%a=N1p+!#HU))*bbr=_C?Is@tZ-j;>t__(--_}3P z;U{q`Y_7DJqOFD519m*BANa_x)AB61gqCFApI_%X`M~vRU3R%!PzX_O890Cdr<`@Z zW|!JEfhsqTqv8*i4&2Yp=K^q3MWJ+2Y6o{t``Y?b2&D5$sah|Qt2MJFCxl$!>Ofld zm<@}${r*~wM>;wH97k2lzY1^hMYKO>h<-jjbfAst^!_Lwa!``?$?Hfxm#U0+HeY4{ zJHVOWw=IW+clRr%PX&f?G>v^XM8R4mqVNK-dK|<+JSAnHE#Z6jb4==}Z^h_#;BarA zPbDrQ`mhivG#gUyS#1SsGNhL0bdnk%DSOkPVRV}|?4$%zBTcXR2TDQ?E%;`;dqxlD zQeA!Yn7aEu1gh@(A`v^nf$Znbhk!s9+umP#Ow^ABe1`Hy1{;3SDyF1Pr^vZg)}W;e zK=9!(*7EbM2&ViJKwe`*8HJ0Kj%HVWZqaUseivdF!3xK(RYi>eRUdX-fhGxEq4ID+g?DQAoc zQU0^{#9%wyfwta4K7B+L&Yylfjoyb@g>XF24))Z+9%}q)otaY92&MX z-rNIJbG(Jej%velyc@jQ2x^6G%u<%Nx~f`Bu8jiGZ8B;m>i!t7Z=gBbmzHPNb;2|h zc{=6DCglv&&aXIl1Ag?0qZtZT+aOS$zL>!ri(cZ5e?=W zIa5Y4zLusu(lUA3LvN^@%QSc)f%lB{5zBrepLUw5+B!FE*h?dt@nYJZmdM|k?ozjV z7$cl`H-{=FHVMLtQF;m_{^o07*$ppC<7_pZcn>jc)MLa^DR%t5XA%QblU-J?Zq@}q}H z&fl^W)i;(n(Gtv3-bCkA!?v06+2H<=qxJb*z0}JQbhl*SaK_4bAdXF)!CrLI4LFhC zv`K*T6$m;LwZsW45>BPYT4=Xqs9<_8u{WW!sxOnvx~%P$Qu@LE&T5}>7Echmp1AYp z<_SfTsHBX<0%eLm8eji15w;a5J&*4xRXT zc$yp@7UKJez{wd?eiTAy3%hjl`0+C88AQ1jRK;8eGMSKCh2CCBy217Xx8NRE`X%(9 zA$|1V!%dx@Y*SpG0j<-uP%}=U>8ya@D_V#^db^0$cA`R9H zh>q&6v0iN-$;kJ5n)0noWjA$NuUez^<#K|+j`3!M;PSBK#4!7>(Z7xmgg-$|7RJ|!K>~waf@#=RVJ2duW>9WP^qMtd}$9-mEiS= zU{P?YobUf~kInz3i>4u-VrcTY`gA_0%B@r}N@~iO#Khb`(W#~(Bcl~G^!;?*fG4}@ z;x`!drl>+V)h+yb%Ms<3H15#CLCHX!KVhnPwn3z@`+jqcv3nk${!S2>))$^kU z+CL8xEP3XrZ#0ZJ1`}o)|I|%FA3X*JuLJFw?3=4RGQQ@de=0ZSI{YwU^oT9!^(^hh zpD@bPgRvTvj>o#;mEwX2fk}851v>E_N%(0IwoLc6=HzX^b9oROgwvEVK>s{ZgU72G ztwcwQH_9af(viPzV6cOhibqWh4IO>b_{#bP=B-BKjsX`UUA)GpYpd`R118tyk9V%+ zscjNd&z@7PZS~nhiQ`=cfqtg2lb}Ex5azyH@-)m85cnql8nMY~`G-Jff}a6B?lUo+ z0N?pcOU>%r!YOOY(PIgQ*75Q%8){A74!ObPwPrk83@e5=liJRZZLpJCkZJPhus0P%!E z;+lP=pOzw@Z#?3nsN;52BEMjCVm+VY-vYsI&9%8hY3GR4-&z7*yf{!ioiALVmPjO{ zF)j#l#YNeCIICrU1K%;^EmZYfg3!a~h=f-1{< z)_hkqZ9%NU6?f*g*4#TI#jtDKzmBm_h!KUpt(q#>)-9!0A7!$+fkq&a@6GW^hFNlV z;*iTVN5}g3U^cuxx_z*vW%^mSyos_eqnBYmll9{)*JjhxSs*3;m(wwqMIpZEvKk%3 zOCR4$5T_6N#Z4@{PkK@wJO5+J7w{u1R|j|6Lx%bwIPFcWvUevUs?eb4vfE_Y92#+E zdxoe8@XHH8Ny@R4b@~3N%d6=yJdhkwvz2hugDNSAFQF}oONQgP7c_GY_lz-}D=GZ5T#qjMSpR-~Er`5!nceDt(T9=f*hYB6BrdH4n00;^?u?mS&;x zEjx>0=!_N1?Q&;9qsa~VD$x@ozH27@&6ZXZygk8(>8kIArK(AySu}ng9Hh#K|*kM z3oy95yAwjN;O_1^!CeOl?rux+Jn!zed-l|+uj-tCrtZ1xw(hI@vi@~~zkWyf*HXgLl?`Q_ymmb9RT3_@x?Gw{ps-yDzQ6&0~O4RD@R zFUH;3&cJADvdkDJ7+>+jPf<;2sM%?h(N)dCvOLm!FL<-gaJzwME{13WBkMD}ojrS& zpg<P7Rw6%23a=SjSKP4y>%(%dxv|xpB6J zf4_9DMJL{n6S0Wooo4Yu86~$%#a2rs29aW6Z0vz-mOe84gNwsp4QiHUqfY9iGfa=| zK;?@|d34xBua;-=v0Ya@DLBrV7DmjIeN>G?C97!a`*;v4)d1!hl|T~Z{75G|d%9bX z%wk9dJAD}mII1N;$!hNa$#SJ96bIx9bbc?c2g>Pd*&Lcfz=B`*>0kIdh4(b>;+dT~ zn7CAu=`$Vfs^wbkG_LD-YGSq(3;BeDHoU%V8Jpm>ms(=R;aJ(2lplGG|F>s^%XolR z5YKNAzE#Rt9p5M#>{Yvk=fyaTa>l;5L$+YYH@<_%w09VcQlwcuC0{;iU|&BxGmd9e zqgggxx2H(ErO?~I!w2*aV5lF8XRYfM^5G|pT69y+6sc5VuLJ@<|xkalmDkfI0_Pjt6C#qEws{Cmfnx_ zQS4;z;YsCOs*J7=CAk1G8m+={Dp`zN^=`aCKrshs<}&m*eTjF`>%w_*m!T$FUk2 zahsjHjo8WPem#!fID>2ocAlKh{pU`t?+G<$KXu`0O9O@Hqh=>Y(wx}P21?6XC+w&& z8}j4P@ZbyQ>zLy%k<`zoOcP6bUyXU;`Ws83V1FxhjyZMj^(l+ZAMIY7cRf`v zRl@NaI`Co>Joa-LBxQo*h3+AoDkiFF*N?_GutiVV#5&MhY=}Y-TCuh*2+FgN1+mRG3D2$V?|=wmP$@qLE+-)NZ( zuYE1VG7fk)k#4k=6{>#~oeH#xFw5hqy+q4fSr@QKtc^4f-$gfhyrQ*kR}@%H2ZkpX zURN2r(ug+H7x-!591NiDCc*M8qDy?(QuJzb4htvajj{#eRNp4+EHCR+X_sj-y*z&G z`=1O`bQ0FQdQPUQ*2r7Y$)W)23J4IaXr}03@w-O5Y~F8rslW1SVb&N-G!`JM;Ix!+ zfk*0+O5a9PNzoBVaYNvYzmVfCFLvg{3m|MrQKW4f+PtNZ>q$6$2sxe4x_Wzk)w$u! zM7ZXY5C$w%+9HujiHk{8FdL(^eK1@Fnc;_A$gp^guaNO_hjFWBn=L*sBVQ0Ll+kaj zB3wJ+fAHZ+qQxcM$dqE#eKve|RJsdpELu$_pRwEMToTtZymfqeAZ2TPMAbchLXagu zHMuIu+9=uGVzn5OJqB0D%WHEnw$XH-3}65xg`NPs8#K%|TpFy^GkAIF2W1i8D=%&oGC z7DHS%l1{mt1|!#oB6rue2TJ3CD}VR8;1!6FA#;41 zM+U_Hf*Q6@zU}1-w-KF2tQ4^%QU=lV)hjj2Wp*~!i`u(!BB$7`S8jw$k*79dJkF1_ zau#8$S4UU6Psq$tX`NQ?sJ>RzLj(kWuAYOBP=n3Ri$k~U&1p_Mca>qE-FiY~OBvC} zoH66>jEh?aia1Wbd_S&=zMfW|B79vBVMxBl+U^QzOk8||IQhB~1~_=H=Jwi+B-P^Z z&YEYc(6iH@*o?j&9-YYC?-uWScy43|5SxyQoZ@)SFi@=!HHc`56tp0;c1+$eUii)M zOEd3zP${K##Ase;3qDxU(_fby{!q6*)Xpf={It_3()JL^XJUM^S$sSEm`JNVSX{#7 z?a5LW4-3yQ$}QTIJ9oa$z5>n@mb`bFOCkb3A%geoGlhQZX(nPvP*qBB1+cc7$T9^b;n13hwFld+t9T0G2^g$ud1 z7Khg%M{s>Ej@7CQ4Gzc$pVD?4KF$G`X@rSpuSWljZJmrU_zgyNxqDKQ3JFCDkou&M zDm1^he-Uwq=U1{u{-Nv3nW;eYZ2cD0MXm;`K-I4rn$-MNoX)7AYA+;oZJCL&M$*Re zGm4?Nw$H~~_){C503=_dj1A9Ldtq6e$ld2~96F{Su@tCY5AcMF?vwjfXQPjfIHW?F zq&F8+i#$v_kUXth7yO|u(8cY3zO9VFx-H|7PXvSA@6eLac39`9L z(4poLL6^)p%$eZH26rVCI;L9KYoN7R7`1OOb|%?2B4NS>I|{C#4G-PmMy&?7WfT6^ z(MtERA!g)7hXf9eN@x-R_oD;H6u|kCs;^!q@K&3QJ7|!?o(V9_i|oDA=p=;D&Jk46 zk=Z>@v&~|Z@i#Vi_m!}P67Eu`3yq>AWQ(yiR{lWB|H;00WlSyDXi1l zUHIrDJ=4B+!V+QQ`IN0jW+{R(vFS!FHBsfuJ*CJeIigO|dZ(rm(yn$KX+|$E-M;>1 zl4Gd2ka;ur3nh!`H{Zy9(3imy=^q$SM0`O+J`MIaA_^O$r6o&M;tkjgH2Oh6qrZDO z+<@PD4%_4#S%OKUAHax>&i*9H_qfOWLe@? zuJ2!H#c8qcG;-5t$XNNK)q1GBMno}MR>cF7>l_yALh{%P$!n3uw5K<$t%b9py{BCS zdlPMfjCt-LE{jh+MW)`wu$n1zG= z<9ombnt#W`9bxIH40dfdKhNf=Kk(0w*7P2K={iiysVtoDWj=$FMg5^#W-HInGrrrn z5;!&VA&a?<(SB$c?N)J6T5|1Ej>kRMy7jWcPJhy>WxMqyg>KePU!$Lm#S&#`=G2gN zI)*Iydb@!zq(p%8CxrR3>?@;0A!q2yGxw{BHL>9-nvD<9{@PtkmZ3Uv0J2;3M8&6( zFtGtNYi!q(H%zXW(z3F|tJ`_@HWYVcS3i!(x1iD%e3@1d7~r+ubc3|KwVX+|MCZeL z70xD0pz+OgR;lo>VBh8jHsfCA*ml2{(go4S95pZoh8#Rnn2;_%>0F+`e7Xa!&;f6L zbPuY_Xyz!^oYe2Rd)weuTiRDANnDSWX7%>MWhdlT*-s4Bt0wXAy3GQTJhTcHUN5^U zw5N$`C{!Qt(0{YI0+G^PHb`#25$2?Hq`xea3r)$d9av?1i-tybbfv)5RNSf2mJB(rRh6E-bOj_0B~-6Y z3tJQ{6K}$S7m@x7oa~1!Bu&Fr5nE-*< zqOT9jnfcpxAP0+WE#YLZ4GC=d=Z>Z`Zo38l!W^II%KaG!2M5(Z*Oo)Gu-FEwSBy`A zfl?RA%xdrB4np%@-7y=h$y$2(bRPA8HW7NJx%%I{>&t&DIs4c`qz)5jm12>O`}}m? z@cREzaBz4DD5ZKf<$?4SEJQc!a>SSsxVh6P^HO) z)b&RM^jR>>j?5uzl&{x5f&lmxr;LtuSc@CRg5t^1MrRY-iHV87t>672lM-LeOZfzp zj(G#8^}{~Q_jf+6eh#lBx$g9qmKo{3Axj;vbE8;o&Tv(716Wg#OTU zOiV&N692$V<&hC5k4zN&!V>>W-03+|{25iZ=?2<%517Cl9ClI9ciCLRT1RVpr;+U1 zxB7UFcGmxdrsT1S!}MZL_&3S0_|3srV#|&m$x>wQczhXs-^XM%QK8IibX}2-1enl3 zs7>#H^leP&%jtEoUk7Nr|I1gwI1#bzkM>u?n*Ny;=7j(G4BK8Ponmq?1fEvIi;=~; ztbjhHi^sJB<*?ZRl5bbox+j~xkX{0o!26WKB9$b@MTGw}VjofOY5vt0{kIvLQ+#G_ zN=*w{g6x|t1kIoASGf|#?X0(~AKrkv=Es+rt1>xS-=46irW{v%)Z$Fq?in~!s0Kde zSSu{=jx4zRgc^wbjK^=w=Bj>sq>eehv}1o#V#T*?NEMQ8_g189qfRcTE>Zq$Z)>6T zt<7o@tyFE{&#_LnsRdypRL%w>a`LI(Vo$^dRQ%zZF-CMg6D-QPeAvpDzUOIM;rLMY zXu03qQ8Ol=&u0B|Yq?NlHXGOv^6WHSse+t!PEpIpzKFk>=xC-5P8;T>%r-@G~g}kg=ZLB<%tlLZ=9y@=_hWxcq+uG~;_1G&;@D(U0NxkLb>}i21wJlpb4fU4m zq$`k?UwOvVT&k^mb8{1_NF{&x<+AlJ>*Io544g+Om2L7H^TiES=v%ZYJj0qr{O5&UU(VI*~qArhfFi+jg)73Z_;u!_q}B zcgm`2B-rC0=*zE+GVadhUJH5c5g*GfFE$Bsd}U1Q43pqYt#ky^=iZ!74~|c>0{YSH z#(KZkM$?tN|v^+jtvL&i@dC#!P%%A&h8dm!K;gP*BmS2An(a_8ms!bRY zLqiAU6@)q|crjYu$UmTc|EZ|X&xP8V=PkTeku%UgZ;nwcrPYaGtYJN*Dz2@H5@1>U z(B$I{2egUoE+vjE|*h0N1|u^R4KI9I}1VA zJt7S@n5DKq$Kc^Njt~9V_p=OSt@hcIu;GVa1ANC*#(X<{@)7&prPXTuPSQ>lRhPd9 zgva@(RnQ|OW&9=NWIoZ((3zmWHn$F{ab_C}%@ci$wj`S46#eDGX0Rv!z`VbXHKHyF zQ|b-aNNQR+8sEm;FnitJQCQ16SM4e5ARJ7UwHXPW&7D3~Z^S(8Y%WtKprE2w#W8M5 zbI`FM6TTs~vZ2UX-b9#MR%E~VQ8#M2d%(kes`mK~e;YKplcs!GvMy33%doV%Hntkz zu(hU&Z+29sF1>3mLJ z*$Pj2##LoO{r=L-N=aJGke?#fy2=bef>0%GN&@>piL`dl`qOtupY74*~rV7L+Znkm+ehNUcAxsda`ehSOtH=TkPl zY`{RyMirZ);ZAFJuTYau&367?)4a=G9!bZe4QJym{Xigu3M&n6=JeqSPcNU@&gXsS zPj13n5EwmL@_7BBM?llToN8p?{&6ooRnzC@WqUtR|Iff8dQ)mSG)|Kr6-m^9twRsI6o#|h&@1V9RFOyQlZl2A|dpi{mb#x4dRUPml!EMy(Y z=PKEN@>d5Df<*5CRZflu%m_`S**vGyLOd3@>JkHKrDUp29OWk*zyN&v5@^E+&COt> z^kI6UQE$nME!rAZ?8%>{b^~nO`yvm%6f{$ISzVJ2z6i*xn+D)*f2{8g2Zi=~8rnvN4k-^0f@x{kcN-;c!zxHkFKb9M| z7*B~rdUq>$yVQkYpnf}~Dw*3}KEilx_QOxY{JmdSqY4FW8+~n}g_?I?V5r@kmW~V_ zCliqD_iKvfhAjQ(%9E^_*oVqjBL!NS5?AF9V&K<6Z%{fi`o{BXKnwZY8xw@74UB32 zJ4c8m>j4!de#`>#6*zV@oVLue;3fl3#e~+clpa>y=STHCrBPM+yy@ymsYf(M$yzJ$MA-Cb61A0c zGyB=D_>X^iPPqR^*tgDyJw{&{m4qE(Pnee@c73bljoNr9ooI3mzf044wt2g6$gX=kL20!MuS=Y6!H5ArrBYR815K~$1 zI@viT*)@UUS--bMJ;wrzm1NbAj2SXn_Y?E&Nc(ygcF0i4MEn44bgooThqr7^Y9U{; zbMoVP5~9P)(?uODiF@YTqaORkwov*6;QCRYR2A?3C?R-7o=o578BsO6DZypj;t^mb z?Brs)IrWqGME+30hO0O34-QZ_{ChG#LQBmMgAfy0M9sJt*#0a2{|$RsFJe&OhO~aC z7|#-rnn9Btm>KghUBga0If+{Ec*~hUO5zjAyV=@w5-{}c#-e4R3~cI%`Txkp2!z!cNiuqHt6liJ0&HNr?}*pD`M3`>OW-?=*qbKe-f& zyRkP__I=-g-hRr#(I+h5Ao6Mn)k3=ZCTK^5|Iir!zk$HxMQOgPG|-JftnPhNI15q0 zrzmZ*e^j|fq5&RWFtn{OROA9zTF+h_L*$@3Qil?}(m`?%R(>%|7(I z6fGhmdq>Cau`$>fj_mor(*gcq62l1k5qE{ygCOU{XoDA`%NI#Q z_#7bVD5~Oa8VA~`{TUF)6lDrO0y;Q>b9~&#nqW5)g-M!DvS3s`t z&$1d9rpUDg%S!t0g6Q+7wr*H<+@k%=9_WToqaNmDH-x~m>BQpspNUj_d})x~an<5J zxgCD5k*NU%Q8m}>S~+7kHATz(q5M=(UFhhd+lDNd@MMq+jktLGk|PH?-^)H z6BO~}NCTB}&U~lpFb07{$PLeW3cKL$7K8WcL9gXW-?EPzAskn$;9+;1tD9wyHV?F> z7ih1m0#w!rFKv3UBP!T-19&@*;8wrYQXXKj4~LJg`ulFmwRDud>vVfz789T3ca-e3 zl3>cwj_^shrsJfhkxggob%4300Qfu~76kF+q7pC{fRG7GTIgB={n~@P(VfSvT}nwi zFH=>Cq+P$;9B7RqUDND7!XT8V4r!M*F3N}VKE@_ti`y$`^*G7)vr*3B$1n-(&4i$< zRzQ=O0@g-7{Gf|j)L0J{xutlpnrg@Fei@Aj$A4kU9J$EXD{&Ci5R6*T`)cG8N7fC- z-8iz%+dKT8Eb$MT6!%h;=oGg;mtCpH^{v_MZWCrJC}zX2hI@YY05qKDa?NreQZsfF z>x`!9Xc)@$0zU$~ydeVgba|FurUbKfpIGs$KZN6NX97HCVc4Hrmkz`&^I5n2f@s~g z_NWCR2C<-95X`61A7c<=R#x7PU+-u@9SVjS!FZ-zz~ki}3s}!`i!XIG$Abn%r~C$e z5dAZbdVG|(oL%k)2sRog8(p>|nukZh)STg`t&hJ_>dX+2qTkd!rYRQh!YzCp0K5U1 zF%{08f1UPt^f1MB>~T3({W(e~3VAj%M~OX_>lx_Sgl7#fVqBcmzj&hJDU&#GadM-x zh0$HhF<3~TeEX0zRfw{gih0QwCf_!+IEDO@1&r6)A=zQd=6Kp~^{uI&Enok|>eSUyDrrFVc>znK1f8vJq01=*S|q89&wV-pD|) zkSqrGuc7ptDP!usZOc)pBVo|I##UI!xZRJW_0mr1-dKpw1_j_bvBaE&f0h=w!yI^O zzG!uQcHeGF+L^?!Ug}2cT&Ym4AUj+NS0jV67j6s3USKcPoDX7!8l*`Ui8e{QgKm_@ zlSkgJaH?BBuk?DuF3Ak@vVPSqm-p@@5DWgB^oF5+LqeicY~Aj7rK5?)F$*3mj+vN> z9FoWVX0;U^^R@Pwqk`F&PXtNTMP3;HD5MN{ycdv%rT2>i6WI#z3JB$g`v^ znCu9?m~bqnw%-BLf}5#pD9o0F;zuy6b%)J-*h9d7soKyz@~blvi9S5 z@Pak#-1q%vO8iBFA8d?s;z-BqB?1F{xLbV~>G)Rw?{;rzzNs(rBp2)|W)jr-<#-XQ zy!>1zcC}|B?bR$++7Z34^$y`>qMc84IO?t^T|lWTh?}>=413~@J5_Q5)P;K?xCQg% zKc-dSxsr3fKy8KY7NVnE@ z{+N*iW;&b2MyTQ%cQ^k$1~=Dh0%%`$LZ2!jV94tLZe^SzCvyOlXq@rS6V z^splLaebaPVAyYwcJF(S$(EraAOI@}Ch|Uk#9wSU{XGiQm7NM-LPY!*}bKs4xu z6i@)~!@;%oU#+czM5u4}_VAtO568QAc-k;1&I_A9p!8kP+SLm^J*?#Yk;&FeMbA%b z9G=n6o*v?onee{z8&?Jeg^zb5Q?tdYC+CoL4$*xW=6^We7nDDTFWT3Wb_uswDJ}Yc z-N;9ry8ly&<>k9fb(pxNrEy{bO)fiO_KCuwQ8|r2S#Mi*US2eq02uSNCd{wdb0>P;B)BqO(OtBjC3Ucb2^Y;@E)npB{_2%U1F-sIJb{+pcW`3{e)2KTCE zygt1cS;xt`wL`2to!HTO1iNboNb=XNBY}Vw#@9270zq_8Yucy^k;Eby3gTM(Y^=bH z_9w#Clc|JpH0ST)bI+}h3#NvVvf`WoZXcq67T5fhfG=*hdvhS4uT)x#dRwG8xP&DX zuf_RYbI%`)KQQba^J_BsH!^ge7iJdm|jNzk%9ddzk`X@V7NFBkk zk9{+lSnEtX4N_-AqJudqq@G6qp-*%p>qf(=;Eppgn>*?wD_5`A)xbO5OdqI`djlBp z_K5smU)MY5oq^V+*#Jria4R8H=ZO70W_WZ^=^rT8>nX*}Loj5#MQO4<#Eyqbhm+~V z7!cQ<|MraQ`O;I7G-^B3hfho%$`yt|ovQQtVJb_2UM6TuCd0!aN8@6Z_@H9f^rQ>0T(GC4YVcrx*Z3Z2G*_+Nq zjuGOFd<&#~9M<6k5If++tV1Ee(q9BSzBoCBv3CmF(TxSmnH|)+f}V>DLA5=qmpM%# z#!y6={9dRPz8qMrnmYvsPronEb*}T5_?{qCtDff${9k{Ig|K+J9VdL%xN5~xhHAGM zAA89JN7U{vm_E-5+Lg^^^CHxeojO*;QnApOVE#UcV0=Hh2MVrdam|-5{-`tP+*1)4 z@-Ni8&0$CpcE&7qwPRy})e+n@;K&*>pMZ{gR{q|X5kD}7c>G&Vnc(TfyB*fY@G~2o zg|m$Trbaif8}pt>h`lw7D7oLA=>4?CA+!l1*T!YBQ={aekg8^1BdlnsYft8-G$u*DoqmPyPUG6M@N^W#L0ZB{6QNVob+8n=%Pnz2%!}Kagv;#y0LtfO<4RqhY1Vq;>~85@7iMT zJHy?Wtv)*p3!z7oMXa`Z*5E#pk$&_F&PzGwRqr-t6Zs>yzX5ZJi9P=&g&(#*G^6WR zbJ4z>l$t|BlJPKy4`#Q@-1GikCoHHqKV?e7ZBq)lzI56H*ofx9GkiO6aX3H*IL%69 z2?sz|Q0IH#JI-v%GZwWnJ?uGINOl;-Y(8F>1WKln!g~`2zRr zo1?(}9N1W5E&I~Ti~`wJVz0aUJCtY5wsmG-;19N7LA7UI@$+1V9yg0R!mNQ-*_-!s zR>A!F!8PW;*l1GAK)X+cMF+W<*nfw4W=HI{uf93^@oCk1uN-rlMAj56B9mW*CUEd`1{oMkfMai_x2I z@sO7CSWFcXi(XT)=rj%nA>)3O8yWYx0H^oPAM&?8{{8}>)@`+HycZeq(GUxGIqO?a zlRL(GjA=`WxF#5SY=VF`Sh8rTUK{5f=J^MJ@@jsu^NdY&=}m2}`Z!4eYs7aqX~ZDt zm&K%}gJ}ZO!{Ls7r^SuF$meS=6A$OD@`LtS8gwuIy7f)1yIh{8brsha6{Z9H1wSyslqbp)}0y5mK}#?Y5pBB0e&)NT(QWl4nz5w;T$~jF!K@+pdGfh?Q5UH;jp+y&>p)A~fw}l(&gXzpfwMOD=8IG%$IYx42EUHw z`Q~A6EjZj5(r$iu2i}}NgUy@E{uNC}LD8|-(ifoycL)Am$&e9*!g+dXKk#?X*Hcz_ zf~v~%dF|Kz>6S-8quj5o1sJCDwFLQdbjNOf!9tN;JT0bK&!m#)Z4$@;Pt?-hi97 z5*^%eNo6Dch3}$AhbIune;Si0dX${Imfr5hM)61q7!D$!B3dgsy5E^Q zDhyG$E6g@gy08p%Bm6S?4W6yZF>i0=4gZB^*zeXKvt~V;exwkOCVjgmpQ%0pxDGa^^(Z;HyG$YBLHR zTZmj+2ng`&?Pd>OGOTbNp|ZdU6>_1%cF##q?xT?4gS1zv$YeMxevLlbF4RL;lBeJq zXMgldbeR?n0w0k!TiVT>1dRQ)^wzeB!%*105r>UWSnbl|= z0zsuT_f$MU=t_NhK+rxLROo{Rdqi?pJHsfgz4H~rcbNwG$*^!fSCHn!b(XmnS4bY_ z>gJ3|VOUEAorfMuo{st3^Jwj&tpgZ(fz;cHl+j|1$innQa%Scy4X{u950!ioB-q4? zp(l7(#gVaz@M$ zXo&;Vw!|l`9MNMSKdK~RDX=3p-3eSAi>TT)51B1-o^D#_tWMTD>VFq@@sXBs=g|+U z9^1p(@7=5TR4p*q%Z22iu_P?GRL|e#t=p)RzP^k29f`n$Q+!x;*3$mo7{JT_&|ohD zMLlTxGSukLW8NEd$~`R8E8EUv9iWZv1=5dpLt+IL`E_rOk@~uP)}{>LdKE#$^d=Ao3w_5S#`I48B!K zb?%PId>(5~Ys4g4N8T|g5Pn2(QgNyvwrxZw`i*jpX}$d3Y2{KB8V zhapabPPyB6l@zizZs5xnMB^m^y9y{~dI4T{Z{^;5cf z*d244gqN%m9-z&Y_%lVO`Tg+9U0G8KxQrPwLX+M_k#jL+sN35RcO*u$Xto-GoCl3T z?Hqbssa2bi{}Vshk6QqclL!|K{MuZbYa@d~Vy6UGtzb_#DMk;pV@m*3+r9~@`8m~~ z@IJK=krgqoKsi)J;)^fE@=7cB!rtA5;Ffya?3LK5GrfFj4*Ylv`gA=?A4{hGQGx2A z05+^^N`B9X7kxUR*ad=wy>-^`a)Op7|1G98&qGYFA+L-I^DktK8+31$n+C>R_4N08 z$W+0T$J@B(T1wyq*}}7<4Y}%w@7F?S=@VAAJ_FzP;XiZjApBEsI)Oo?H}HA1MKjBm^|Ii4n>z9P zneQsss|&YO;%cwoMYJ=wuh`;lW6=V^V@FNEP#)mRP7uB9CY>idg}P}I2p$fJMn{gt z^Wclr9{u30-4qc*QlZe+-d3!^1}6Txcrl4=pwVoR@>4eF`K!SJ)vPVQWOs@x-seZ3 z%hD~j90aF|+DV%#DIai=!v)@G z1-!r*;FDw1y~zaPgTCC@hlIRTunb&vOG?I6_})y7SuBp{j1G!3J-bn;MjPuB^c7*f z_Q0z6#lbll;go~;m&itbGr_-%5ms_sL8k&IQah_WBETG zG+i_{wUqo9>QX?D-pA*^QkT0{YgKvwmAbqL;w}Pzo72nl3_@yb0u}w)u)G19mlthV zqp0)sJY}h<7xsrOyE>4WW-U?|K>^U-EtaRqDKak2~AjRbMY~l3BFnbaa@s($W|r2Z5tAV^J#kkDww| zsr{gt9>c2Fpf5D^QMMSlcF=~%yTN*K^p@QS@bx^fyJCuYe)7-{gHqcmmM_s z!E{%jsVd{2ZA&_0wO^aU6x5+TAT%NZUg;LQDQGwmb?eOb3lzZPnh7;ToVoK~=ACnU zdnZ0C%j*ugF?4zH{kzz-G*MmKa-{#1aAZcq8wb4&_`fDFy(3g-QCC4lgeV?z1`!6E z%|}knf~R=ulGb-p$*xnV-db<&);Da`@T=fQ)>{8Ac$TBty-*iAqb#~Q=bM;! zj`7iD=?%!Xbx^tf#*&Y&%+9KT?f@y4YE9ow<|ann_hKXO-X5dHV{ zTMF+wsjbd`PjTBVKB~Cb?251~tDiPlB>r#!+j6xJ9b^$Y#Uu7a{qo)1N@Q~SFE^6L zeto2+QPA$~FM?A+VU?M&8bN*{{Z>#2KNqEH{?vsKpDr|>(eKhekI@C{$&ktNxR~v6 zRql;6v*_sZ#3B@l!R-lsG^Jk}UvfaTkY4L*1AXhgGLvt#eaH-1{nC?r4-2?;hlM%} znLQnv?z4`RA)DHfH`nygJzR^d=7H^z(|_0kr&VvWO$^bn^ochXD(VFXCT-2n`@OrR zhxYaAaaW?YhLX~CG<8ckd(`}aPCC9X3p+)|YDuUH%otD%fk=0voUAhl{%W8VV!-NV zgQU&*ywB-PE?j$v3VSwYDS=GdqZZ4qbv?1ziBC^xR=*?t8PurTfnv(Pfoys@G$|BF zYaDwJ*Mai%z?)ai+=0#SFr_1$-Im?v@X>g&mHx}NaP!THh>;z#0(}PPXd;Y>btw)X zt&rVnksp;tU;}eDZG*M;d+FG(X!isONl6%`0=cvfu0Is{GodqT z%mg)1HE#tMBGt{j`zpZ=<%Ewuap_rxTcJMj&svYj@+6%woeTK3ej93h0H+T}Ps#}; zOD!=gnz{T}4*(-Dvs+`=@yu!=Da2og&4K2!s}TQ5Kj>iRB(pNhRqr{~F2;CcZeRHx zsFbx?=)wW1ySdwRX3_8KTj-=e;kuwHqb_tHTuiy5IJm`;R9F$=@J&;Y`vAj7;vIOa z>w{No{SwbxV7K#O=>8IaK4bR)m(qI-R}lD>RLj?BiA&ebhuumwLbc<-=&}^jb9Z!s ze|hihJxUjsTAa62mU380ou{`KP{rs-Jv*Of}G z8dK$B73yRrt?y!Cuc~CA_|>0K*gXAi8@BpYW1H$YU`UM3}g&!?>zXdnIzjzTYw6psk6;}Ty znf0xVpVGpz>8iPIt8HFF(xR=%dKosc9_3)yeu_EsVuZDiSpqeW33sIciMIE2q2ZTe z!#+Rk;xCsX&PuWn9SLO-55!>DF3S>MybCd`kv>DqKSUX4Y`4D`#C=Dn#vb{gtyW-v z(X3_*N+w!UX-pp~&1gsh^hC8hpcvYxzDbRubJ&qs6{-)yZ)s6!aPNxbKz2AOf!)*X z4%2CHtCxRF6M922WT}Cqaa6`T)9DAxXTJ{R^>7Wp9!8tpNaX!+eI$Exyn+v~|MnjO z(=}WWOySmlxK+a1VXETJ!^g*`550Tne5etXLZTEcavqSAW9J|^M)@HJs2Gl(2_)?a zA%Mo zZM+!Ds_C7J$erzxWHy4kIlX(rX6V}g;xuwG7dC&fp^{Q8D-hfNx<}cKCAiy`j;`VVTJyp~0R?}7<@zbB-?YNRXqF3ib zdUS%02m!0T0UKo);k|xAynVn~D+Q{P|D(sgBym)qfv?rsCKd-P{0#CTAUWM9Ryu0O z-kJo&L+UU4xJuq5sU*Vw&M}l9`!idGdGb5b;TPQ}f9AqGM8!eMr5YIG42>Uh-;kpt zd}ypczb(~73LuImjcTo4c|-A$lWe-wJUs$2+U zHI273MkGeairnPkZJM$nyRE{aIa>4j8CtQ<34B;_fnkJ6{t=c^tteurzR<9EZ2G=` zHgE{l`D2`2->-FUiolr7v2IJH7+QaJN3=qRy>S}QY~v0_lJw?x?x;*SBgNXzo!r%G zXG#}rwQ%$SvDE#5$$W7qGE&`Fa-MVK*-HDNUL-a09p}8F;OfACss6`Kb@8E&U{u2j zf$Cnbd%;O~AIWUuIko4h6K`ccF=QzyLpoZgXHyN$+LWT|GjC;~qin0SEgqHqR*ROW zja@e-cX^giF^-Kztv$?vPwFV+II~4O?s&J!1VC_j;wHCRWS{glmn>SaC&rST7xmH% zM{d1|+ToVxNUnikRTF%;tt3gpXA*#zk4P;rS2*1Qtn!(p>+k37eAz-UB^{&UtfdsP zYL4;OMn2u-JReL!7aGEy9XLgXq?8~rLjg2kmUQnan60XI1cAAqo+ zStdD@NcLldTsU~r`W3S4chi-;IYON1klPlVC;8>OP6?V~+ab)|8_2dR%7fbdY`Lgc z%;{y5&X<1^23OU(Z0ahY?Nr8PF4-8_V2)K4VI<$`u3_?`@)Mvjt&A(JWgYz4D@E_r z$yQirCf=UR1!yLCd5f8dLwE=djNjB;KF9d-k}c{GByNDiBp$dCc4dkvctq5d9NW9L z0SzT)3;Kl;v7A4igrV&k`Kp~@BBY|MHm6{RN7-F4X2g+d1(Z)m8nG#cV;4g4fa7Ol zf8|OOvQdw`URHbx(;GnyoyARxj}PctdLi=I5EHU-XAdAGV986WfB#Dvy8%?;V> zbI8X0H|YFkTFWGJj2aYN<%YQ>ohPopiMx1`o?o|9OH=LP2)ERxjEnVs@4Xhxh1n0g z=H_NA2W4v7dnA0Y_1_sz^FkmEji>Vrul=@`2azU~nAUfZ)wUrIV>D7GZlRxV@Dkhb z*D^pchCFq_z}e`x=<*K!{}=~AXB!$Do?znRWa$Nh-^I`S#?Qz61+GC4qRY1|>3T43 z&{NIKEZHJv^13(I9#H$+lD=T*i>B+_7xx43B-MHwT3J=4L=@$jFf{I`H{WACTK%lX zWU|AgrVw8B&$~f}FtutWPB@IhH~!~Vj;AJ5dk)7owvRvR0Y1aU#pUO3KBUz|O8%>* z1cPDBDpaj(?R$X0XBbSf_h++6EA(JB;2eljQx_}KaTei(^gNaeex#N}ksKN2EgK)$5&u3pRQq}+?yW}gj4Sm@6@LwQ#C zo~ts4&F;%?vD#7Ml6pk+2=p&l%@k7}9QKVVjJa77bQN*m*b)-721ig28yUF~ptrvv zkWf7^!dEStDwA2ZaYJ_(6k9A{Lih+8^PvCB-)TaxoVL@x7p0ZU^Diz;dQ;?mnKi%>T%!8^0u2e`eUs7oZT)1~fX4@4!LC<&s`G#Q^Aa ztYX>Gn;0*=`11}}GEI>@%8X-u>u2`;WEE$JGk985(xE=}VIq=K*fKLF;rJucLxUry z3F(AB6^(GL2ttn<-lOG3bVUcjcIt@cp2=~N6?c8O7{}C(;wkS80e9%9FKvmGxdsQIDD)ZVWRm`#0Vj9o?Un)l;_w zd1Ks}3ho68bV!pvq$I)fpb)Gzd22co81&&=_AnNm{nvuM_!{F5&DWi9iiquR!PSn5 zHCr!^c>MBb?$G9u=n!68Tg^~QX*&kf7vap#r8+qap}Z?WcW9jmupAH&ZU?3Z1quYL z%xj;V&J11?|LRV0%<3St9Hr~V+4$-{NOa0$x>8wA$QfLFMS8%mnb_%4^eD)oN`<38 zW?GDM2xl`YyAElK{O}U<=a#1(x|IG-^)wNfF9Jvyedtk5D*IGbO#PAun^Sn@cr`iH zvynC2T<2&QqauM@zlz|+T#LUwM5{bxm#ZIe|I>GWgWVTP~(YDcu+hdyaA72HTo4*^|)Mxbt&i2SkDfp6hK zxu$*tb2OW&PM5Hqu@|MPyX@{_SI0`%ZS<%>DbXLsL2j%rb*3G27*!`pgNFJ5<95L zSTA~EaOcGtb1E&ul434{{raxazPE3;{8k~(;NoJEuclprP+Neh!jCLoV!9!tu90MJ za1+0yR;+-n)APzuD@0df>HG>)+@+TQ5;J82S0NaR4gSD!5F8hqq^rQszgmEB z|D4uOH`A(mXh=}sno7R|y@5o{<{8KD<~_&t^_-cbmwwk)%zm6aqcY@C31T_YZ|6r>RW2OCHW#E`4Nw~WPb|Aav>AO=|#;GwQO#w zH{3nrHD5(ZmWYvW< zF9Vz}5fK7+dJBwaMojsZd`fWYC2KY|-r4I+F3(J7% znG_lu-?U!CIjS-Hx%N_q0V|#;Kg;vRZyZaj;4gzb(IQ<@=`7h21d^A4k@{U7fL%^b z-V?tHO|gy698$#QkVSZdYL_4kzW5(GuX;2Dg72Vk2FunHAL>W*9X`H&!|+ZQM7`DQ zB0!od(E|eco}9dnM#-$9Jmse*_RGI0vaMd08~d>sQd7R)D$gW~_61O|$De~*Owcxk^hfhRxpP3pg06=%W2~`U2__AoM9)+khM`LW zE;1%_q7 zJMp53>0ND3;#ab7t85tQWtpgcmRG*(#zOS+wFP+mI2@1i)GJ{X8?f%0oFw!@Nmi+# z;6Zb(-LHG-E^_QT21|czY30TM^0XEx*mcNxCY{vJ>WWWtFrM<9l7S!OfP)x6xO|hF zg?}>TzMD{)R_5QUu>Whmd6y?SYTzZSLl{QQ?dr1RL{T`X6BruY-&v*1rS1L(kK4vv z%<=}ctjDAC+ZrjP-z}zdjqqry3(X@3R1r&iKH1|sODprOL>453lJK!W(rBNDKZaOe z^tr;FwKnl)#|4Wi9>5kCtw=j@My{Ae)?r%ay3Q2;+?vQd%|d#uOQ&k+Nv>QRiRB5I zJy^5VX%Edt;O5Oj0qNem+v^tJy|pIR-Dyq1)Z3S`ZOPv}`%chul+!0Sb>^QTo|D)nPE_>&4Jr&jFp5g55%uR$o z3S!$VpHB4~GIyaAws;?J!Sv#E)p*?zy_KTQdSs+2U#_TD+w3780et`OdfvN>w3O)M z_`DK@y!o}>j?X@0@alg`-V*+8ow5pey8#o@SJux63Xf>DbQHDBY6Lt=iyiaf|DSrY z{ErW-fZ@kH$sV}ER|K+-jqRQ^IB54+-}t4iE#wvR8?UoeKDj&#t%sb-L)N~o!d#=4 z)udZ2oRly3knTPZNbVby+PJ9D4<%rUzW=W9)$dFIy?VLO@6xn24;o@HbXiYd>9@%D zp_6uBDia&U`+uGAziX{_jeU#?*ha@6Ny!OOg{&wd1T+@>E_4k4pjPG+b))buqk}aAva4Ew7-iJE8X9aRrF;aG?jKSHYLm5}S7dqqhr`Jam`@Q4Wz_pso+dwdQE9>nBzl++QO-`>bQl{M1(Dfv%E<1?kf zl+?sEcN(<>@7>-2?S$>?DkFEXHXG;$OY#RYf{65yB%Bb)UD&>u_-&$9iqXZdFQY!! zYq#97Z)3qVe1Dd^uT5Hhx>QQ7B0+qp1=zfOG=x+!E;?*96mjrtd|>NNfU9e8b#)gg zl~C>D+g91!_ZageFl1>N{U+E&A(3_{P)*yT?|FHi_%?4hbiyn1d1ZH>s)Jfk- zHfb$Yw}%T5r3e*lJaLcW8sQ&lr=Y_Zum<4Fp00X(RhiwH;q$TWb`y_0Exu4h?w~V4 zglve|mTF?BnN54Ekj#!`#W=1IwD>XgrggNb;kqc^uxTtWf+KX8fj9JWJUn>uBpcfJ z6gek1C!~-!O5|}6&4m%}{5Z|Ov)O}q^pyjU)?VjE=%QG2Q(!JWRhtBjzpcNl z_-D%#fULR(K=5MZyqvfpiG5MFY9BGZLU0*;P%wYGzlJpFaAY{jH8YD{k3(OQ*Y8v{ zkJb`oq%o=>Or=!Z49zO8b`zzU@=)Jl%xQ`Lc{ZLNmo=s&86tv@==3`HH4^kh%AQWJ zec77wt_l%c2FEOTMuTe{qhz$2TxMh;cI%zCHf8JtaJ^_oA9y=Cx`d7^1Viw?X-MhrM3?y>lmv3A!8s)WSw zYaR7l8m8S%&ZqW@C>?kbd7`nx!3LwyCXweR5}3r*FWE52fiw@}3)E)x>R4+UlWwXl zwp-M=ILee6zf4k=?5g`veMQ;V2#Q<(K^{mR=u?T#3}@@%sVmk74ik0(+--%h86}P+ z_6Bh+tnJPZmJ-3GhewPyh-+rPJ1=rQ;)&s@Xa=^Yn2+7@a8UUWu%X z=6)UqE;q#x2L0oEw_`lSdCW{m?77v=6KCYa&A-#3o?AdATKCT9hq+GJBI_ z5;B{}*?=65>tlT04LWK6a2eEPCOt@t{xiTwrTk_;qk4-YRIbG)Fr_kCpsDNPqR7>` z$dSo#c&BqKJ=}KKaMAfFPSLR)=|_zNogiYH_sCK}nD4>f(p5HnN@&beCS*!oI}8#$ zULVBJ*RAeQM06u=yN=%#f~8tqPFazO5RR;mV1z}98E$k6iP0b5L09&1Xv88i{uPVa z5bAw%S%ma?3F8TsCBksxK%YO3$GIq5P+(uG<=QqT&f8mdAI>Qx^z!BXegA2*AHaeW zL>wan!}*ii+gtOHSu{8Iv4?_H3^E@Gb{2?7$hfd|so5A+9<6c%9L>GY(~LtdSi}Cgp$oy8Btt^zL#JI(sdBlK;;D z%8(uSph7k3_J<#N{yA7AL496%!{EGORBiIS}-wIJTE zPwbQG`{N29eoM!v7W7QG;86x5@Bam<`cECK$JWjLs7;a@RBmkEqJtuI66rSw$*9ng z3|5Z`LzA$?9^954*vNV}{;v1}riT=CHvL1ljOQVj%#dNS%Rd^Bh977^?yinQG`EJ0*HB0B^ei`Fd^->|nKAoe z7Wg?2_YjdqA!`!p_Pn4JtTQD1;RM5t;|jYqcgI$0(w}v?%ifrRX)6+T{w2b*)vB7>PYFDne*Vg5R9Ao zr2h6KYd20ien}9rea2rDX>s%e8&}*4Y&ol9wBFk8Fvd1qX)(ht$Ze9Nw@*JII3KND z0uG#-^tvV97TRXa4ND)M0B2g6Hst94p#}o`%oml$;l!2=^nRf(TG(t-&3h97^np;?s)zMz$PpM2D~Y%+`P zn2z&agOD4Y&>CDii^UmLre-qMSZ_K3wZ~#i0fce*ye5YI&V63fF`@YK_GAYX=3w!K zNHD(4=V7^!zLVVV7+)z>o*HB1F5H_tmECOrAw$Kf-2n@g4u@y~HtI^Fb!jlFr9FCi z0X|dNZLr6{g6;)tN%>#tsQmtvxEf1X)RIV5tgXUxrRRUGi_NwftelY&!ed8l8QX_) zd%m9>x~dG(3LC%p8UJ${{gCI=ka+k0U6NK>|39}-Y>U?F%P1qfM+bYPe#Tw2+Gp8%kl{6g4L*a=b zc%M=7z1}>_*y-dj-UUR(74667Xq{o>uD-A)K?z5jOKh;#hFhK|ZTaEp*efzK9@Ax8 zV1$5o$?6l@h2AbS2h3(&vM;BEx}5mjv*A@19YpAyJHvDW1Uk3f+Y2J6@I|V#d*TTE zMBU$&k`wV&lBs+7rMXBEsmVQFa;u1X-AT9mTWR>Gsb+t~}l|YyB2l2_4 zny)*o+sq#xd9kfujDP#J4rW zaQI`zdPjW4o{Q6}HjI%NiYKLSDW#@%CUW8!qaQ*8^9Nfh&-g+$iFtR=dn^I&Bw)XH|b`Uhw_qL9CF6+3N*j9?#R8`MD%Pj~XlX!T`FDR-U+*xbyF| zcb`mXex9myUB;?SqwPNE@NPae(URZaQRlx_`^N$%#mx27BvT7q35t+n;O?r?5Z$`q z>ku=&@rdXxt)bsr@6v6X5A|plcIkUT9-cydU~*+Xoo>y<$#grNqlK9@>uuj<*9mCs zcL?WJ9#WNpJc|H9Gi17NtOD`UC%{>f4_nt}Ho@g|`|}HK)a8|6k{v8!`|2@_Z7c5b z*}c_O)n_wXAFRHMsJvTcML63jBmaiI6^2k{H;kENmiji`vF^_0^vgZM$STn!&LrXe^J$&fN>ODFuwfo(Y^x^0=>nBPE zLGKtIb##gUTXy5$g2L5^6=vumz*YsTVqE~Cew&l>FCq$WP=)CVC;9f+n70kr=%Fi; z@dLoQwt*Fxlh#dv?(LAAep%cT?kF8H1KQ^6{>@f8ZiZ3c8NCc6?j@*tR&FzMv=f;; z-i*UQBwnoDnrasNPv|W3xl=;jjsA;@)7*oV+b-gLC_vVCAo*Zj_l5kY(MFOu^0y6t zL!XE7_m{EXVbN=!(Nwu!6yp6Is`BT5nNPk2?_PG0*)gs#J;4y%Fy#zRX_?BzzpZUj zHW$I*wS7?{p=ucTx%q=ZKNkLdN$n;<1EC0v-_3#_lF-;|D%<@hOrjqtsQd~~`2%O2 zQ%s0Sv-h_SoOWs`cWo6jkJz%DTO1_`ToU@k`6PEYsxCB)QFU|W&!d{J-ob>0z3!y2 zeYQIj3WDgYK^HGfNoL!_c*ER}ST~{x?0r^YSKrtw%(F108OEp#j2?7g!O+7^el z2m{ZyhBEy|RveGqOQ_vto<@?e`jJ7-VvLTLD*URPrXhG4O&QXYhGWdps^>qrbANEO zogmRHo?NToI~+l#{};C09s1{~$YxjM$L#F2)eIUgk2U6N$0stxFj?C(Fm>S~*-H}N zj8omVw|sB3uqK>v$>Q*l&}3g{U@(mOdlcytMhjIhy91ePTPc;KHOdNoBUWh=lZb&+ zB1q={fJtR5F;hH*t$_^|G_PO0(7nvjLV{-;!oQWboLT))X|>MCs8}ky)1+BoAkPL|g1S5w?7nv8RNsN_gG>Lq!~<@S3eITOdV(RLtHW^4 zIY)G5AYJ*UDZf=0$FxZR=oR3LS8c+^wqgQVO~~6?Us)9H#>lST7Tb89?36M+P|2gl z-J{Bqr)~0wjR*wyhfy;|FV-*A7AT&ij}d?R%K4=y3!bGIy~@Ti!a}jkq$5hXf15Yow@Pq2XAcs|qHEK=agc|61f_-0I)5CU7D zgKSUlkXh?CG-f-k3%ijLvx@`>nywO{fHkqQuzX6^#0cqLxyFl=P6Gx%{{$9hMC{@! zr>UZ0(xibAJy?&id?%hillTN}N4}-dPxIjA1y?cBRovl3HD;!|x*A6b)2T;+?3uMg zDUZjICu;o6!-iQ4x(}M7So6I!K}_Bw!%Ut8~u>SyuN}xfu z%}G}fzo0I67xl1_yUXW&&rGI0x`e(yAQ>sj`1Ux=_u)AuPmZUT>ZstuGgF{%34y{a z^xUboG`0A&3ZKK^jr))57z}c@{0Zk*zDY{-9=)VI?NiYTCy3s`^BnnKpSjL8j*Y53 z*vMN0_NVH?`*?|HuE!mRKT_shLoYNXe*tEK{e_x{z$0X?8YH`1{#*jshx;=Z{%2ao zM;Uh)KrU{?i+*H!X}q&DA(J21-5K5d&4X0!;X{T@9)VT@9yKvsrx1rpi9FQ@c!I+k^7S9SCA!*3sET1n5&AZev(wy5fklebt z4~`MAg)q6Oe4b1mft>ddxs&}7f@fE&R)WNfz@ZkNd%|casxkUg)lTplC}`keGrbuw zRr8f548~1Q=R~?5@W2V0LoeM3v|zx(6VqHUeX9HQ?;3) zfDVrq{2Q;JlSmq2A|BcK@w3@Vz>2n+_H~tH)2k14a6A56Up?(&_lT^ElPVI{u}ShE z?^6S>mM~caOByylY+F`rN`)k1wEg^uB_hnI-oPs?5(xhQ&S6tuJ^ocXs+J^QA(>&PU!7`>eJsae(|aF=N7+Psm1L)J8UNfOyB5%VBNk%R zI|y}isT8Vdcylg={?sAcQUf=oQa(`ahBVh)rm@sqtFjg{oHeT?{5P_lyAMbXJLpg^ zg=%2f(m0A1O$J_3-pJos$V{Q8VJO%?Ff1dI5pSPk(HI@m*&FOu%0l(r9QhT||GFXf ze}~gdXktK%OCrgM62rZO+G{My)trAjw7t>W6cvc*5>=0zf8@ai2&V^fd(1c6Yr&&z%0ayA| z9AXAbY?kHZC6UE#p`W|H4o}5JS%7x>! zlM;|@`>ZK}%Y!5tnNYIEEn$NC*v>vSfylzBOxTx5o=1`F6GRJF5$*%U7-lv3(+%t|H0Xa-ozIAz7geoXpR1)Qxs=u#gTgLFpp&(5wkIgZKp8^GcXW4&DZJn0|K7A=Vz z*@{6XwSKu)lT}$z(*a(C+xpZN83w0pZTR|&rv=Eh2DNUDk!%GlFJ_Q~XF1(t{}`lI z08kmysrCQf7}+~^TyFfy}qOM?zm$k8OSW6XTcdu&36mm1`ntN zTygVF616!gG>Bmpm@d?DT&y|`LtRx*IkMF`FqFbTA4=GulQ2wQ8k%T*66Jw0{BXmOqZS= zE`sQx+gp-+gGD}*_Qcb}Q9#+l!-EqZDb?u~Ga5ou^qkrD_ypEN%HvEf$nCd?sW^2f zcRm&yF&SXfkuRZgaU96IBfwc7Z+NB3z_7<-t2-e4&<`j%IwD3;E)j9Ghic zNN(@kQ2iw6-3M^T!e{jIoeHaYSHYA-4#H)wMYVa_=HkBBv%YAM+0~|AsB4Cn(u4r|S0ls-#TvjNO&aqKd!tWSShydGZ(p zOjUgI_r6lSco{Zu)6;TuakXF?r3&zJnc}YHLf%mD`%2>ayzL4WFGaPl^aY|e8X>3y zil}|fa?2}|Z;XCeO_&1bR&&EactiD`2yxnWm)~za6GL}^v$P07MXzioveZ2J<4_J3 z$CE;?EDassPDsTrILe`CFU5>Hh&!QQ!J7e}Wl3be^k<4FSh~m7>(2{~!V*EVi2}t) zdqOutp8laGaB@XF^#Vy|G2WD>q@NI3H>Wd@gIwz(buaCi^36xkJ&NbTMO#p~tB!09 z&1E`)%&L%myTS+(nYOgME|iyi6RX0RD%A6}eksK?oF<59i)*d1R=^ReFS5*#PVCYw z1eJNCTt~z-x4jBUTTgd5yc-*s?f|T|m1H^#qt4-@JGZ{kq%zieEfp7%`4L%~`RbD2 zEBuWqSG&apA0FNJqCQhQax*_G$Kzu_m-j=X}E==USF|*_bYQ~m7K0mL1lk%HZc=$M~(9076gqLQ^ryBr6&y0-w>uC1$ zkCV~*Tz`3LUXDei+cP(ZRy7?O6QfW-%0>ZM56FRD)iGFb9iBe)y#@1t_swN{Uz$5t z?`TY&o@cI~A5jCzbA2o=tD9NqIBn5@`Hbu$e|b&G~YRuC>+)7+qws zlYJc2m)a4!mhrZkC6i8im}hRdze%-=p1jcqIEh&5&B74vQW{%R@YOcsilPy_@AA z#j_omk91tW>3R!EB;|X@FaJ9_ZF205^7fP1S0B=PTIvS{Cxv@ zJFa{m%rnc_0H7OcZQ@lXq2lO+26$zSu(g&{<&iCiSK;kr0X3#?a-`xB+Ni;Wi z<|oyr3msyTd}YDEkBT)Yw777b?aqI;fz8(h`fiUG70~|H`O5EiTCPcuz+9UEC-&!> oOnK;kXHICiCdzblQe5vac2X2zLNH+UVDA6KMP!6a-|71N7dBO9TL1t6 literal 0 Hc-jL100001 diff --git a/docs/src/path_params/tutorial005.py b/docs/src/path_params/tutorial005.py new file mode 100644 index 0000000000..d4f24bce70 --- /dev/null +++ b/docs/src/path_params/tutorial005.py @@ -0,0 +1,21 @@ +from enum import Enum + +from fastapi import FastAPI + + +class ModelName(Enum): + alexnet = "alexnet" + resnet = "resnet" + lenet = "lenet" + + +app = FastAPI() + + +@app.get("/model/{model_name}") +async def get_model(model_name: ModelName): + if model_name == ModelName.alexnet: + return {"model_name": model_name, "message": "Deep Learning FTW!"} + if model_name.value == "lenet": + return {"model_name": model_name, "message": "LeCNN all the images"} + return {"model_name": model_name, "message": "Have some residuals"} diff --git a/docs/src/query_params/tutorial007.py b/docs/src/query_params/tutorial007.py new file mode 100644 index 0000000000..8ef5b3004b --- /dev/null +++ b/docs/src/query_params/tutorial007.py @@ -0,0 +1,11 @@ +from typing import Optional + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_user_item(item_id: str, limit: Optional[int] = None): + item = {"item_id": item_id, "limit": limit} + return item diff --git a/docs/src/query_params_str_validations/tutorial012.py b/docs/src/query_params_str_validations/tutorial012.py new file mode 100644 index 0000000000..7ea9f017df --- /dev/null +++ b/docs/src/query_params_str_validations/tutorial012.py @@ -0,0 +1,11 @@ +from typing import List + +from fastapi import FastAPI, Query + +app = FastAPI() + + +@app.get("/items/") +async def read_items(q: List[str] = Query(["foo", "bar"])): + query_items = {"q": q} + return query_items diff --git a/docs/tutorial/path-params.md b/docs/tutorial/path-params.md index b7cf9d4df5..96e29366e1 100644 --- a/docs/tutorial/path-params.md +++ b/docs/tutorial/path-params.md @@ -35,7 +35,7 @@ If you run this example and open your browser at "parsing". ## Data validation @@ -61,12 +61,11 @@ because the path parameter `item_id` had a value of `"foo"`, which is not an `in The same error would appear if you provided a `float` instead of an int, as in: http://127.0.0.1:8000/items/4.2 - !!! check So, with the same Python type declaration, **FastAPI** gives you data validation. - Notice that the error also clearly states exactly the point where the validation didn't pass. - + Notice that the error also clearly states exactly the point where the validation didn't pass. + This is incredibly helpful while developing and debugging code that interacts with your API. ## Documentation @@ -96,8 +95,7 @@ All the data validation is performed under the hood by `Enum`. + +### Create an `Enum` class + +Import `Enum` and create a sub-class that inherits from it. + +And create class attributes with fixed values, those fixed values will be the available valid values: + +```Python hl_lines="1 6 7 8 9" +{!./src/path_params/tutorial005.py!} +``` + +!!! info + Enumerations (or enums) are available in Python since version 3.4. + +!!! tip + If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning models. + +### Declare a *path parameter* + +Then create a *path parameter* with a type annotation using the enum class you created (`ModelName`): + +```Python hl_lines="16" +{!./src/path_params/tutorial005.py!} +``` + +### Check the docs + +Because the available values for the *path parameter* are specified, the interactive docs can show them nicely: + + + +### Working with Python *enumerations* + +The value of the *path parameter* will be an *enumeration member*. + +#### Compare *enumeration members* + +You can compare it with the *enumeration member* in your created enum `ModelName`: + +```Python hl_lines="17" +{!./src/path_params/tutorial005.py!} +``` + +#### Get the *enumeration value* + +You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`: + +```Python hl_lines="19" +{!./src/path_params/tutorial005.py!} +``` + +!!! tip + You could also access the value `"lenet"` with `ModelName.lenet.value`. + +#### Return *enumeration members* + +You can return *enum members* from your *path operation*, even nested in a JSON body (e.g. a `dict`). + +They will be converted to their corresponding values before returning them to the client: + +```Python hl_lines="18 20 21" +{!./src/path_params/tutorial005.py!} +``` + ## Path parameters containing paths Let's say you have a *path operation* with a path `/files/{file_path}`. diff --git a/docs/tutorial/query-params-str-validations.md b/docs/tutorial/query-params-str-validations.md index a82018437b..4258a71fdd 100644 --- a/docs/tutorial/query-params-str-validations.md +++ b/docs/tutorial/query-params-str-validations.md @@ -12,7 +12,6 @@ The query parameter `q` is of type `str`, and by default is `None`, so it is opt We are going to enforce that even though `q` is optional, whenever it is provided, it **doesn't exceed a length of 50 characters**. - ### Import `Query` To achieve that, first import `Query` from `fastapi`: @@ -29,7 +28,7 @@ And now use it as the default value of your parameter, setting the parameter `ma {!./src/query_params_str_validations/tutorial002.py!} ``` -As we have to replace the default value `None` with `Query(None)`, the first parameter to `Query` serves the same purpose of defining that default value. +As we have to replace the default value `None` with `Query(None)`, the first parameter to `Query` serves the same purpose of defining that default value. So: @@ -41,7 +40,7 @@ q: str = Query(None) ```Python q: str = None -``` +``` But it declares it explicitly as being a query parameter. @@ -53,7 +52,6 @@ q: str = Query(None, max_length=50) This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema path operation. - ## Add more validations You can also add a parameter `min_length`: @@ -119,7 +117,7 @@ So, when you need to declare a value as required while using `Query`, you can us {!./src/query_params_str_validations/tutorial006.py!} ``` -!!! info +!!! info If you hadn't seen that `...` before: it is a a special single value, it is part of Python and is called "Ellipsis". This will let **FastAPI** know that this parameter is required. @@ -156,11 +154,35 @@ So, the response to that URL would be: !!! tip To declare a query parameter with a type of `list`, like in the example above, you need to explicitly use `Query`, otherwise it would be interpreted as a request body. - The interactive API docs will update accordingly, to allow multiple values: +### Query parameter list / multiple values with defaults + +And you can also define a default `list` of values if none are provided: + +```Python hl_lines="9" +{!./src/query_params_str_validations/tutorial012.py!} +``` + +If you go to: + +``` +http://localhost:8000/items/ +``` + +the default of `q` will be: `["foo", "bar"]` and your response will be: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + ## Declare more metadata You can add more information about the parameter. diff --git a/docs/tutorial/query-params.md b/docs/tutorial/query-params.md index 54a71f36d6..85a69205d4 100644 --- a/docs/tutorial/query-params.md +++ b/docs/tutorial/query-params.md @@ -186,3 +186,39 @@ In this case, there are 3 query parameters: * `needy`, a required `str`. * `skip`, an `int` with a default value of `0`. * `limit`, an optional `int`. + +!!! tip + You could also use `Enum`s the same way as with *path parameters*. + +## Optional type declarations + +!!! warning + This might be an advanced use case. + + You might want to skip it. + +If you are using `mypy` it could complain with type declarations like: + +```Python +limit: int = None +``` + +With an error like: + +``` +Incompatible types in assignment (expression has type "None", variable has type "int") +``` + +In those cases you can use `Optional` to tell `mypy` that the value could be `None`, like: + +```Python +from typing import Optional + +limit: Optional[int] = None +``` + +In a *path operation* that could look like: + +```Python hl_lines="9" +{!./src/query_params/tutorial007.py!} +``` diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 194187f28c..2596d57541 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -1,8 +1,6 @@ import asyncio import inspect from copy import deepcopy -from datetime import date, datetime, time, timedelta -from decimal import Decimal from typing import ( Any, Callable, @@ -14,8 +12,8 @@ from typing import ( Tuple, Type, Union, + cast, ) -from uuid import UUID from fastapi import params from fastapi.dependencies.models import Dependant, SecurityRequirement @@ -23,7 +21,7 @@ from fastapi.security.base import SecurityBase from fastapi.security.oauth2 import OAuth2, SecurityScopes from fastapi.security.open_id_connect_url import OpenIdConnect from fastapi.utils import get_path_param_names -from pydantic import BaseConfig, Schema, create_model +from pydantic import BaseConfig, BaseModel, Schema, create_model from pydantic.error_wrappers import ErrorWrapper from pydantic.errors import MissingError from pydantic.fields import Field, Required, Shape @@ -35,22 +33,21 @@ from starlette.datastructures import FormData, Headers, QueryParams, UploadFile from starlette.requests import Request from starlette.websockets import WebSocket -param_supported_types = ( - str, - int, - float, - bool, - UUID, - date, - datetime, - time, - timedelta, - Decimal, -) - -sequence_shapes = {Shape.LIST, Shape.SET, Shape.TUPLE} +sequence_shapes = { + Shape.LIST, + Shape.SET, + Shape.TUPLE, + Shape.SEQUENCE, + Shape.TUPLE_ELLIPS, +} sequence_types = (list, set, tuple) -sequence_shape_to_type = {Shape.LIST: list, Shape.SET: set, Shape.TUPLE: tuple} +sequence_shape_to_type = { + Shape.LIST: list, + Shape.SET: set, + Shape.TUPLE: tuple, + Shape.SEQUENCE: list, + Shape.TUPLE_ELLIPS: list, +} def get_param_sub_dependant( @@ -126,6 +123,26 @@ def get_flat_dependant(dependant: Dependant) -> Dependant: return flat_dependant +def is_scalar_field(field: Field) -> bool: + return ( + field.shape == Shape.SINGLETON + and not lenient_issubclass(field.type_, BaseModel) + and not isinstance(field.schema, params.Body) + ) + + +def is_scalar_sequence_field(field: Field) -> bool: + if field.shape in sequence_shapes and not lenient_issubclass( + field.type_, BaseModel + ): + if field.sub_fields is not None: + for sub_field in field.sub_fields: + if not is_scalar_field(sub_field): + return False + return True + return False + + def get_dependant( *, path: str, call: Callable, name: str = None, security_scopes: List[str] = None ) -> Dependant: @@ -133,83 +150,78 @@ def get_dependant( endpoint_signature = inspect.signature(call) signature_params = endpoint_signature.parameters dependant = Dependant(call=call, name=name) - for param_name in signature_params: - param = signature_params[param_name] + for param_name, param in signature_params.items(): if isinstance(param.default, params.Depends): sub_dependant = get_param_sub_dependant( param=param, path=path, security_scopes=security_scopes ) dependant.dependencies.append(sub_dependant) - for param_name in signature_params: - param = signature_params[param_name] - if ( - (param.default == param.empty) or isinstance(param.default, params.Path) - ) and (param_name in path_param_names): - assert ( - lenient_issubclass(param.annotation, param_supported_types) - or param.annotation == param.empty + for param_name, param in signature_params.items(): + if isinstance(param.default, params.Depends): + continue + if add_non_field_param_to_dependency(param=param, dependant=dependant): + continue + param_field = get_param_field(param=param, default_schema=params.Query) + if param_name in path_param_names: + assert param.default == param.empty or isinstance( + param.default, params.Path + ), "Path params must have no defaults or use Path(...)" + assert is_scalar_field( + field=param_field ), f"Path params must be of one of the supported types" - add_param_to_fields( + param_field = get_param_field( param=param, - dependant=dependant, default_schema=params.Path, force_type=params.ParamTypes.path, ) - elif ( - param.default == param.empty - or param.default is None - or isinstance(param.default, param_supported_types) - ) and ( - param.annotation == param.empty - or lenient_issubclass(param.annotation, param_supported_types) - ): - add_param_to_fields( - param=param, dependant=dependant, default_schema=params.Query - ) - elif isinstance(param.default, params.Param): - if param.annotation != param.empty: - origin = getattr(param.annotation, "__origin__", None) - param_all_types = param_supported_types + (list, tuple, set) - if isinstance(param.default, (params.Query, params.Header)): - assert lenient_issubclass( - param.annotation, param_all_types - ) or lenient_issubclass( - origin, param_all_types - ), f"Parameters for Query and Header must be of type str, int, float, bool, list, tuple or set: {param}" - else: - assert lenient_issubclass( - param.annotation, param_supported_types - ), f"Parameters for Path and Cookies must be of type str, int, float, bool: {param}" - add_param_to_fields( - param=param, dependant=dependant, default_schema=params.Query - ) - elif lenient_issubclass(param.annotation, Request): - dependant.request_param_name = param_name - elif lenient_issubclass(param.annotation, WebSocket): - dependant.websocket_param_name = param_name - elif lenient_issubclass(param.annotation, BackgroundTasks): - dependant.background_tasks_param_name = param_name - elif lenient_issubclass(param.annotation, SecurityScopes): - dependant.security_scopes_param_name = param_name - elif not isinstance(param.default, params.Depends): - add_param_to_body_fields(param=param, dependant=dependant) + add_param_to_fields(field=param_field, dependant=dependant) + elif is_scalar_field(field=param_field): + add_param_to_fields(field=param_field, dependant=dependant) + elif isinstance( + param.default, (params.Query, params.Header) + ) and is_scalar_sequence_field(param_field): + add_param_to_fields(field=param_field, dependant=dependant) + else: + assert isinstance( + param_field.schema, params.Body + ), f"Param: {param_field.name} can only be a request body, using Body(...)" + dependant.body_params.append(param_field) return dependant -def add_param_to_fields( +def add_non_field_param_to_dependency( + *, param: inspect.Parameter, dependant: Dependant +) -> Optional[bool]: + if lenient_issubclass(param.annotation, Request): + dependant.request_param_name = param.name + return True + elif lenient_issubclass(param.annotation, WebSocket): + dependant.websocket_param_name = param.name + return True + elif lenient_issubclass(param.annotation, BackgroundTasks): + dependant.background_tasks_param_name = param.name + return True + elif lenient_issubclass(param.annotation, SecurityScopes): + dependant.security_scopes_param_name = param.name + return True + return None + + +def get_param_field( *, param: inspect.Parameter, - dependant: Dependant, - default_schema: Type[Schema] = params.Param, + default_schema: Type[params.Param] = params.Param, force_type: params.ParamTypes = None, -) -> None: +) -> Field: default_value = Required + had_schema = False if not param.default == param.empty: default_value = param.default - if isinstance(default_value, params.Param): + if isinstance(default_value, Schema): + had_schema = True schema = default_value default_value = schema.default - if getattr(schema, "in_", None) is None: + if isinstance(schema, params.Param) and getattr(schema, "in_", None) is None: schema.in_ = default_schema.in_ if force_type: schema.in_ = force_type @@ -234,43 +246,26 @@ def add_param_to_fields( class_validators={}, schema=schema, ) - if schema.in_ == params.ParamTypes.path: + if not had_schema and not is_scalar_field(field=field): + field.schema = params.Body(schema.default) + return field + + +def add_param_to_fields(*, field: Field, dependant: Dependant) -> None: + field.schema = cast(params.Param, field.schema) + if field.schema.in_ == params.ParamTypes.path: dependant.path_params.append(field) - elif schema.in_ == params.ParamTypes.query: + elif field.schema.in_ == params.ParamTypes.query: dependant.query_params.append(field) - elif schema.in_ == params.ParamTypes.header: + elif field.schema.in_ == params.ParamTypes.header: dependant.header_params.append(field) else: assert ( - schema.in_ == params.ParamTypes.cookie - ), f"non-body parameters must be in path, query, header or cookie: {param.name}" + field.schema.in_ == params.ParamTypes.cookie + ), f"non-body parameters must be in path, query, header or cookie: {field.name}" dependant.cookie_params.append(field) -def add_param_to_body_fields(*, param: inspect.Parameter, dependant: Dependant) -> None: - default_value = Required - if not param.default == param.empty: - default_value = param.default - if isinstance(default_value, Schema): - schema = default_value - default_value = schema.default - else: - schema = Schema(default_value) - required = default_value == Required - annotation = get_annotation_from_schema(param.annotation, schema) - field = Field( - name=param.name, - type_=annotation, - default=None if required else default_value, - alias=schema.alias or param.name, - required=required, - model_config=BaseConfig, - class_validators={}, - schema=schema, - ) - dependant.body_params.append(field) - - def is_coroutine_callable(call: Callable) -> bool: if inspect.isfunction(call): return asyncio.iscoroutinefunction(call) @@ -354,7 +349,7 @@ def request_params_to_args( if field.shape in sequence_shapes and isinstance( received_params, (QueryParams, Headers) ): - value = received_params.getlist(field.alias) + value = received_params.getlist(field.alias) or field.default else: value = received_params.get(field.alias) schema: params.Param = field.schema diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 87e223cb6a..26d491beae 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Sequence, Tuple, Type +from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, cast from fastapi import routing from fastapi.dependencies.models import Dependant @@ -9,7 +9,7 @@ from fastapi.openapi.models import OpenAPI from fastapi.params import Body, Param from fastapi.utils import get_flat_models_from_routes, get_model_definitions from pydantic.fields import Field -from pydantic.schema import Schema, field_schema, get_model_name_map +from pydantic.schema import field_schema, get_model_name_map from pydantic.utils import lenient_issubclass from starlette.responses import JSONResponse from starlette.routing import BaseRoute @@ -97,12 +97,8 @@ def get_openapi_operation_request_body( body_schema, _ = field_schema( body_field, model_name_map=model_name_map, ref_prefix=REF_PREFIX ) - schema: Schema = body_field.schema - if isinstance(schema, Body): - request_media_type = schema.media_type - else: - # Includes not declared media types (Schema) - request_media_type = "application/json" + body_field.schema = cast(Body, body_field.schema) + request_media_type = body_field.schema.media_type required = body_field.required request_body_oai: Dict[str, Any] = {} if required: diff --git a/pyproject.toml b/pyproject.toml index e8be418388..8700b0ef33 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ classifiers = [ ] requires = [ "starlette >=0.11.1,<=0.12.0", - "pydantic >=0.17,<=0.26.0" + "pydantic >=0.26,<=0.26.0" ] description-file = "README.md" requires-python = ">=3.6" diff --git a/tests/test_invalid_sequence_param.py b/tests/test_invalid_sequence_param.py new file mode 100644 index 0000000000..bdc4b1bcbe --- /dev/null +++ b/tests/test_invalid_sequence_param.py @@ -0,0 +1,29 @@ +from typing import List, Tuple + +import pytest +from fastapi import FastAPI, Query +from pydantic import BaseModel + + +def test_invalid_sequence(): + with pytest.raises(AssertionError): + app = FastAPI() + + class Item(BaseModel): + title: str + + @app.get("/items/") + def read_items(q: List[Item] = Query(None)): + pass # pragma: no cover + + +def test_invalid_tuple(): + with pytest.raises(AssertionError): + app = FastAPI() + + class Item(BaseModel): + title: str + + @app.get("/items/") + def read_items(q: Tuple[Item, Item] = Query(None)): + pass # pragma: no cover diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py new file mode 100644 index 0000000000..3245cdcebe --- /dev/null +++ b/tests/test_tutorial/test_path_params/test_tutorial005.py @@ -0,0 +1,120 @@ +import pytest +from starlette.testclient import TestClient + +from path_params.tutorial005 import app + +client = TestClient(app) + +openapi_schema = { + "openapi": "3.0.2", + "info": {"title": "Fast API", "version": "0.1.0"}, + "paths": { + "/model/{model_name}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Get Model", + "operationId": "get_model_model__model_name__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Model_Name", + "enum": ["alexnet", "resnet", "lenet"], + }, + "name": "model_name", + "in": "path", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"type": "string"}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, +} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == openapi_schema + + +@pytest.mark.parametrize( + "url,status_code,expected", + [ + ( + "/model/alexnet", + 200, + {"model_name": "alexnet", "message": "Deep Learning FTW!"}, + ), + ( + "/model/lenet", + 200, + {"model_name": "lenet", "message": "LeCNN all the images"}, + ), + ( + "/model/resnet", + 200, + {"model_name": "resnet", "message": "Have some residuals"}, + ), + ( + "/model/foo", + 422, + { + "detail": [ + { + "loc": ["path", "model_name"], + "msg": "value is not a valid enumeration member", + "type": "type_error.enum", + } + ] + }, + ), + ], +) +def test_get_enums(url, status_code, expected): + response = client.get(url) + assert response.status_code == status_code + assert response.json() == expected diff --git a/tests/test_tutorial/test_query_params/test_tutorial007.py b/tests/test_tutorial/test_query_params/test_tutorial007.py new file mode 100644 index 0000000000..a0fb238501 --- /dev/null +++ b/tests/test_tutorial/test_query_params/test_tutorial007.py @@ -0,0 +1,95 @@ +from starlette.testclient import TestClient + +from query_params.tutorial007 import app + +client = TestClient(app) + +openapi_schema = { + "openapi": "3.0.2", + "info": {"title": "Fast API", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read User Item", + "operationId": "read_user_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item_Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": {"title": "Limit", "type": "integer"}, + "name": "limit", + "in": "query", + }, + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"type": "string"}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, +} + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == openapi_schema + + +def test_read_item(): + response = client.get("/items/foo") + assert response.status_code == 200 + assert response.json() == {"item_id": "foo", "limit": None} + + +def test_read_item_query(): + response = client.get("/items/foo?limit=5") + assert response.status_code == 200 + assert response.json() == {"item_id": "foo", "limit": 5} diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py new file mode 100644 index 0000000000..1e00c5017f --- /dev/null +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -0,0 +1,96 @@ +from starlette.testclient import TestClient + +from query_params_str_validations.tutorial012 import app + +client = TestClient(app) + +openapi_schema = { + "openapi": "3.0.2", + "info": {"title": "Fast API", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + "default": ["foo", "bar"], + }, + "name": "q", + "in": "query", + } + ], + } + } + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"type": "string"}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, +} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == openapi_schema + + +def test_default_query_values(): + url = "/items/" + response = client.get(url) + assert response.status_code == 200 + assert response.json() == {"q": ["foo", "bar"]} + + +def test_multi_query_values(): + url = "/items/?q=baz&q=foobar" + response = client.get(url) + assert response.status_code == 200 + assert response.json() == {"q": ["baz", "foobar"]} -- 2.47.3