From 60b45168947adea5f4c9c7af2e44aa5f79d83a8a Mon Sep 17 00:00:00 2001 From: kennethreitz Date: Tue, 24 Mar 2026 19:52:20 +0000 Subject: [PATCH] deploy: 3d5f3c7e93ab19ed4e939451457eec7daa1fc394 --- .doctrees/api.doctree | Bin 225069 -> 229808 bytes .doctrees/backlog.doctree | Bin 4589 -> 4513 bytes .doctrees/cli.doctree | Bin 11717 -> 14446 bytes .doctrees/deployment.doctree | Bin 19071 -> 29159 bytes .doctrees/environment.pickle | Bin 235230 -> 238701 bytes .doctrees/index.doctree | Bin 20393 -> 21606 bytes .doctrees/testing.doctree | Bin 27947 -> 32381 bytes .doctrees/tour.doctree | Bin 72928 -> 82488 bytes .doctrees/tutorial-middleware.doctree | Bin 22643 -> 27056 bytes _sources/api.rst.txt | 91 ++++++++++++++++++++++-- _sources/backlog.md.txt | 9 +-- _sources/cli.rst.txt | 19 +++++ _sources/deployment.rst.txt | 82 ++++++++++++++++++++++ _sources/index.rst.txt | 8 ++- _sources/testing.rst.txt | 54 +++++++++++++++ _sources/tour.rst.txt | 75 +++++++++++++++++++- _sources/tutorial-middleware.rst.txt | 41 +++++++++++ api.html | 96 ++++++++++++++++++++++++-- backlog.html | 9 +-- cli.html | 18 +++++ deployment.html | 80 +++++++++++++++++++++ index.html | 17 ++++- searchindex.js | 2 +- testing.html | 53 ++++++++++++++ tour.html | 74 +++++++++++++++++++- tutorial-middleware.html | 39 +++++++++++ 26 files changed, 741 insertions(+), 26 deletions(-) diff --git a/.doctrees/api.doctree b/.doctrees/api.doctree index cd61576658d636de351b52e82151669badb4748f..78ecd0659a102f5150d94f38ff71a830490092f3 100644 GIT binary patch literal 229808 zcmeFa3!G#}RX?81zGru{*}SvaBsa4m+q=xpy9ADF#;Z&jUB=bWnZsH#(su71;sQ&yZp|8-6)HKrHZ)mm$`-YAt@OPzJ} zVy;|oFTHVT=PQ;TSt@kaH;YGGjfLiPd8u;>N=#R(wNkTOUwUAva!O}yt32JVHtM>3 zWp!muW$gn?1$r-db-n;ij2g);LG=K)FAj+*eR6a%!{m-vnk|?a1FQR;V zsd9Q}{e;G_va+*AA$DhHRjpbtFWtE?RqPBE+wEp`YN3q|Q3qC5OD!PVSvy@Twpw_J z=hgM%oP1hWT9`LKri#;to8=iQv(Q=FF3!@YrOIiQt(6Ux3o0us+d9t~t2E}yW6gzn zz1$o-+GrjgYnEH{jd}?`%@fdUjY;&ziu2XcW()XV_<~axrqJQ_=umOCS)8xf#CheR zO0^Zu7iY^6cd`XyskV3E)527(Ivw4;*se6{5lA^2-PUME3oWWrK31HYua#Rv#d--p z=4-`zkvP*DiCX1y)UK4HJ!p2%BFsdvDu!CsH}Y328$<01xE^%vpZ8kT%LOL zErVmTq}U7Ej!N3zS-B7#>}+n$SE}`6qs3B5iRH%ma=lco&rTczb8M1r>FN^8)S7Bt zhy=?qdeCQZAJ%m!iOB z_r1Z{^}xZ|a(l_?4k2+(Wn1N$5VciAScu!%oz;TRR$m=@SFV*K zy|TKq!IA|@$Q$@urKG60iX_EqYbHRq%Dzk_o61D8%8MLw&1WZ9<;5L|buxKYj9T4s zNK;N_B(*eR5n9X+Aoh@^mzo7P^NY@=Ll}ZI|J_XUkR zal!fZKxDUu`$2*`jrp@#tVNBf7!!8Xn2E|q%FRVHy+p-%5;QSoj7Iy~QKeBUwW38Z zJ8Cv)G94M3tCmW&GDNUE61B^iZHn|-2-kF@K2x1tXsY@*H_P}IHR|Q4*cNk7yD?8t zslB1OMromjFPMB5TIHyU5{;--p1~9@0Rq`-vm6~QPhswA9;r^3<;((K5xE|BLihi#ZvJ=)Ho2%_<%@@h)UN?^+gkez@HpY9D*4bi>#H%~2tFS+h zStC$d;i>wovz8P>RoK8VZ{~~D=2B;ioS3gOBXp^Ax_q}=kK(1unmgM|MbbMTVH7Ic zr0G`qGuAq}z^`dRq~R!Z&Z9A25O#W0ts69U!Zpwc(5w+e;*`!BWgA(>pHRo?S71mX<0{QU|}NXni4f6cg^%omFs^rn^X8z?akL%LI+lVtb)!dp`F)_taBP zq3Led2sGW)!tD5M#afH>D7i@EcS2K+L_DX-U({B!I!`vd`i{AFt~Jq^nNUhmy@u{> z7pL3m7nFFp-r^>C%9Bm1Uur_zG1i){l;?`0i*vOd@Dkck-qRDMYIA&td^RuT42TM% z4Bl(?FU#wn_*7hIHzt64alWi(Kx=Z_apzr!_8z?T<^#7LLQy&4PE=^_QuMGUT#2)o zN!3Sso*>_8t~LJ94l(ylVBRc|y#R9V*b}LO>RY8;gjYuI3p+<5^>VHZ_o*aa?sy)d zVLmmQ)!Ax&qFJ6TA44UHfT||H>9$~(H(KQh55ipW*aVz0)V=!h%O3$PoaxzR0z9(0 zGDs~o$izYw1gTYL;O`Zg;mz`c3*}aOqFR#Vk<&Rz+GZhX#d^I#9C7^b&TaQ!&vHl# z1ukl7PjvnEHk|A|(GD@XcHD5oNMuThiN-1u;XAw<;l^LxIo)r~lKswV(H`3x>X)`| z;tj9^(yffnio;7q&zgWJF8)&-O zU-^^DpJHN&SBm15@5ruo+GCCRHsS)UcDdAUG-}gD46HHfr;lAVdIkP><=C;SpEXvi zPL0hA_nqF3wO~H&#w33jGSjkx2NW=vUnFO&g-IIf9+tD2|LCij1225R3PGWbQW)Sa zQ?$aO&ycCagtA{5iajexu|j79=Cs{VLjpi&6TuUF7rz}hm??CnL!tNz`pNjN7x?1kCrUlIsvd)TKa-d$_*&?J7f;|DP4Zph4w93VkB*!v(y0JJl)hr*W z`g*{WIh&d_qp2DkP4;x$*)S<&bUt;JKarI#eMWMjX8`$X~h z0sO<3X=j6Fe`%J8DUB?*34dBzEsFE>seTz^b_kG&3`-N(js102)Vp=f>m+Wkk+@CU zxUCpxKzK4hekuqgei)y-)Tknugi_IQyv}N2A~6{C%Yb@32#Tiunc_mNJ#nO1TPVAI z>zvtIm?xKiqBV!;@`DQv3c)`{hBN}BvBadeZVj+*$XLsgbMfnK>Z$bx6{u9dOxHdT z>{|ThBq}Oiy$|0Ors6ET`pYns5U(T@i&v}2Vq{jyAErB>4g>lvzdJqHBY_XZo{hEx zlf(PF6$X@-NfP)#OcK_-?N=r- z3Uj1(KABn0JHxQu;U0zP_i;?Ul>qchDqQ9G3@L_w?Bz%r~4(D zb=@Bf|E9tn4)O0L+4(mgh7#hRgp!qiFAD?8%RdQxApUK%<1ZCl}Q(d z0p(?q1U?XxE>JX23Nk10Y?D)-Ip@7K{JT2b;Sm3>MAeMu#w}qeA^u4y7XLOmadzE7 z_pRyRfiUR29F^z{#L+VoRtAzdIb_OlFYQ;Ri-*Hq4DoO_I}aDbP(nPEP%Iv<;}sF^ zn0aBk^@Cx6c{wMM7>IM{D2{l`H%ZLfXcy&Px-U&ne=gk95CeZYI|JVph7w|+gkmvp zyEY0-zHON`sG3n1 zo)?A^VxNR!v2PV^iQ!(!AErB(g#qPdm;^o$!_G}vxlZESkSWU@v|pKS-Wcv?XwY4k zoooBUP(oajP%N%(v{&u9bM8yiz5By}^KwxlGY}WIbZs+8;@<|V6!+12XS&!9cQM4l z`Rp8gWf)3`gA$6x!5%^XH-tgu<(ULO5YIMy`#_R7He|{$!|YdvUyp~o7vk63v-9h> z!%#x}l29yu1q1&d3~LCC^_$pM4h?1Z?kAKs%A8cE(t>kNtA?Q zNz~iE3pTSc(Z4HjHNr3!W>enLC|NhqXgs5PQ(%(7Z*qz;^}V;IpSOqm8Jb3K$u9IS z3PTAAy@X;3eNe}h!hrI!O#&Z?ZCg1`*}d~8k$p~a%|7?7Vc#R+{)X7Mn4NvE4?_vD zPeQTSx6$6Y%KdX+n(nFn=97@ZJoRfli+hQEL^;E{v7s;RVU~)uH3s%dj|0nyK5hFKH`946{Th; zaCm91xb#}uK=>ls4z!gwT3g$Qv71Sr62`9f(IeIJ(P^AuU+Qe;$BANny5j7a>~$oC z&f@Z!+H)r4u@`SsHV%%<<00|wz)K(It-Od(y@XhyQI)#^Ez*3xD321a#3n-=+NB-K z@-U{m*RiukLKbI()zNQ&RlDrhbk@x*)M{dnqQqfnqTQG#y0%+O@pFKJc>Nkw7avSX z+J^V7$~H|xp!yBk0%h$Wr+o-GN@49Y<+J?eH0ecjnsmNd#SXtkI-rSto8o|GBrw#+ zGFUR0N)hI1?VTsQhrXXuLmFVq+XQ4nI z1Nt(7Lkx4>)s4uY44*8DcJGczfN;nN$B-KkA)NfBGr%+0J1mPuGgV|U7>(|&)@sod zPA-e1#3fMzr-!5J3>_FQHOj5}jy4Y1;B#par(OYt(-+_%79UK-`H4n-*1`@WPh+D= zY`roheq}BaKPpN5F#Z8)>CF98kG|19ltN$ZEr%%c!0{smGBR`#!*s=mZB0u^Z_qu) zw#JL1AMR#muUvdocDXHz#>emv@3B@Rz!CwyYD247K`GEB2N8kz6&5xfZ~aT{5BA;~ zYW*tpD|Jh^PX)#JcL*vZF`mBI&7sWqr!qcY@55a80r%$mFN#haH?HrumaT~A`(`3} zB>MJ4`|l9P|L?=Uy35f~8uCME$uSU>M~b^T>0oMH)wr!CbnIUJWK&2sypLw6sHUU=Y+RQGsFbV>=u237{1WjOK}nupJ3WPFhX){xuM!#`CT6Pbls%{yX^nvR zE%X+UAwi=sdN~B7=mc0uMD9|lBd}N`GFypbQk0Tp4kxbX7FunZV<=Gx&qlD>pL8v4JLti{$8p+dZYtHhU za;0wL_JryeaFN?EIjNXta9gY1Sg5s^0k!o& zjl{?x1~(GFEwo;<3}~G;Icdb&;5KAlS_uBc@j$TmbZ{%c_$LK@i_4h~f=$LvsSO($ zw9uR^NJm>;j3_wfYQHk1{hFpq(mB@P;mCjQF=o9pxnB{*-7~psm9QlA z!1)C9^>2gwY3p1C=&G9_?n9^=nr{+uPoEvAczhAY{A2OO_-lnQEwPKgOth9PA4Vx2 z70PS2GY{HRpOf^jSAeo}cH#hCN{m@rxcOnr_@ls8MlR#4fNT6L{BcHCd@bG(ZXB$P z_fRs29siS@3NIbQjFc?iYv$`?^39j}b*7GybA;#SwILO2k0g_$kMIoOM! zqe!rVY*U3{gaMoFg?Xf18*Wt=+NH+P`Y@|6C!l0cp(>hWzcTXC&ed&Y>CdB5vfD^s zJWKzXP8Xhf^ruxPo_h3WMi7GhY3>Mq@3hQ0zoqmkO$zSTcurvDPOYARb3`x}MZ=7^ zorj=`2+u6kMIvDulE|$)8r_V+O3|Mx252)XM!EnZ#l;A_fsm9EOG=53z19(mIr_KZ z%+GkF40lX%<}IRQNj?~T@i;Sn2s4YuI(N4Ws(#zOdG+H0&v2KN6)kxcY?7_$*$k~J zE1E`bMl1SYhE~~%Mp2u{VXSY&++e8)wrbrS5KgMIaSSH|5zoYBQup&L0_ zNZ#$=Y_|!RLQ+Alg6k@r=GIH_7?Mh0&h}p$ns3wO%I*7{hpIXJhqFX+w?k(p$dc-~ zlW*qKT`D&e;$nC-=szorerUVN%?s|LDe*LD zD#5d@BPOvxyQ30)+XN-7c$M(Q5av@JeZw7A?0QmkILY6oFCM$D>9>;xNx#+J-20fo zFx(mC=}PVen`BS-mov1gJY5>x89m*l46Q0pmsOIUHppc$%4zKj>B=8-#lsr;+p-DI z8*=#*q!8_@}>-2vhGi-nY;(xHO%EeB{Rlpw}spkydjzcNlM$ji?(-009SEO9DI!N!zs1Ppg8 zh9VX5Kf{`d$AM}58G5>bo<6IeK8L5r;?Ik}Ul4!4DE@v){Qa`{`xW|2bD|qjP+cPN z>npcEq6)+00*eeJfq=rf-2nwrB{h~H&E$|9|D$ZkO4#DB%8`#9E%S)baLRm<)mfx9 zD<>Fbfpd;0K%*kOvei+YKz&n?_}Qf_mVsWSGkmXSMNoJ8QaD%re%n;0Ni zuc^c4ul2^vjQ0k|bH=d1LET8_Wy=iBnW;u3?&o-kWj1>C&2?kuL}dpd)`C>cPBdA`0_me8A%a` zJ)4}toW!AZT!KfKd13hUws6Nn;fuFQtg`Uw-C-ypK1nE9`SiXppuBvNzz5-z&PMLY zvw2&w_CDyh(EU#4@+X76vIWP@Tpk}q>rif-kNjhTW3Ek9h##UQYhr=3zD?CsF73Zg zsAdDrBCRTaw$u+v(z;faU}4q2jjaB6kPN~74qp{raCp#3nN!wm2$_)K9LWNTC96G7 zv7HqLl~-D2CkK&MTzFwDfFv%hk>8m~{L}DgceqQT`D7=mW}Nr03quLbClZRqqhM~P zePKX(IV6D(#Gx}2%(5g-o#vKfj`^<*=cdA44RP)z**P~Kh7#hOgp!qWFAD?8%Q*>r zAkJ;}Z097dt=DCkVb&YNt2c)`7vj|$v-9fhVJIP9NhlVtdd!5s83vV?TN3<0+&U}C zu}NatX>LL0oB!G{@6W=04KeS-*_rob7)pqF5=wUFeJ%_tFY_e$fta_^_CJ%DwpJBj zZt35KO)EAA?SK%QzLlL#o5N5-Y?4qcHU&MH3&Vi&GD!l@$)s@cl(kFay~kxT08jAR zC0*4n0(H{AP2MQ{ex>u1-h0y}6D3`b%(n@L?Qt~nxeeu>^ zo}qVu22nTC>9>(S8%gQh8b2cNas6daig}IfrJ`tfjqG*~$PnRam!$qpX#h02>Fc!I z1&R%yINV9MGml_poc4dx9qNhvFu@(QEM{I961>wRW4LRIE02q=C9Q_h7mq7q_h(AK zC^JBhju}+_wtI8ymjs^SE~z!KEZo|w0usayeS({g+Ah=&*Re&KcQ~}<`E5C(#KwB; zY@l>3iEPqg4c?;5VGq;uk9t%M_ee46uTq&rUpyvxC${|(?g7J|XKugb0SM!(PCfcC zAzowR-q;-EH6-&}>n$w*N6;&bY7SwUmvIqSR&ai}-Y|pwXpxt{>3A*ft!`q!y$H9A ziCwc;Pn@d_j}GmvwHhOo>_g-Qm?~pS1Ge7a`edQa2KGUb#F=;VyE$&Lo^Ed|bN@{9Mv+1@~a}CWlt+vwCmMSbMKG7~L_H zaa+Of=tfQwT6P~cI8{-rl6JV3m+oY~!Ps;u{!{AR368aF>Edq6HgSVjSG?snfahTG zmVZDCGT!oeJgIn#CpsK+Nt8!&7b(RclMDfcCy07k;x1zc%Ck_+?omH^Xf6^mO(%EF zc511a$ym-?&j|m&DcpFfbcNrWU&S7|-=Z3F)A(0($8zn<`%b?wX_vDF)9lNu+$46? zxl_XsjO0k{EYgWlktE_lvbS6FJNFDl_>Ue(E6ARQ{pR-%-?#gKEV_H&EyE8)<8&~# zu&_`qjnbcI6?W>~cuyZd$trYw(`niF;3*!hcIXvW_)2xMtU`iiBYo__yA+s8_4y2X z66#Yt4WK>^Hhu5G+u^Rw1azo(vd^uTu0)sTWS@^+FD<&A=2^E=K`%7QEg6Yg)nCI> zj-~(FOf5Hp`L@OGPAwVr>UFx2Wje*@QYtY^N#a_rd%i8PNWo20VlD0}+FEZ6Szn|n zl6y1V0aVSnsiG8y5?YFqP^_h>9?QMWFsQtXQ4)OmWXD#{i?PWG^W&X@Ca!GSYLAMi zEJhjGjQ3L?POyO_4$^tzn7kro5bLs#o()6?vyk3`7Nmvr^LXNebRJ%8B8h`^?l)^~ zim3)RTuTJZVk2E1uyrJ$6eB5rMKk6eSJ-8@lCGf|(n|Uz-8IWfdKgh;3i4MPjl;+; z*ltCX9}UI`1pyaYI5ty4I?NGkA%Js5AfVhjT%DgUmxd^gB~}VV-WeR2qi;B#hvNrx zICM~KmytcR&_W9E_U`Fwb9$jlhvqq=1H*Ak7Zz3w;>Q;Ax*j1{xVJT=Tdv5SX)my3!j_w|!hX&a+U zs-Qcaj3uK7v{~SUvYXmTp*7-r%Tou%82}_Iq0RrhRfs}LHV%ZgVO?{mF)@~CX}OTz z`}bTuR`JBIu-tT|qNXplb%N30t%Ud`T>0<060&Zy3m}u68<>hqbm-*l&JE1_E<8{w33KE8~S0O->uZ$tUk7a08g#dX-X~`v;J$X=-QOSNxm zsRQ_<&$|2y;kN3}Vw%T?hlb0|W}`X0CmLR;6L5l2E)74zGxB#4#!^^8`kTPFtf$Tt z$LQo9%S$gwR30x|9=3S7Q-1G&@x8!Qdc611lkj-O(;yzN?9w2o&UTfLO_#-zPyR%i zT~*Wl-sMT>mVjU{*Y{F#eY@%v%p05`PxO7am?CzPMzWx~znICk8Ju`Bdcbwv$TFqs z?CzoRbnb-*rH{sLGQ~heG3~f6a8d#15LrS25ZHTbi2InPOKv~-)u@^yVa+Qt6i;yx z4fEnh3Eva!B8r5Uh7l~Q$zGzt%{K+&3UD3FOZ;`TAic!j#*^|A69x-AiX!1<7v`3) z$mGKWf0!tl#aFz-@)g;AqTN-+h|-i)XR6bFBbvFSTTAI&1oQ02i|AUJV(*PZT{SA`sNpvRu#?V2FD)&Iq)nlTK1MHosb3@)Kq zVela%RqU17uZ+Ol7zUa*ATAL}pIN+s_yv+W_W5#s7TGy7Yu;u$xBUIVUfEM!_}ucn z0zWq%k>T9(p@eES(B4$&tdaA8v~3+(wZFh-<)4P7$AX;?o>p%6gLs(RDaNXqW8$rZ z?+G?mH(2v-%2p49QJ0Cj5*Q9%PHx>|_FGkNJC3nvqlyW^PwnYekwu+qW_I6%~QRebS&fcYP$!vO_1lj~7{8dfD zTt@Hj=k0C$UaE273&`lTU}~fHzEyB(RqiIi^K!jBG$hVhME5LU>rH{*j@~sDBh%p_ zI1S3Ot(0rE210SV#6gi&y+GGnj{7gw{%vV5k7MU|vsj-kH-~rb6s9m))G%`zwIk&T z(QcttuFYT{czp)D!Kp1{-_jEM}o3 zteXN-_B0pAMKAR}m+#So=^=+0#O5QApsXgok~T8&jkKNEb)iq^84`S`>~E>k@jX;F zCXc{i&pDlK!tHZN_Sde63ruOn@_A|o(t5^jj&$p5o&Y%Co;6ER>pWzVQnAAT15}oTuH9fd#z&zw3Ly9S$YzY1MxIKx6IKn@6DmdIewB8P7?pY@A#XJ! zZ-1dMjr6e? zvEmFiDNdy)VN!^v0Za;mP2Y?t%Ek%Yxg%C@B}_5J;GpvSe6o61 zpj5t9`OC~47l4YkY3kUJOJVM2L%L|s@=K^A-@S~`jL&5J7#ohf8E5Yo9(6W9FjK#CT_xb(fds{#Frq2g~P4Y&J;+=%=(_xTE z$w@Xy3_e{3$r-?JFoR?sEl7jp7@pW5k?1%EiFjr0ZeY@2{ymGRl*J&qYCla+*bQ2b z?xl-m#^n7n&b=%YZB7a;_f^+O-lGb~%%;h*Paz=eBZjaiG_TW}@(_nZa6d+sj&BI= zkhD_~36ha$M3mvv(D{JwtWK2V3l~ko?kWw@fq{iuslKC4ujY$Q#FKF*mG+bJ(Sg{x z3AD$w`oD6~L&c4L4V9APM)bv2ZkQMM_t(Lv9(_w<7mb|zu+nEh4(B~C@OBlhXR32J z@0Uc;a5(Q0jAn}EQ6RE`z-iMT>WP8VfX?`YN4+qniWz?+FeR0V%b4C6S%*33i^q(u z0bC7b{ffOQ`&R;qFup2=Cn+0jl4E#p%h0Nd;n5Jy7{mLK46Ujd9?wcVm4>laF+A20 z$(4G?@V1@F2KR;ZBn)oxG=Raa?Av~0c$YNl6XIUtfW3W=8^+@rsU~;lk!6YG8N7N0 z^PWNB6E0pb*D~*+ljn57Chkf~-jTeHYjKRvyfB088Zg%$o$lbt=m%V-8(DsGc1QZo zO(9y6U$EILtI9Z0K>G@7wGv{#GPJ!@lO?ya@O)H-Zo9g3R;k>Yo@iBPC+6wq=LMmc zm)^LfH&w6L!|cVAf&G#o?9Ph$rJ}EMUQAWC#u9XVfxUBkMWlh)Q~O*HNW240bV1pQ zmj;SM*p-lI3Flhwp1i-D{2KaZy7%%RWV>gb^$5193yS3>#%u9HUP!zLS09V-xUC6s zpd|^VvjGKo_b)CYUO&IM2Uis?)XGcobEw8TybufiOY!aK4e9l3(4~iflkeaKx9vzu zr_bizexut&`>sd0Mvi|arq0zGsrR7%Vvu&h3k!ZuqTq0C6-_`a9`c9b({F@fg_0sm zSUIT^E}jw)H`7;qE8%;B{m+f|jGht`Hz;+vpu2(MU@qv#(SmeA{~k}u1vScnz0lKa zJS|6*X#|nKoXC~M5v|{Xw1mwfF6$HP`+QOnM~(H>?=8w$s_(1EJ)+`*d)oXoU2e9E z)jA#8hBG^KaAAHP$CVLFmoG>Y7MtybdF)%MEVN6=waMc6bb~d5|2ah&HosiGYEMwo zE!Y;1Q4JZH|7T6sT#@;&^$T+qSZTpDk@=q#8~oXhDC|&#-eGU+Z_JnL6QyFiI8|(w z=`P1QHa#IF@Wgzhflb=-u;S?GC}Qyx;XCo_st96;PvXJwDG zD>+!>@Faa+gZS{Ke;$p9v&%;Mh_hb+Oy$!3HhL0fzjzwJ>^Io-9cOtto9YfI4Ls`gB?hf7Q+=ln+v z&crtpz9-n~I44nTFpcYlni z`b`Jz7;I448oynj88nw;6>TL(WsJ7|Xogl*w3TI(M^_MKHobV#Nv_m8+WL>cPnuo- zL{Gx(5>Eq|UCNf}JKD-ORcDX3a*YAZs~c&m=XS6srvqeF-5NdjwU}Ig8o1B7R-qwj# z)QYs!T#HP=1Q>QL@ufHHSsEQ51KL$aO41323|DfVz2M&>!g^{ldWL zn?sa#e9yeibhPreU=M5yH+;16=7jEKI9hpALNyzxXI3XMaT8MDnUSv~(~-b+Tta*# zR_Ygqm8Bpdf|58XI^i5}O}iAf8HN%%6fB`whk}C_jy@U&l=mR81fH()GVp1$Hzg-= zN?aSOQW!F`oOgy_ZwYrW6hVGdc7DAh3?;-b3B}^qO6Vc(lz29sc_IuZFSjJ=Xb2i^zQN8^^7=v zDJYKi{H%i1CxcZ3ntop44Vs=%_i@EJA*;os54(@wCgeiyW8CVNgYXugi^-Z|FY|yU z6mtvMsFi$H&zNZm=GeAe9a9eEd8m}^K++f6b_T?A$$?Bl)kvRTD}7>;(zi7}TVUW? z<~|qH{+=^L(J)ze@>pWh>fd~up&F5i9=fp;)g}P*!u0W0k1}E06`}VE+(E>yy;StY zBlLwt=yb#lDt_JGLL#Yj}y zK(k=QZ>$v9}A7B@K1@;)@t4VC{kF zDsf6@bGzEEm2m~sOc^%@PM7VCLT60+)SKiHbGrY5fL$n}KufBQoCcfZZK9hqw5kG^WFlk?Tz*p&4HI1jF4-zdjzRi*Qf(7u z^EA0q@4)3L=W^h31wDztrFdG_z$Fru(AtfNAL=}C(R>qo6`JkEol6~Wo2W`ij%`e9 z?rbj=$=>(~#CR_ZH8}=5i%;v~sSJY3Uf@0vO7I(4l2+al7ZHe5BD!C%73Wh|pPtUfPq{NY@*b047Us#u=ug8(F5)flTb~Qw4hmrmE7VPVNzTY*{cxeRftjdeHnG znp{bzfwc5Vzq2~9f^N>5h9p5k%t@wj@szbpV^qXHOLNW%Udt5uucRH3ypU<| z=~~Eq4e%StgNlC=9Fcz0FW^b}P0EbmRZNlpN?>R$VKQl8@;;_!W(?Gux|gmj_vv=` zl+QF}!=mtOy?j(|kVU{2aBwBz3>{{q?Y4A3p-i5O%ud3af*Gn^spHq6kQ5!w-yzW(WoP&$0E!CFW89Ew_?h126mZ zn3yBV69fd&T32T26c{CjJ6gp4dwd)fiQNh^|1}vY@&$^hylhv{d3dVD>Dj(V?5Bm; zdbB^4f3$CK#!0$Dr$rgHX2JRh!74drqy?+iNSR$q2vvO@n95MqH|R-(s>IVEp(>3{ z-=V5)&4qd(P_;#x=6taY3fo~SP|~beNLwPbY#`Fa61-iz4j)a;BC%2ck&$HaY&7Ya z=ZAc$j3J)Qx{=PYr*(~m4x@?~84*$1fcH9abS8_?kKTr2=Uc(`JX7uQUAn7@;hB&< zei^F5{BrE^HIi$rzWJx&&$VHAA!}U1OCOD1lweq(=f)yzONxr8SmTEO@g;=s3AV=9 zGRu=~af3~lEj|S72D8Oqf)=DLK7%J^i;FSEmbmm4XbRAIXqhM&+#88LX{#9aR>Bt^ zSg4Ej3MaD8>NTH~WGe^))XhVP{D|R}O_*JOa(dk4ws{{~{KBRnXzE+*Cwvj%B zzGHf=dznOp2zZ%9DlhJ=7QGbQzoxQnnWsd^95GL9`a3g0Ml4qNOm_D>t=H1Tv(;)L zT~-4>6Xc~mnOKa|*sV8GYQ)3GDSbL)PwyuP3AuoFSmA?N_k`{-{k>fMR=2eO4pj>6 zF}1wYtEHNt9aJxnYyWVx5dw`)O&B#Gq-}ypP_~E5qc6nhIksl$53W{zlS<6 zmUq7dT#U0^7lZG!OWPOq(6ZRQl!Y+TA&>1riG@QTy<);zg;!JznSLM)F+?T_(Ve7hMUqISaPbtM z%?NOOi10nZKHHEP#VP4Z3_@LQ+x0+jFt_b-v>@HKcjHO9Z9G%3=O%WlshP$&Z%iGi z(;JCUS)8}yx8|Xw?D#ck#PmI?H>^+HdC-e>5p9Gj;6?TgBP3iP^7_ zzb&)lkNbs5){F&HhvGZ2h{Mkno2|+m&X+WfMk*A4P~3Mo63tZ0wNgtaE>p}MzPsGU zN{d{x!m}(|kpEZ_dPJpV?NMZ&hS#c?@pOWe>_X@N29(RX2&4E!i!g>}>9Yh`ZYnIx z5{|H}Y^0B{?3aM4G?~6kPr_spPXm}t2AjUavKJ|@$lp;e zc65)68IM9U1#H+WmP#!>w$q=%q&hY-PZD_~0iZbl~IzOSB4b-y|&KAX8 zV``%uT8-W`SQX#n8>p2o7XAjJZafXE_1LXx_C?WezLdm*k==;Ke z^6nXuz|&{l3`|614wlNcV*>#E>jVh&jm=E}r5q8p9wyi|{?c{-Rh# zleT~rJS9u@5<1YgH8%Kkxr^U|**TcIc=|SW7tg~J@3@obu(v37+=*A#N*|L32!01x zWO5cSNmz=L7fvo5sUn$nUB>YdkI7KdNL2*P)5Bc0xuD#;WjFXhvcY@tC{8ck!rJ1r(I&vkz%u2oT`Rspvxk};36?mF2zMw6$?RfM%w{Ti=&(C_BuO@b++ z_{f<4H1ytxk>A<$$%CT=qtw3(UqBwaVdsfmfO}yslBxx`15_!r0GB_>%dj$%IT;E6 z#G2ex6^r)mM&g>Bwyjx5blckVxq7Hp$iB63-?Vi;!UD&AaYkW82aKdV&5Umb;qZ3hIKxi-mLpEfpfTfIaqh4 zuz-no_g1iv16Q1Zb=a2{S^HbCdnJ;^XkTz5Z+e*3f9R1jjK1Q|AEa`JzIfc(nH_yY zeZQUF)c?KXOZ~md3MKmQEtPQKxlu17m2uZ*0< z7d;AQV#sGx8A4w?h7_{)$5O$5Gp+{TGCAq=eNrb`+2p*p8eDOqi&watYRi(31?C55 zjo$y>TWbC(uhaya^&@F15cG zPbzkzCjgF~Y?7;EYC6+9rI|qR9S;(%vMjbAIfO(}bVN~Phm&bvMv;oJz0j;v9@c}n zS*(Wr&*g{;-YnC?(ET4pWLFy*62SvDdqflJ9F(}ejN%RlL}Cpb*syI?9h6xv@MdKE zk)jl9x^yY!NYC<5mSFJv4TDeU?%Yr0ArEJO{U}um1qZBc54(A0X3vy<)BQ7IlRilh zT|U?`Ss58Oi5iQ)tY>ow?YaPVqw*5C#lHvZMrVZjY52~W!bw0Qeuxwcf16% z?A?T_FyXRf**g%163VhCp`?!;wwzYV96Z-+NXsoA-FfzgJZXRjZoe{<-K_3Jl3ktA zTQQV~XQ(}42pT%ZSL5YCwpYiOaA}73bXBCCD-`Uqis z49hiA^_B|D1UB>SAYH@l6lNgXYL7jgxuz2dfz#LPxE{--d12(^LyE;L-L61poM8S? zH?mBZJeZy)#6!+cC7aU3cAB=%Ixa0fdZ7^K8zya2*iiKEG%=E<>|iM56Q~**Ypmg3 zEH&KUh~jQkXZ0?9rMh>te8n!713VdY|1*qkD5mmn627zTBzU9y%8P?0Mrgx{gq1#f zWgyKu9xaOP&L+UrgZCGNaSqYvTvW|{@P20)UWi5#UQQZ?i>HK^%z%&on&jsMhnBV@n35uGrG=1I2;toA@p;McOp?;z`*wW;*5Ik}!i9PiuD$(+Dc{eQLNtE^e|8 zt5?>L18$$gzve)>E<=2hSm6yCpU?nLI}d$0!1Ewg3I%xb@BVl$t0j&D>EG&_irAH) z5nAtNacWKA>XhW*5I4hmBT3u+NG=+v;Lz()DLFVqUu-87I<`QTIitcCZzT1|QfhuP zuFZ~hR;TyYI;->EYVhqIUapzs4F$H_eJuQSR{wkYRLqgA*9yXgfvdd{uNFna+gb|3 zSRkpnh0e%Fnv0%#^o^0l0Q%wy z#>KsmHpuw3dsF%Y0+ZuL>1VR-(I>H8+XVzNFHA50!=q6cdqwhpNhLXb>7V3&?cOB+ zQeKh=o8(OduguV@+C)H8bH?CrJwvN1_{-XeJ*+U+%9Um_A-PiT;P2HDJJHwBlW?NN z(*RDi@>cuZL{Q+_WTJ(8m+G?tKl(y90_;^Bz?~kk-D$?7)mUg^K`s)LVGo~ra~Cc$ z$4A$DGb--}1MFesj>?Q4_8q#B&a0MX!$DWS6CCYxQz)tYEyvAXBg=|Uu9Izl!9>SD z4MAr$Epj{9)2N!m!JZJs2XwGs9!59hKt3elXLqoFC=4s)JW5#UlauFQCy~bJB;m|t z%xw4eFwP7V3&?cO9WxwH|sq)%XTLBN&u_Qk6T1Gumk zlhMO)u|zQ6K)8;)*7;(yIG23g+FA`(Wu)ZaX5#)ZXljoPR}M0Isehy!S*C6A+%IJ> z-@C%P$n=bEVkJ4I>$q5gYwCWZD4Z^ADEVnkgxv1wCs8$rd-^d^+;vakgGoV9eap7U z`Cnn2Lq6DlNF*E|b&Z7rx$x?zq0#E$khBHY$R)h=8OQTeC5^(xQ+zNZ&GAQxJ}1}* z6Z_{`fRooa4MttQ*ZY9sV7}Kg!4v6wU47wLE*+ znGYm|Ao8^e?GwGkd3PT2u!psuDji=B>sc%!>|+T@(1H^!HWqd?Ddj@3IbES`e$dK^ z-j$iLm49Vk7@;_vtJiFGqEfPlHS0A8(cMKJR(Btsdh{*by)bzB4W&|K=vQm!)h zgqpppq9_{nuAV1n^7KV48mzPBdbwF_W6x!QHeQM<<(x@I1)F3~;UyVb zRh|M3+KisU^E0%nJO!Sol8t^}5|yXG8YH<=Z%^T4z)yM#AEzhbDTt?mJ%upQCHj?b z*ivQHcv9+Td9TE3kp$GeRYG2b{m&Zv&uHw$Q$N^OI+BQ;^Kq*La!^d*LJ4S996&2g zOf61`q|1*ib{L#J()^mPAyBv!D3}Z4-XmsY2{md=#UPeQ=pipT5L+V3N6O8`=tvbe5*Bet zPi#wR;(!%ji7*=NYY)xBsA-Wtii*?IIHgNLKvA(R^b*xlH^jFnjnGq%E=84c5vC5d z^WsAK=Hif^F!6?pt7C!DRHL*wf_vo~hpT0LqRUw38cmh10yO$A?t$Uz+U?}Vxe>0DtJaS+YQ*JzV|OVd1LVJPKv33Zm$N-0xZ9U-A&NqZN5^XM z+iKuKuYus$;O$BTRTwbmr+3yc%E!@~=!P-uF(25&pBc3)jZs@}Zp_UgRn~kF2WD}8 z)+BR2-Tz|s^Vxa&N!GiNmfbEAI;Zn}FIaKPDchsl<#3D&(>PAK8wYmF^%fGB94YS{ zYBvtUV;L703aU{%I$LfRhW9SufANKNh+1m9cp z4RY9#&)T|ZP-}7L3J{}*Wf&uL(cqYBqR^Vg98OvGrpp+LP=E7PmC2f9yV#Z~t~o1+ zbGY)h`>!vRThkM*>gQq`mp1M8%82isx@Dvi&1r%2;VWG(H8A^ z2$O`iQjf#9(f=h3CA3-~p;&2nR^5q2iQF6c z!*u6cVL*9P??~XiC%YHRL6sy_8*OEi#GJLN0C!3MHoZFM(vXW292RGwDnh(Oa83vS>NfLNYCWVWqtnV0QX3yWlU8k}t7g3NRg8ug$8*!f}4xqyWSn8ZV z0R^=Ht9eW-p)sklmO85ubwMyC{u#(~^2(0ErE6v90aWT^Wv8+xz7AaxFy*q&Bp4-r zzGf-Dfj?28m=55x27{8HP@}Hr0?u`N>oWIIQ-)388^~x0g*=MWl~AaJ$Hzczm@!oj z3SojbdQ#XgWKk)^ov6j%-YwI}B3z+kNIFQQ13=Pk3`UEFR6ac699kixs7I{gI@n!q zNMxvRq*{#jz&mg5nVfFa+X!Awj_?aIrSS{VeswADT)9*&PVPiA4=%WY6caG{iIcUL zR)C@H$(42g@Mez~LZY2WP5d&dt+re!nptf>>b30#X`CB~iR^By7~_`XHV>nnkga6R zIL-~kuR}fi5>Npo{RU!r3885sPEOgY5G_}W zab|TqKu*3RTMowrdVa{zbFCAQJ*CJE03f-?#ND&(AA=2d@XjO zd~UF2Dy#oKWu4L8$q-7#hC&CXXr*wB5HQu5WCSPn4FHBNJGMR$Mx<04jZ1#jW<(!W}tjiJZ!B!XG||x(VK~MY3F;aMcz9&JL}}+q2@w)ax$vQ zD_*Mg>Bbx_0V;69@WyN>mIP@@w~nPiTX-iYjUl^^TeVcjw8Dt35m$BKt`-Sji~-2- zD*9#h7wBj9qc+@!)I zG@yx!YWE4t5;Ul6BrS{C8maVLyIk(!_*sCIJ5b(APhtm(cDKFduIR?Gmuf#hP**JbI4er~ zf-6c)zX;WsyZyeBYMx-+86vo}^d3}2a3@Q;&X0tlgqD^hl=P9xI#ew! zJ)t3WPAa+SPTsktYZUQJnDE6g?C*64lgyEfCoBw=;!jh1!dx&kj(;652U5+Qz(9~1 z`>Oz9Y3zhPE8QLcCrXktLh(h$7RvfJ2=O#!ZKuGx@euaoFtM@MS58?YxT>eEu2WiQ zH?Z_uoyG;+i=)y01?=^iLY1S%DsEen3L46F;C2iX|3~4TJnB4$PIzJOrW#TaeO-6l zGD)8ILd58z=}NJQZi&R*vU}J^LRwtpi?7whjZ)a2)I3_n9;6xcw}ph+(}!ty*$WTd zw)GaTLl3}?!O;@p*P8%`x1L>CbW#NFxNXn&YUo$5|oP*R)UjVmxb0My!{5JDW5Kku@wmGB(0L&BQaU@gG2C8Y09~)Sj<0 zuf)s2RHiT7QcoU5yOy5h-m!8#hR>`V881wi&n6Vpl%u6Kt|#3n>9+&RM5PiY4g8D$ zMFqM^RPNK;8PN`J-2aFTf7mmH^%+`j*Sg{c(+EzUg5XU>?-0}R72{;hjpJ_ zBi2)=?4U7;pdw@=eW{2a2T-XZ-b_zIMTn7 zis?$?<;&%cY0P?Q2_2f!HBL%3@r07sWML1giFc!FMm6z)FqDv*kWezKiFay9os&RD zx*aaP#F)O8`f=Tb0W^i7L;Nvn&({?1z{|ljMVEj}Rq-V>Y^e&}U)B|0#&^~gj2U#r zuMmjQzTFnQ;WDADBWqwSIKCCuPUUH2ZuMM3lHgWsv$MOzv&)j(gaKZ zXadgH64C?`N@h(ktRXF@CSVy!)C5Kx5ZS>@DSw;!XTR>k0GhziA-;p! z^EJUXygY82K=wdtf+8ArHG%xfnqUgwSrag3&;%C~k{L9?6~f?`G{a$eoIj*Y;6^)O zix_zjrRub}sJXeQU4=es8lF@Yddb5iNhe%HHKb0M(S6IL6POgx39^yCbi$(mD!qeO z(38*!;%N|_pz-NjCp?3Lpgokr*6t7z*G$(6k1m&gU{LF&7Eb4=f~j&+>V>x|nN1e> zpkDYXRL!Ut-Wi4x(hCwwX1(xc4XJZ7NJ+P1Ko$?VI>1XY=7pJt{!sT~0M%ef5x<|> z^Hsx-;^knfpEvNy97!x@T zqtVSs*MlV%T%I-(%@ykl;gy#=0!@mDQ?5o0CqJdSlsvwY6v`W^hEyn@)bz-tP?&sB zD6)~h6v}@Bs8lFlqbH$I#M2-OMdQ=ILYY~p)h3W!D8EACnkS(`F{ou$D5lCusZh=; z$T6HO@Ii%gI;v(=D8peWA%!BLWL78}HKgTJD2C-?4v(F+iFM{H1Ol#xd10oZYjiIL zP$-5J@zvCxuTa+D<#AFdx=&J}yZ|lR3Ppcrg>nZ9utH(npitHmni&+z)inE4qauf! zx{F9D6qW46%8wutnn0asm!se6hCc@tqRFEsNlmPy8d6Q%t$UeCO)ycQCS)Uhsfids zrJ6WQPeM(Ir$N+&#;0#Jaj80e)I&=otV*bg=}KbRBF-AKUOGYtZFP;4Qbjzb1f0f$v z^}|DWIhcOv5^$*={x=%7)PwFHYlrvaJ8K8V4BFvkgk%Qo@cg}zpJ2xdJW-;ndb?Py z)23`_1x}Kc6t&VC<9Ie{xcFh!q2z&;q(vT~8d8gVP*u*j`Iw0ZEg~D~ON)FOK&2M> zdwLRDL_7_mMKnJBYY}7yid)#%7T*7qphZ;0lTeFj%ra{cUE`$GBHvc>nk?)=E%FUi z&8S5-?v!&x3Y3r*kx(*gk+13gET0z998c0B`lHe!{M*bwmjsEGapSO|LmW|iz83jc z(CIj75$=K1BF_diTZ`~l)*@HqJ8Kcf3|izr6yG3FH?1)Vmt>|$Yai6J`Rom!sNth8 zO_j<~Z6%55h#n<$q>O4(VHC)#QxVW4_`p%&|QKlj_y1o8~#Q* zd~DN422q*Lh5kE{R%)j`3fGL#C!8 zIhd|W5Ok@n-ixL!ZDsY5_0{jA1nVot4iorG3DFE*&q$h{I*OI|IphJ38ptv%(&`*k zYAUDx`LMzyd2INjLg}ABqFzmbtC#xvClN2haH>fCW@zam&+2E9YDo3-epNZ6`e7PF z{m4f8Qa_&uP^o^tKu<#bh^Il+kH)8O^)sx}ZzL%non7JFZq*}`TU49`nh#iMo%KjYE0g*y#gzA|vkouhr3WIH1!=TvK*U(GDhm-`8ALx0 z5m7;L1>#{X5D!~KdP5jWNFZ|b zT_nz=P0@FY8ynQcFo9z;$FD&%0qy`jY#+-tYi$WsKGsQOErJ=BD)hmO6M7r?^?As| zchxjGjb1Lp%)-&ro55ese``mjR2UPzL8l!Wrg-JQpgX zR$4S;`LY-=V!a~hIu!s{I4Q&D?|`7#BikJ^!8pm=#AwKrJL-url#rPxp`?#^wzO34 zsJCiJCxL`?$IdxX98cUzHq2D_ryBnOqUMGO@t;t8e$@OecsY=T*71c~T5F#|yOy=a zo#lA>r}3HN<%}2R>YpYQGsMfUBaNetv)d0Hx?AO%6LkifYJE_dn|X2CK1BVDiAMm5uZj>i!mhO4aafdJ?KZ zJPn{43_g8_x}Pyu#SozN`0z%cgi~x>Gku+P+0G{!)OslieZa?5IVsh|wvoQo#CfQi zF`T|D3?-x{B$Ui*;w%km`3@ZzmM4VL*O{+!H;{Q@rlA{kF9uK+h7|D))Sj;_PQ%N= zlts6YOLcJ&EnDis^pF+CArxSR!MH(TY#}r=D2!W3VeH?x|5mx7P}8&Izl>Nxu@6c4-#20vbJVLVDDGhvaWE~aFI&ah09UgjrMD+xoNMt zuntjcx`c!9?AGaS87cA+OdmulrVyV_I7nr7pF$@T-9j~1X3RP$GucRA%IsADDwWx* z=}9Ov@id4s)A;nQ%(lxLJA0_I1YbwiOIKvemeY?B>!rrDImi`GN+tF-C96CV-Juio zb>51q8I{<(!%#v>OhQQ?f1a=NQyS9p`8v$-1QoW1zexqgKh4DRA&vh4>dO!z{vfsI ztFJfViQ%;v+82Jpt^p7P|TpZ_U^R~KyYLc^n@=XuLieI z%TbU~yFVPfXFYNpS~47aN}-=Tf|C56H&YF%Dn70I?hZV!8mkH>6;y?6q%T$RbpVyB z;v4iNRE2mNL{(^f`c@SMTy9;NkOQQLzPPY^qmNZNU1|Kla_us8u?R9;P<@<*su|VCWnm~G^&z2TRv)KpNS%{JR=VS58+@_A%7gRH%uUzn?hK$! z3{B!a)Sgsp&YrealoCnqQOUF=XMYf{IJ5&}AF5^)oBP91LSiGKB<#SDJv9`r24UFK zc&-gM5=_54EhP4R2))H%Q#&3)9|toR5@$4NGdzaIjm_|;6{lbyI{tGdnk|Uep)gwz zEQ_!pHYp}RE`q0FM3ycZJ+`HQYx0`KX(YstwBP%}19wEt#zNbq0`8-xk&z!&=p|2* zwv4bdxshr}3*m=#-!fSUObS>CvXQeu+_5>=1it&5!axf*)CE!v) zd>aiL1<}#{W1a9Fd}p1&m_aAJmypchRf?Hi(NNt3jHHib&yf2#H)6B`TjlIU_EFRD zWX-5VFL{_G>4e{-4oRJ`QdQ0vU}RE2C&)(n(g_y=sMHA;(UZ^#;%N|_pz-NjCk(gR z#dfcyvV?;nqFTB>cx1UeMTJ){ZJ;+Ks`4kLF1S7@QMFPbwtG7rgjoz@u3!w_!e)itQo} zC@f637Z9--JxD_}hnx6d5apnoIEShk<>%#LC?WZgP!in4)v~LG`acu|V$b)v{KSiT z(7Im_Qg*D5fnkY-sU44^_k$S+-h3xbgLk4?%QR3T&xXOf@Rbb%7FHMrS13*-I*az^ z=TTfeCYC`#V`vy$C5DZuP28VWDpf`P=Nfk2$X%(pjZ7|zV&LViW@O|Eg;{o+;Bu-V zZGzv>-Lkgib`DjL(_vaBB`rocI=hI)&e}Y(&P6ljB8|!sI?=k=Scr}mk?$IvtQ6}d zamsec>YcQLiqTxPR4Uhw;+9OhEvG2GWZXD6-Dnm;9IB6n<01IdNPVilQiHW}QxoXq zLduZ;1O1Yp?r}>b|5Yz+6=%zPu#T=4*hhsZjkdADXM#p9MIFW?`YGNOc1}*p=@D|Y zR#mpvx&P9`&|Nmi+3B2M00o}(gA3(WyC-HA8lUjc2nQzAay#MPV@t6}zoA5WtwU2Y zmG~MO1DqE}cwocKm5uae=6(%$N;CJr=t-El;%N{wSL4&SnR`haajG7xBIk6kicqa| zBlqFuGIAway=>f#>~YEBC#8vd_E^Y|3!1oFP&K28vONqXWTHqY=>y0McWly-I?F8` z-4^aDEeM#o4zyKC&6Z zIAL-eBJ?uEH%4j0ml{YSNx8VhVxe9|Lilp}{YH7K89p3Rh-J58)>92>#oVKN6;>+h zGIAyYrhM5*UsL{J0F_gIjh@7mFP;XO@-;qvPx(>ryyItg&-kd6KH)#KTob;)s@HtK zf#-Ws`lOuhU#H|VS-6AK{cBJ)<8=QMVJM;LUP8${-M>;p>MXNtbkFuHSqw1Qi)S;( zyi=n+z+7+o9{(D(=g;*I+-$eH{@8tY6mId@Vw($`G>_W&wq z@_(QwF_Vj@L1uEKs@!;gRcz( znQd~67(^)3hj99qgm_a&>{pi|p?~24ac+ElWou;v$(}j`d?_|e5AA%#(j!ZS%4(T| zq)^$+FFHsU*_vWs^Tifz0j$;$k|>M7$B}CJD4kVDfC6cfk@&I{6`QjQbGYYgbZGyA z2=Y`#2n65S%|bxj(<<|g^3;I5TR3{^(IwHI*f>8#-u(jNEwHRcI3qL6 zEdWv%vFSnhU52&c-p0%Ga1V2WVA(#4iw^g;+}xO(Yt+Flgo~T?)*hY0=XC#z6@b{< z7ZUqjBz~7g=)RxEmJ^boQF1R3j~Sk?A+vTwzlJ00zwP4HnD{y*DpcBYHL7rZ<%%0_ zFV|{~>&Nh zRwH?&+vvulso`evsJxq0Ly6pK4eVuU??%+UT%42DXR5VwVVL&4jI|qM^lNm!G&8)@ zKwZEfQ9yRn$un6`wlN{A*DzMfW94J>jb?jvx^)EAw^JH4Kq;4oxB|)l1j#>ez4G!a zi9; z0os~MSNtmIPiTb>G?`V)kx(O zN)32Ew?Q$~k!TmT3Sh%PvEAw;?Vmum@3eo?n&1?3@|T&i?+VVAL7(LXsG8Adc_0iW ziM5e}-_<&(!s1ZL%?Flc&O+jd^FeM`9g+b=g9?0B7$Q(#R=9UmLP9nn1 z-eBS7U^Jj9xDsW=dpDn;eoYP`6*1WVco6$wma!j0)zC&7rngF4^~0jLlNvFeq~0T5 z5l>saFmEeKZ_$SpyR07kuV4>sv$(SXTDVrE+&PW#+BCf+f)`2Jn|TvX~Ka#2|mUx&5@Oc|~CCK?hyU$Ye7 zz@Nz3r-WiW-9YGWLAlfrg}tUezPB!tH*1e=gdH_<(~8rTDCDInL$EVoD@N!}xkBR2 zK61LnLY;;;b8=`LQ2bk(;+8M`QRT(9Y1Lo3!pgGGKnH-7K zFY;l`FX6}FCszE`cjY}y(hh)9d8S$~50RTJFEFKz6x>c3NxYk_N#Pamp;Rw>CUILT zdxo9V(nXGxi*);SF)HB&!JF5f`u@i_C zM|HZ|M)p?3fM&3dqrUW5{HF6U%EeIsaeAUDr}AReE0X(bFxXF{K3(_%+Uh_=69?x{ z9f|VMQV3B3Eyt;GMN2AUwR$6c5&@`08!0m_uMSBnYB5}v^D-t5g=2{e7Rq3K#R zy;*Jl;Blhr5A;dZA3ZKq)g24b_59RH-J(YZTB|sa+~VZyU5X#KXw4S~8a4f^$BEYO z=#$n@93NV9$3nDTEfixmx}MRkKNH0G&kboe8ckc+X~FnE+38CfJ5^zQq)+;O!lSPM zl3QU7ncj)Ti!`-$Hi>h$kzvHm7v*$UfjCL)UY2$=hFM?fT-U#-*sRhO5-q_>SQpkC zgW@-X9J3W0P~>E;|4o%b$z0=>W#Opho%mSSJIms{LxjwC?5XXl1$s$83_?NC zF!ZC4B3L#XMbWTK-Acw1Wf4xL{q2YL-;pj&R6RwQgc+7%Y2K5Inw%b3^anKT5~lrL zb0~9ZmJV5*@SAYO=z>Hsq8=J4IyXUz1Pu(kXFWW_Y*a$zW7Z`^eu3UX^n5|dF!UTk z^!;+FO-WJFO;8>c=zJftVOCr1oumz>Xhj(FZms%KtQlk0qH7SN0^HkrdA8B6V*kI$ zCWGjHvScaiREbuX3Es&?WF=d#6%X?UDFDv zJu6@#v`gDeEw*vaNT|+&t4Oq^t9Yb;n{Gbgku@xgic9ZKHeQRSna)hBzo56&)PW}-BO+@F4UmvF|zQQ z4w%#%ZH%yXB4;*OK-lPU-Wh^?$|Gqe4n3L5A^PHR=z>5Ot*P0s=}ygSCnwQwGYzlA zFRSubJ+R?ks43TnNK>v8fAI@+p#?Ah@SX`NOs^j|r&?(IK6w=D6W@n{zAkz&DADhud~$AVM$+TmEgfIA%^#j4$RGcRnk zUt8!u?7<78ujVWt2h3T8%w#q~<2Tb=XeI>R!Z_v_oOf`32xoBeOR+`~-Hc<7v*i}H z6k-!DRybfXkm$|Rql z{et6nHtJ>G_T;3eStX&X#U1g(2+6;CLg*4SrM(v2+Ry-p6PAi?=hz34@1qh&vJ*fOU>X8ij}AuT50rle|$#_)#JYh=8|9! z?08;y56ndg-N~>A=7NN3HqhQw=xpg46^gyi<(?buQatCoFAZC73=$>C*6T!voLxzs z72^yLPX@~VFcjK4)OAU!+BzhmWW99o{xG1tmkvtc>8c=+XW`;0dwG-ZPiL(pjvE2=|NKqwn z$b@tV9}UuyXjKQb0F{zmV*29Q(^~`B8d3Bsrq4}M6t~8|Cy;QpyC<@- za&CS{6b&!8jM&PEhw7btj{9-d;`2 zjl-$V)pDGvwy?@@-rgz=7p)LGncVi>e|@Rknw~)XVgl#Yjy9U5J<;{sX~}<2w1dgg z@2Qn_+yL97=7kxg`ym|m_;v?h@a)PyRLyvH<^C{~(AgCUC4I=S{kc+Zv%ghCT5j3s zK5u_2NwRd*>CrG@UL&2j2Q$ueG{p2gZcux|d^U88Z^X-ijMdHtZG-}QX|=uzjoMZ# z^@~s2zZ&1zOl6EN9-jrY`>-hqf;m?=aqe6X#{|pu}7g{ zn}1YGnalBBssR>*ppU7_q4)x-@%eeCKb!~INY}x8rCiK(;q0G||CyA^y8%?Hm*1c# zpe9f=n==eKzcd$NySmFo2qW)=nNfMyg?5UZmdvi$m7N$ zIED3&37X!=N%%&TNQ>3q@vAPsA~C?Xj$2~EH7|?+eMHGXvhZdM^!>4Jr1RRRJCBWb z?$6>yLa^_dIcO@VR&YXTopoGad~_p#?l+8V^TLq(DNU)Q2|E}v`V^{$Mk?zwbsFwT zQQSe_oO>JKG~E9LdtlFY;Yi@u6S|Wj68N=*YBtc`ROoDS#*$*Q69rtyCG^PAFAOWU zUhPi3?zA6dM)?Z(LV`1T^(iM(`IY; z2~BcIoN{)fsGd3R48QIQcksV-0S_ZJBDY-~NaQm}U^$XFGQsP{xfgd{u%R1n7#mO<`uH+@$?`$V(+- zND#Kn<&8l8LQo*>8Cn^lCz+)Ha=uk{;Y7!7e>)GUIClG6RO$G}Znv{BL!re(@Q5fi z8Ki=R4$p~EMPt{f3D>+Z^6*!=I;ooZ7qx8j- z5s}d_y%U!B_?2Dp!M0s=*zAS#tf4zR$YGu+;qf6tc--SQeu3T+F(zmehVDp2ut{Eq z_+SP(Q_B#fB{D8UygNgyY8iqRBgY8BSgU0SHcpZ&^+n(aU$_FK%7X0 zVfsyCMW^IcI)q+PBIg=hWz3n{sd1vt>y|rwVk6mWm7=NbR8y;f<%p3;B+nb)v124c zUIT>HT4Ea-WfW;w#&?Y2eW@{rOn&P1T=CchG@tr~43N0}V*IvZtwqTi+ifJStSySb zS7MyYK3%FNJo}ZI;(sYPO=OI9{eo`fBx9CXHgLAKJ#a#Kp-dBJcic)q6z|>8n0}2p zRy-S?{JthFxHt4@y7F&fAbFz+5^%bf@M1qnjM-?<8%fMrs|s+3^l#Ivp=(`x z#MR5e0Nol?%^09NFAOEbAPL1{&??%j%RQ1mOm{8|1Io)J349fuDi9x|FJ~xK@ z5{kuLmz_2H!%#x3kx(qwtc2EL&WLBjnES(E@-jw(9*8j;EbW@an>F$~_lJL)F15p5 z3h`$?JAYmoh7#hBgkte0ICS0+29%dW68JzI+Gv|RNi15c3NVlKZ^NX=!@UYI>FwE> z^xI)5Atp&ES()^~Frd6llE4RJl5L45F=>q~z&zrghDDzW_bJ4pC$qEYOJOJ>7D*@; zi&hJ>n|q{wnGSs;3@R^^B=~`tw8?Q0lDM>vOK`8u3)8VPpVPOouo+b|8Vi?%p@cXk zp;(-f3wX-m@mKT4!hrJfNdnKwr*QF<^&#V4#lJ;X>4{$-GOI1di%nS}GRSqU5dAce z9c+c@MPQj+A$kd(>=h#0o8>j4vy*&pv%8;ZN6Q+@xQB?|)Ri#EUM0Hmpa`7G!;t>r z+URH%8@zElWlbk&YGCUz7LaJuO!Wxoc7Ufea64vH&IHBS3(SjrPd}@K1|6SPl~43~ z&P($k$?G{ssnWJsp-b~ey^A^dlRljb|C?jSijQ^N0+1Le4mjm+%GDzk82(XIN)8Ou z7cVe;IxXHf7#gPg#na~zUbXpQ0owKNJmKI~o7an?;Z>Wh!qxZaDBdL!vPYcY54_%o z(Nx6zU4bTr9dMD!8|`%#`r;9Di$zR@rlF=^zBe_0Tfh#ZsiN3fsJTyh>O{|5DHON2Y}xIRe@2$nlKdlV*|IH5@(;3& zEZL3?c6wUfJ=6Wv)7|usEMc4&gAIZPCuR&WBq0!p1Du3I!Y&XXunvotL-rgJlFgFr zE(shkhOi-j90P}CzkBQd^?TK?yJw`yW__%h*Y#di-MV$_*1flG-MXjP+M3$2GxbW` zihIS5D|V%J?AXo!r*6ITo{{M74z2ggg;4)C7tdcSj7Ql1IVW6XfXbkeH9c>tVF_>4xBM8LfT@ zdZ4YV$pS%yMO)YW+%$ZJZ*0N2e{5-ws%^88?J;!ZHCK%6c8A;#zoeiGP$-%o(wh(k zjVA4YHLl@mTw=nO89HkSW*&Z7g|7+0;O~+o3e%#8D9lGmiQ+uQlplf~h+?y_ZV*}Q z=UoQj^&&!v!2cU8vcxgNBDuLThDd&*ej0Z2P*0eX#P9%jF^Zqln-DQv*bQt0Ot^G+ z?tb6&BKvx2ryy+KnLSaOY)z)fi2+Xb;wG;KLb&1j0dZfuT=C_K5Q%?n=uiw@8A42_ zpA4bQPdRb~9*-RXdJ`IfoxOL(fETW>`_qXQ-JVjUA?=9}6Ka(KviGb{yzUXdFU5CgCq!j@Q-4Hhb6!n>TW-(d_yaZGySr<3p(J<`cp*SQV&he6VbY15&ToxP*k zAkNg8ly1J&E8TdRlkz}$O9H7)dZ3VAo6rNLnV?qbfs(_gV#qDznwusU+)Ivg=7z!{ z@!Jx2cJ(r(wjp7OV@N3Ks|ni=!K0mMJUtq4*>7xx1{39p5dBXE%J|5W4BZN#NdkTOMS!$;f+ zvLT8yUd_AV%*FY!*8o!C7xW-Kv0o5B4d54K5mmpwK^Ngp({4^d>xg8;^<&0**NBe* z)qdj{_XZ;9y14;uvO6<6-m2tqVhwjvHt^^2W4Os=Lf^aR1fZG+lqr)uKO4q(+&f(p zdg|15C9?&Qoh~|SBhe*yF&x*Lv*}BI;riB?e6S1g!{G7l8UJ@$Uqeq-GVZp9BixT=cqw!6)m{l-6~=}s`iMM*>GA%h!mQz zfLG-RcikM~2>GoVBL5?%Pkq}F(jN~TM~WM``Kn>qafKEMHk9mRLubp;3tOUh*;L4q z&(c{%jx@TkL>7jvtrv-KW4~?EMO#*zMk0LQP1#y0U9Yy9xYKz%ZZ-#UMm7&;8z(C{ zI_*K1og-_Mui30a6xh6*#loBDIgQ1Tf0@q(UPt9uBwfOek}C1lxfHixbmtE19lbwU zDwOlM!kXfq;tuQa5p|^Gk){lH0W@#H7$ucTB}L44N5@da0|)31L&gvy zzS1oNsT}qhirM3Z-Lx5zg|9M=&(>5azZHjan)Q?E;Rgtzv_pYVv0|$N+CGsxMUcg1 z1XNB_{S3BXrpmSbk}WARhHT?GtrhS=F$ak20=s>P>xTfZ5ZCXfCl=TFX%KN;L(_M- zhqQIrCez4{BM1o1LRUCXsW>PImlwy>4G86Ane=EL7M52}WDW~McdE&JBgl?%ltLUaP zF42ncEK->3d|?pzwC-M%PLfc!GdK!HP%ErhY=Yf9S-ks)rm z=UAoWpz#Wgp+07SHM*vBkVO{b!Eiy7r7<;C=G- z6bVcA?3<50Yxm7icNk(r711sS=Lb0g3j6_M@@)y9&#qy~KWYduu%ePU`NtdZYULg! z0j;7ZmVo$a5D7@b)3*e4u~IK0B_Cmbh1|0~Qtp8SJQ*wP2)6DEc6F&Go={ai7!8L6 z*oqR>PeUMEfaG{xGU4)anXaV$^!&m#k^;yU66YVFr9v1y=`7C3it$4nb05$zt4tm!d5rbY%=F+|f_LVvhbAJsoY~RQhzwvI2E-8nI*|Ai zd;&EHIp?!@vgI7bP?ZhQL{C!dg^nPv@P&o-VnSV#NJM+c#~fxvwx@velYk>u7+g#{ zUa!J=r~<&T4Ve+D#4+?y(EiD7qVo3Ch5^g2`cm)=YHb0w|10eoCX~bJ1 z$4>twkE8yIYs^b5BH)0Ihe z2>7`IjAC>I0M^aa(G~@bqM@TAd?rATA^g533zJnC&(sn{JS#pHCX%_1v9CdxRIGaK$hR%Z%3)Vs}je1yp>1w-?L zm63FzLOKk#9OUBgZv$9CB0%^*V6>9joh5B7bjE3BFMpVKgHOb@HGEQL9un7WokfLw z0mLi@auab}auwSf&x{5Cki11tf5BwL+z(yz>fNY5x2G;i7qK-c6zyS6Z)_z1YVkFF z_r-9IaJBIg2N?vmf+SWlh~8x-m^1^_&5!1O@#)V%pFZiDhFyA2DSo9^I4{U5(z9C5 zqYHJ9-SaB+S{VHg(G#n@{4{{dE49jg{c|=;c1U-Vbo0}>K#;Q&;@K)bfa1INu(8XN z;+tV`=-@*14P@}lq*WVn{$E$vbIs0cuZRqQgOFdkGR1M7JVU{y(8O>lGof}|(3P~` zHaoOq#v|Xs19O|BB5&ydxs1C|#AkCZB;a(7e1bcaDB|;%{H^%Z zbkT}^M%))r<}dsW^?F8JG#hA#Nupq+^yDHs7e}XJ?s7_yd3UeCCIjl8@F; z{jK;$OSEE-7IAphsk8Zq>CU1XU6ID++(ECSB^vK>wEUmPSXj(z5j;%Dnt2P$ny6Ja z#!t&Y*I{NE1GIygS$1H|gqh_UJlSRzXL(k(mUU5ZTYg&#eUK}UO0tXGU9u1L?>fS= z0SqpDE1Oc`%hfFVwP3pi`aaI^<4h3tORHh!z2D-7Zg29^tp1LGeyD|zzt9JAz zq}r|Q1k%u7`1^PsrgXLvx9#%R5S^-M0^|ItKbpYly~Xd@5PJOGkl22Py8$J+BiaDH z31K_wEq>vm-4XvZgW-o*9(qfH_}xZQAX~-}=ul++=tu*$ zlp)Ppc9x;I=R-L2cSsJwAIA;>y$KD$)}H!eAPZO3eMmmj>yUV>ROiWZ32K#A5#ntL zts<{VP^+|xD0Uug;0RB4d3s5$xzUBXTSeyIq^u%C^u$&Xej3;+;zzm!fBz1bj@&{L z{Q1IpC*t0&)f)OW8hU=}3;LgK2QczlNCQY4cVUQN$x|$N(LgwPmp(LA9DRs)pcWN3 z6c>wmQQQKd@>VPt!^(+I_(qKum#d8SlEdVeow^n7*)@G8#LYDGWD|O5PdV=lF494` zlrF)*WB`nDJ+5)9*yk#<-!OZKH&U$%3{12UR>Uq#UPQ2fKUV1kBEC$eT8#oWR@mcv z@1fgM@VReb2Ml{I!`VtcRjp5CE2Y=b7EGD^vr-)ELR=TtFy|nvr@3Lv6=g|6KQq$J!|V07eNbo6Wc+{CmmXknBmIG-Wl zsYXUlpcS4z=Zd)}Gt#C^$lhs4ecCU|r16CVVZNG!MU#jd%XK_d-5id`r&LdIB(URiQ;0T!HuXrxCx1~U@DAUffty; z1|z{Ks!td|oTISAhEx?$c9sF?*SY|d=)%`%fE=^=Vr#-ML?N^IJiO<8*D9{F$t{^a zF_8bh7jm!h^dl(RgH8N*_;bf5-X0QjKLTX?4WL#(4d7quAMoe<0o*^+VvKCjLpp-( zLPh-2UHpPar$&n@ta>B(2l1*XMJmVFdtF92bvL%_3A3F>vpt_UXnrbq4>}g@wqyY5 zu%|tMLJ90?OLd#HFio*1dT}VY4t?Qvg+c9~Q5pYyaw@n%y&?^s+_2R&!{mDq-;pR6 zX(+Q~v@Ls6ELrf9L!x3sM7)fU&$MStPh|{2y(~de@~>aIglH7JhDv~Kpg;er`{OO9 zc5+qsbtQ2w%<+Q%^1Z+`-v_^fo>*<+r@jP#mL61(9AMf@>V)@gJPZv>0TB6Ocqrea z1d!bAQ36)noXs7h`XNH!-74S~XSphOzA(deA$r}LGH|{w!BSk+Q3lARKGn=N;EDxb zsiOvg6!DK3fHq8Q%+W5PT)LOYVYxEshmZ09&*we8^aVyn@YyUr0_oqR(8j9 zwq$YgZMu76io1sfR&~Opu)NF#)~fRAP?dh#mJxRd4xn~z+d0P*hAy6+N_#Vp(Q7fa z)UY{<$BV9;RqN(_b;cG3}6dHf!PvfXiYa@wJarl_GW-)!Y?(F~yl|fnXE~+m=p<3S27h&b;$Ty&U zs0(O`RI6yv9Mx(_Oe>*^I3a%QH>0j%HK(Fbj3)#0XS^_bm8wsoD1_qN9HSz{-9i3k ze=9y82hob{c@%pSu)gj)bZ-MX2Zsd3+1%mdu$p%Y_|ho=qBu@M za4Qy%S|38It1hgIhDUL`Rh__ERbLdUI+5By@UYr|5RAz?ZMEv}P+$7bl>>ETPTB)q zJo}USPjD_ZE>5>ZQcm~NEeCr6pW`>lHtBSW)u!I>x&Pptv(DO-+DinRFXXD?92o73 zjl)+7XT&&uH{ucuM`}`}Md4IaK2tz!gYsyzilN3@hl@(2KE=9{^~DHn72Q-gk)5o; z#U)prL)8dB~jdF`w+iHjUg!*-hC8S6}lws6)M_M{O3f>A$?K-oJ60zEYv#Bjq!xB zLAhxmv(KYvvrNC<%WM)JVK|{HX+J%?v@U^kq0%^d!>Ufy@w5)@%*+|*+>rVpGRamp zZlUs>8Vga{m{)yx3PrmK%UECnDO)sj{@bvus11>}H$3R4 z{cXJ)6?KFIdMh$9sYP4y>#i~Ycu>>d0slYq!|cP)e~rLT*8~3F@VDo~k!Y_+9Qi+w zQO(Ru58g`fikUUTs#$w=1n-OSKsNw(=xPlBJeaP=TAA28o4-$~YfJIe?y!Wkna?U; z^tBNkuw2mrZQgiYlT>6BPQ`UaRgZG>byw?d3k*Kv{lGuacbssyn^VM}r4CwtGi|U$pYt!-ukUTnE>LpOjLt>@0(|%X`6^aznq23i;g7 zt?kzJ=02?TvENt% z(i=k!`H>;_CBx8xj#jWC%kG##c=+?~G;{(``D8DWyCea*~7T_-= z{g2f;5nZUe`}BWASA-wJC+Ug(5csJtKLl1}qyuu_G1RW2ecRrZug!^+FRFV0?JK;S z$9v49<7zkWfFlWuwuHKMHvcg6`Bh-sW{d6|NT_f9sjj5`&RM2!iN1F#T)|#~88~sZ zmR|I$@919ltY3W-MSXKTq(pop!RIjovKgA-e-XT=M?hW^mM?i2qIWY4gdGy{3xIgq zB;+Ogm4v(oPZ1Kbm>Nn%UKiB`OGZ}Mgy8mNLTsEDnk^$A*sraf9G~godbUPJ(2$fw z5;LtPN3{=u?GmB|=V_|V@PhM!mv~-a`x8pz^6Z`M7?t(1H_kpujYK|abHaDtp_U?j%J96t*OYsKD5qY3Z&dWtqtn)Ph1 zK*J{mUI+;nb#2*_OtyqZ!WDsr$Ho+lO3)t?8CDfnhN^HGduT9Kv{q`D#peUl(|JQ% z;U0N~3f@GxoH`&jF3eCyXhz-TVp|K6E`fHI0rKvia3-bWyQok?>3Bn=Vnl2pN;A@H zR9H0{?+H$+8XZNUXw`_`=z0Il<8L^N|AYG`+FeUztEUMxdI7A#nN!$t`3yTDDW!3Q1kOHn^^3jF53%I`y_=JG_8}!5iEh@ACpB4P1F2Sy+PXG{eR`9R(^4%m@J+f#X8;;_< z7U{+4FlC98Q8jJJ5q|2EP?t;F#KrY;6EQt}bAhfmY2Y;6F>IQqD%JXAwk+;Gp$aLy zIBxmmLb$B$C_+2x{l~E}?5@%&y3x&JW5e{d)uIR;S*sPY^%OUZUDFhWC~wHC+{eal zY-T6+WG|)k=-8M#Q4K7XrY+D_sT`n2OjyRw7W)O?J1W0sm- zx?fS|goLLN4RV63sXhUoV-8xRsaAnyWtEaJrlX`8g6uxPbkNpmxL>Fx!EWdY-UXGItef0RZwA&FA~hsph>GcC^u@VbTG zpwqSWlO%Q1_oJA?Tj>VWER@tebO1yNz>e54k9#hC{^;3^?YD?tU_X!Mf(iGazM(6b zHE8U-5PW3^u9$Cxoc!kDE5T13Nk?Zxz~N_u!Jp{PN6C&}x#mYaLtWNmo4`VH%|G$y zArZ|UeAyuf@&)n(eh29FZ_|TSxA$-9Ao#Q~7Fv?*}ZLfT%Q#??ee)UyKWO3X`?wNsf`lHyzXUgJW_6ju{cDI6%vM ze_ztJEk<7m&5Ga)>nxAmMH)&EpO_3)5zn|tK>9rD$7oQyEQL5{X~NLN&le?9{EeIu zsPd?U!zXtU1akL4(F3F-QAx*6N%tLucc4kJgYXnR@eTq%^<{%+vBQFislK~jeV5GgGgp;~GXCc~_mAC@#YklgekUCHUc zkJyLW(f->Rb@@~L`Sc4<|Gobn{DlB1iSYCte=9!WNwktwc={KA zL%j-5qVag{9yv(<&trrqGnax-QXghscv|JiB7${V>OQSN7Y*?mXkhD*pxy^qr$vG~ z?^Y#2ZNifyK^gv~#Hcl$pj)z(!XK8}4@h!|Jc3}!Quo*r4df#7+Y!5;+CLY}H=T-- zp|qrwr2wO($%>-d_;+6)l^ZcBzIwyWw*Y1FTClB>DRJcelE#3eQCZl>j4W|Pp%mhX zsH6{Z&~=r$NLK4Nc$T$d*#GFxf~di;ydNtxBqFpl86+; zkDx>1WVF4b&<0L+A7LBj!MD5GcUg1itHlTdbB2-Zav zi(UNNH0>r_7rvk?Ib+uYMWJR|76;R};LoX>Gru@kg0(e@(JO?3 zu49GxBS1SXE5u8vNURY5h$m--uxUyy6LD0k)(VA1@V?IxLKCbNyLwtHc)h^#pqGJu ziUV+m;VEQ#XqpQRFl!~aP4G7*PYNCAfzmGr^kSKOvJ{7QOa4$n`6aQGN#LcLcO zQ|0ENQ06M+(pnntuzZ2;!G*d9{M1(u*ekHpVR`tqv=O>3Pj19KRj4m*k;{&_ekWz} z4fZ%GFF6d!By~p#F=-2R#f9BWLt$z3GP(9hmzr$RCD>8%)#6zZjFe$TEQn^UPxDP$4B zY@aMuROvJww1SHd-Qyv2Q|uAX3RuMa0=gc=U?hwH#k1)d7sX~`O&n%}100@;I9i5K z4Z9I>@BVEXd)pYbV`E!G*@r3E83jtjE1pqfW3Whp`RpABcfkA^lw&#IyeeFJ*W=`~QSzS|ZQ>zx21_^XwO` z#FLe>qsyVRVvE2Pd`_ML>E$jUCG!1`2FWqBo)aS|$Z6(;&t77GD?f0Y z%oeH-ROd{F>DjW|ePXiL&1@J&6S|q5?{CGoQz}}qc1q_#U{XEeXVaO>{mt~cPb!-3 zK3nApharIvXOI?YSubjYhQwRd8}-w4XrI4BzL0Y_3TTq-W8dv>#Wy;l6>D_n?$U!p zkESabeG?%K%L7H9ulzx21%g~-s~J~^NXtteiz$+Xm^@&1+G z@xI*cWxwj-Rf4#k(AN&@w$(m!^u`Ll7W=iBHz8F~F$SE%dDm>yJruy*_V>=WB>ZUR z5cc_CBrCQtU;Hv_%|Cc4J>lNo_jM(+7_ptsri(PwW%Ptk=-@5qyMegpscbr-L(c}6 zL$B;x@tBLEKEE!dMN7H-{{Z38QyjVcY+5}c05wmQ%4He6QaElaV24@G_E&z^xkT(#SD4g<0a1sNjP{> z5(s*Aw=C?NSC+q|LIUKvIO8ZQL&tt4CW|)F0g7>s7TMpY-G#PDnF)(&4T(1Yr)46c{ z3F;FI*H`cqTDbI7QA^j_sEN0k!w--%sX{2&{4W!36F3NMyjNQnL0&cZdzJiq^^P6G!luX=Q^v$m zVMr`jCo+gjT&*`OQ{nDmx>Otjxu^zjaEG|n+~yPxmE#?%?tCW-Qw6m;hH!Lzf&s?v;wU74ntauK3xPh3RBw?(1O68qqu-=OB_Ro4k+r)e-EB3u%gSUF;Yr?(ueY%oqKQZm}D?SXN^O?eb#Fqb%dM9)a_0!B4S-D15kVvE&6cf;(k-VczYMSTNNhp2x83MCNr*F|#&cY~Dx5Mutb^h7`925Wnv zWCBKvSF{9PcN0F07vtkj=~?z0Re@qhk@Dk073SOxv=)3DwwK^{31GI~e3+hC2>HxM;OrZf49LC-42$MwihVyX=|BymE5#;c-+!ztnJw&_@gKv!`JG|k z^wV&=Khs?qfPEW$1Yf24&LsPO(c2*}`~DV+_Q1Zsk>K+f_8pC|nP=Z$1IW?r+d$O8 zzCVpZ)5X3C0KvZ3+<_cz)5jOMe`!0YS&Atsp9qjum6q+vfO#le? z{S-aXPn&%c6EN&s(GuAAE_^r;`&Je7&%S??0A}|6K6+yI%}-~ReZv4Zxb%%m24vp^ z#%W;RpOSQ-hOsa9{Rv&kY+>Jw{}}eo?+p8R-je%|7sANF)O<5`%r?FIJu&;{r-9kGSxVZg1q<9po88-r(z$_=Puu9~b&91kess+?z4IoCHw+CzJ z&eA=>nOeO%f!&eD)T2|Q?fK0rLS0N9JgYsdzA5DKvqjFGbK1*ttvVoVW@KG=wU?-z za;Z|7x~sjgQD`>dUx9s{mHBF})hv}8Y4{D`7UD`CF39&~%W#*Ndgs*UH*kYP)mF3C zYEIo%Ty|F*_Zn6T@KdSQQPU#CnulXWcCv;ai|f^D6QCBxODCq~M-qIEmV6Nk?npNYdrc%YxCG+wv?WK)Eu32eKW=`O+)8y1! z+RNysyc!%ECMQv_feOzPIfZh8b21c+!sM;uG?2=3+xn|~gsZkOnyF8OGHL^#`)Da2g0yR}I z?UtZ34NMN6cc^r!{46tG!p&Y&U?c1335_%gb)K7r3e}d!kT0%h9|p3;&x3Q?D`~!g zaw-!bME2^Mx^u;4?Paw>4GuPvT~KG1P|ndTV5h0kKDXFx)*8FFZ%1|mkp|!lQ%P6r z6PQtJ=}QIxUuF=D62sHP@GM0Bwo7(g1$-{6kLN*qkh*u|>`7QOu$|?u|OQu)Ps9IhoOuQ+FWKs1b#nYOiRVtTeMHGR4wFv5bG9 z-?PhABK;+e$t)(?Yg?Gr4IpYY{}w+pxE4JtQM)l$#I3bC47`|cz%ru{rH{30XkrL|ad0g9KR5?M!Q<|t`G!G(P z(`;nWugV0`Nb6{OpY2|Ca{%&9wgWVUq)kyB~5I)zoF!(w3$9< z5t6%xksP7q50)bN6eU+LLvkG@#pOsUl+0U!WFaLFuSD`FC975;Ifs&MtC3tu$<{SU zc2e>$l>C^ImFFNihmt2LX;U&xcb6@vgCl*~O3$=w@~+(*f-3y@q-$>%6} zo|0QrNbaEI^A{ocA|;IeAJJ$$vb=cuA$^PN`8-$^Djd( zLdmaE@@`6oMv*L`kb%Vju?;%QB!?mxA=S z+(vnnP-uaGj$s9KOe-M2_JI7}d1A1WW^e<|7;=yaXfHLOz1HBWJCKmsJ|GKEKo+2Y zl!btliB@~5&1iY1FU4hgLK?&@7df<^s_z8ruybe;;9M}~$)nY>=G~mRCX}haUgXrc zNVUp^Ryp-UG^#hJu+Xgy*CpRTLd9yItF~w@hd7w4mdk>NLf%`jPv*Z9{OXCR!&td+ z4I|b-aJB}RwP;W;`gV2^qD|vu1IwSv)xv6VesPHJJJIpd2pm>%3p#=ns^vMKmij*Qs6BW2eJn}--iq&b<2$dIKVOQRbJ}MU%fvc) z`(3xZisU{m{?h_gm^!$TJdmyt^|cpkWbop#xKzoNTX|a5CP*;BwF8jGq~Id-z4ZSD DR}8%E literal 225069 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 delta 929 zcmb7?PiqrF7{;^7Znn{++lp0LQy45l5^JD>JqUtTER@tp+lwI8Y_gNSo9>^uJ42g; zRFNu$z0G>5;e* z-&=m**q)(d7iqd~*juQg)d_Z=yZ8mg9;qO3oNW)~YL3-3v4w4dh=VFsTz6c2rpgB( zZw5J-@ux=pg8kri@RHxDumV>h0ogLlmT47YzHAyxoTZro3-Z53lAjsk_k6kSNOj=3 z!48v!y)~FEiI9aG5rzBD_?O0q|7)W4vk;TR{Y5E8%TbJk3OLMB9G^qTk4LhMoMrdK z33fg4G`09}w`uY}MeIquI2{p(s_8#$-f~_sCG~rL!`8(0a&}4Ak*g7mOv5rrI8DpY zbrbJsE{+`kEs8o);bRYw>;pbNSVjYr-=wy}}+VNLXb}<+fVlkH*S3*%zgd zKY=bBLx=h)TeC1}HMvu`~LZUZ%8K`~`l~Q5OIJ diff --git a/.doctrees/cli.doctree b/.doctrees/cli.doctree index 1b169abd287aff1fe0e50a6598a85c2c4558f49e..4f61da6d093ea85f7b1e1ee2f60ce1cc9e13046d 100644 GIT binary patch delta 2204 zcmb_eU2NM_6mEXIrlaF0?K0M-H*U10EcK8!t#6u+ugsyo5p&}&u0Enqb2x;O4@x}x2$PaHbY*2JrwlsN7$F`>q);x98y`z=6Xr;YS z#kNU|I<}DPP|}pCrpUV9LKc?mHliv@ae?hrSuY7{pkR`)_!0s8g2ht@Qsjwk`(kBj~XuoDBg&}?K9i=vXE z6Q_<$U8dKF)kF$0Hh_1nO^m5b2gG!k*`5D?VngVF-F!EE~$W!;n5=YWepH~Q3 ze;GS-USh7#F}>4{w9BY0BB)syP61#b9||2(QDz&PG^(;bODH#Y4#>SK)$`knQ_ z8Nl{Lc>iS;8@)~jA#F^{etX;4+JNroqC>wE1l^A`gJSENtYEu;SBRPAHtz!Xs$>)O zw}FjxZ5^XIy(Ma-jHoO^f_4?OzN37v z&Jha{pv~e4sAjwpkS$4g<# zOxgBlTeGvxt4EY>_X>VUcqY-KnfTVUG{=Gi4wiC^@|%8o$v z=RrU|pn{oomHmu^U%up*8*p*lAwzCr+A`t4100-mcxlW#>;6J%c`{-m2C4tEYl({E|=@?F4plCh$kd6>s z?7faMdL}JTXl^YSAs+t87Kcy44mw$*THmEuK<4MI-AD i)8yr5@_Zl#ouwHHAR(ZhTV{IfAmu=lH%pp_G6De8g+#aj diff --git a/.doctrees/deployment.doctree b/.doctrees/deployment.doctree index 6675cb5b394d613b922c13fe27a0ac64bf5f2aca..b4e65bf40d04140c7623e5a9eb2c04dcb348ef9a 100644 GIT binary patch delta 7985 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 delta 1060 zcmZXT%TE(g6vlg}(+aIY0a40BhE!7ueNfxdAPHESQfwv z5jbV%f`zYy7*mUhBt#MyZdjO@n1H&_7(>{g{snl?9a=GNPR^Wje&6|K?w!@|WFt;g zVb%1oKcTv7fEQLLEE$f1y>fws;8&%W9EVAx8H7BZK8rRB7g9oYwFBN6b@0P>iyKnH z*E)+jC>BU=C6s38!pj4XNSLCm?{&dR$4;0r7SNrUaNoNhTXWv-3c~-p za}7Q8hz@*wqE+pJ&+`;1{bZhb<%NNMe|0e_eJ|`}r*416i zAbjy%=MM4kdv6|GZmc6-DrJJj^BG({5396L4+)o3eToj(^57QCEUn>TylXei9`59N zWwyZYBvP8~voRiQ!D0J+0o)6Do8Y%rcS7ID=9aeY3oU$ zcuOnUvpJUkcg$$na-b{Bcn@_e8%vJ077}7b3Iu(o`hwiaHsr!;o0oJX`^7nq8&xGs z`?dTwze=Hyd@8UHm~VWfH$nP<;Vp(m4E5Nr!=R-ur3?&a4CQD#mU-#y#opm-gS}Vq zdP%4j726_G4#8w8B5p*aY0RZssuq=SMU=@$m~@oMMwp}~G9n77Lha}VO;+Z_opv&h V8FPaFi0p(*Ig$49$*I9M@&~h3M8W_7 diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle index 4a37ea783e07501ece74d3feff2678ca16539762..0bf0c27f81c21f6606204643e61efbf2c26ad604 100644 GIT binary patch delta 16201 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 delta 15378 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 I8<>{z-)>fB5&!@I diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree index aaba530252d5ddaa8c9e6a949a24a6ce7a06c642..7d2b673d3b341135e80390b1fc9135500e89b537 100644 GIT binary patch delta 2608 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 R+UvNwiCECg$F#JPe*uj$ST+Cv diff --git a/.doctrees/testing.doctree b/.doctrees/testing.doctree index e8ca6e205dc384e8dd1481aa7a6a5d25f3ffc0ae..030b70a0e80e492c2aa89615d748b6b637a4a935 100644 GIT binary patch delta 3828 zcmeHKOK%fb6!uJPAcJU=K!B!s+&YLjiC-~@mPAp5O2b1KVjdWfgZ)0jzkTkTuC>Oq^fxx-JPl+L&B5f%b~WBpb*EJoSCHG zAPI|Uc0ft9_pOobNW*$jRdn3jYeP_;+B$lYb#gJ*$iL+#_3Qnl?&X!_<5V4a5L;ay zF(PSU@xmE1lYdZQf;${N(cIHdv-(+1K@sT9U(<}RaZD1l@J zX`+(FzKDgLTwL3K^1`=V?#x%8LU_UD9 z7$uX{QA#F}s8hxhC=(z|^RBaWk03UGyHlS*luN|nFgxKU z1KnFzMMJb9vTkxOwzh0=79(d0qMo<;caXj~n3o9?Ea}g~yKI0>BBX{BP(ol{>ZF|a zB@&7_juQ!!^#)8=pb=y>^?7YRq-#LJ!0a{x%842_N}7VayQu)N)xxm9<~1o0XgX-Z z_J){cuOC%CbP59bqqⅈD$#?(9{MdY%SX)ELsHourrH$4OnG1WxmL?mY3XTOXu}P zrnTpp^GfbDv(>U(R<}J%R;!fusYz)Ovx6T)Y3poCvlt>k>B7NiwtRs>ibYZ%Z><65 z0ZQxRuT-h2Zgw#>?VOv9pXd17RH3^zcaut+a`WW<;e>nMnsV~za1Vc%jW0J(Mn+os zc{X%HbdW;6LDgcOwwBy?^t4HNOmdCBGk(rppZk5}9LL=v)5qTCS9z#6!S?3%5YO>l zZnwuI6_P#P&Noq&Fb|?{kNXxx+-NuNuZohR!&C$2Ux@CZP+Zi+!%&!H5tJ?O3LL-R zL*7j66gq}lv>+sS?h8J#w1Q_5M%W&TP9y8PjdnZisvBI>*6H;0SmRk z4s`-dGWHuHKPF@3=9s`wST2XCOT%(mcDiJerCd&Tbsc$RLC~w2y-lk7CD_$fT@q+Z zuqXI>H?npE)&+W{P9}H5N`VC9Bq&J*k)u6SlJ!538{4iR*Ld+%V_nf`_~_(!#?( zHaCZ86Mt?saf7pondBPTo!VM|^&y&=C1+E+xSex%QeW|_H?MHHW?sUYrfMXXSvz+r z^J~qD2VgOGpPbK0p)?%MiS%)qKE9xjdsO@jJW4aQbnhCIMXb}Gm$?U|DZk?tdS;sG iPcz-=l7y)AK9Ta-CT5IYB~4@W?#7JeX6NqY=LW97F1 delta 546 zcmezShjH~SM%D(_sS3FpS-rw0uS%9>G@X1gTz9g71k2>0? z!oZLrmE|}2T53F#AIs#zV#&z?X@-nxU=0g2SwMm}i)BHSgSIh;uP`G}xff7jfs%{| zNV80ac7`lO*cHT=&R{N0%JSUon?8+^F?jNm3|Gb;kX4*et2$UFCuF)a0V$AOhccBJ z=fUj)3QA^az~o}Gv>7)b%k9pJ0Lg*fAqH|s3x+$u!YJtsPOZLTb+5C5=C zzL=lP1f;;`%7V=O0XA0x$y~57%-qR}*)o$mO9WY*L8ku?7n{7L#EwyL^XHQFOiT%^ zo0pVxv#=SnGB9KrOx{|ZA*~H!Y5PRiRZ?`k&dy zt?f%{3aXT>Z+7SZe*I?N{!!Hnr>hq&)WF^J#UD1Jw<<@XGX;T{bt#3v!e=Cb*Cj=^ z#M;A_*lLvfW{0cLq2e!+KG|)euIIGG@UWnyw0O?t78l5|;oFlB;jAK%jD{syC-W+= z6D&w7N$HsaUXXM#yq9P>MHYzKuVGcm>ykVl$NPwmlS!2v%@a+3h;c|Jv991_j*4Uo z_@$IAY{sB5k9k=LQv%9MBSDIkBI~M>!MaGWCh|Fgl{pM@<`s`Pkud+V(2^Kftwo-5 z>O2qFi`8g+qrbG$S5ZZU(Q!?;*uSqvy}P^d^&IC2>3PH&5b8D&)5gB_!Et;`+*Fn18pEN(T2dgG^k~O=Z=xxiX zQi>$-Tt?yba5$CWH4U?m_dOB6A^6ekZ5l9V?2aD#byD7pmuAU0eLbDm%?F$Io3~zQ zs&i8R|0J%R`?%4({K0ngpgj^o?Wo6m>wGs#m>Vy4a5YVS6mD#yQCL^gKr4pT1S=ol#vkLQ3_qJ8 z_?W~)@$n11q*KaxmIx9*Fqlj_IXN`wq)Byp6R1PIH2`^WOF2nfRwF84!Vt4~y!ATL zTaD%wnguwFF-KJmfoA5>#{RmgqtqLNP3DJWu;?r{P^~+~N=WCtXNvLIq|91N$yM{v zf_NG8d0ojuPfUSJ#zsf+eR57!Qbg03t9C-))CyqpTto`waYgEPU&L{$|PXX*BN zQq=G}ixw^@c`PV$zm6AF3ECkq7reFxofoP?AmL@6HjK|hy&`nR>*=>@^_X@v=&}E< zRv}!xA&04PGY>0a<(9>QZSw?P2*; zH^mkkn#|t0?cCH+r-Ij+&tB+pEBK^S!L$ROaVq$vr)#+iKIzKHmnxXMeZTqU#lCG$ zU&pg#PJt4hC3JRaMAnxjO8Oa^+|KNFDEqESS!(y+YcgN|{#fk-6?>VP);+}*m&%n& z|4y_1$&NvcVP{KY?iih_R!k8ogaV3&E zI9HYU%n&poJ&7ShFb`hJ<}w7@%L1P{qKkm6it}Qe8A&Vm-p^f^K&`y*rj6LON9^8{ zpEVk_oG2CL<8fXPWaw|2W!wOv6CjHpIwu`J+9%>%K*UxjPu<-=MmbUK9#RZ@t8~`gE50&HTncK#;V14DDfb|bE z>o*oWzedYxR5GyO8hC~pm~W;~vulbiR5$0BK+S&pkq~MdEAZJ2*h(!txMS+e%PoAW zjDI9rree3Xih^-_(e z97H?Ar;e-`w_Dh@)@9q6x&!t=7(K|n!jx-#*;B5GDQACDiPms0yE>hvI$dQt)lIR5 z3Q0V-z0UD0j03{W6(FUkV+B^L$_x*;}mWH zDDn=&Aykm)l?R`}8D$=Dz9dtKt}-B=aEcxVX0n{5gP*6UK=l69%mCRp+=}_>t82P< zPw+V@PA^EvKx~*E+G2xYfy}Y%5A%0lSYv+hT-~-4u_L4qOW+uE`8Dg>@i_T9<4t%m7AiMC9)Bg4-E=CvbqU2@<0)$9&b;w|^QX{1~)GSPV?pC2XqGD-;-cL*A5JHr3tF{t)%2`XZa^_8%+J zCN3VK^SNnLWXXJf^2&iKG={i|hkjCh=eXtJg+!YSr!s1U+cB0QW8$ZBPJCVp(lI2dy*aU=ViES-NE@f%Nfm zvOfx;UhZ^+q6B+u813VX2t@(m(-1#~0*>34LTGeV>fti#1&Yv-GSsj{W3MVgz7+wA zOH7weUzaM18v@@Qj$0a+ne6cd(Cl9~1*m?&xKg7h+FRg{lWxzsQG!CSr|VH?^#kAm z-aPeM8+!7}*?M%9<52X<UNikNeGJeo zeef{q-TN9EA}f6WUgeFD%x4M3_Zqz-O}`PbpN^utxSdh^-6)E8+!d{;IGY~1p`zkk z`VZ`RH+!=yY7e)dHJA!K$Aq0_g3hHU>G!;dDK}7TUkkbg4KtN&U!|AmFRBv2CV2du z{-R~dbV}bFv7c&1f8!dX_Ty{N3tTn|Ei+!#kxobHnZ=h2;U=w59@ZQNI*cCrg~aAMT{qz$!mu=$P-G;SYgM?1OidK8x(ia)oP zC_IVpffoXBzY^d+l?Y58<*s`4FFN$m&Xx4vYFI+w>C%J7op!Mk<+(RKCcj}!D#0oC XhwZ4Qb-K delta 737 zcmY*WT}V@57~b=3Zs}a-^rP+1bb@O(jkTFSwK=_T5HTu*{;2RM!_$$aF$YBj2`dsb z&2!+5?xf2IG>};o5kV2cXyBbU(cQwx3op9tJI9%J^B%tEJb&N&E$1q}zp*^f;9x7> zB>`(@n)4$_O%|NXJC48)dR~Drr2=RpvlR#FRR9+#YehXZHX~1KR*33Mx``#PkW>p7 zH6KNetqN-KWt;6flidml>c_9O=pzKtSEWXeT~z82J}kQ}%Q!laYo~W75!wrhL+~rYdhr>D2h0u~dfNC7^gk`qGI6n-)pv!m;ir+~Khj zsy3M>m69=M3}n`rxA*G!FJo%lZc=%w<5{^u_u|3RUFgKV{T$@GA)a&GLvl&G@TM(%w1{Yft>0J*zbRvpI%EfSo70c|x7TebiCtDF| zAP#rk0uSP=YPa)`M>fk|IVjg9-y%DxY#U8?W0z8DpGHPLTocki~Pfd8obuzzOe z`^`7M@B3zcd*^ES>Wy$@GV;bH^@B)T-xKXeE!9@_F*IDU2--2yKY;eB#iB;4*dkL( z?8KDPdUlRM?6GyNY^1Nx$)rwCotjE2k+a|IGAvZaC)IMLj7(yc46BTFnINnek!6{_~C2z3F1KuzsJt)OtX!hi^e!kr2vZ>o`Wqh=|AObhO=z@lUtk@l~v=f zcz#z3+S%c7`5h7P0FKW99E)t720=g}Z;3|?5%H>pDwR5>7C0Z$s zAWKqiCm+Duve1Njct>0qVOrB=$Fr5Orqyk!Y?vgCAo>K7Ar01gF#x8PkQgzVuxlns zoIq=OP(rb7GtrokPl~Hpwd+$S=R|dcD||G+EMiwI-F1(D3m1il+=X0KwUwOWQjjb| zQsOZZ@QYi3Z(c{;yB^QGtVO74=#*qBl!@&+>u{s`MNUF#07s)Uyz;w~g~Z7WuUDem z8NT$4Ve&Gfi8LxCbc5<@sgy{i?`>SNaCxSc)7v+6{601oDG|#eR>m}-=xbsos9#mK zGlr#(sd}cW5IrMX2BluhTxcim^2uY#8BKVELL7ULrc&EyHqeto-AHgV1ICZ9Ui3{; zfzUlT_&lERdO%a`leSjpo{66FiuU0ag%e1*TyFl0!f|VD2F>$X6wa&?=BYoQMd7%$ z^uHB_<8CT})Sus?SUzi)6GgFXR#7l#b*uDYge`0CWS?(o3s172_dVi#A*2AP0e(tT z*k_Q5K?ztos!&oyDr{Sp4!e8}T{n5qsmHJ{KB32$4`K7NH+OGS0K}rYZhzpfm5@5;)i+S7y;J)+W zI_hvyPHgdR$iyO_Y9DVQXFdS-n-7+$gRPu9ECD0e-?a|}Ul?UgOE*7NM_$LZ;e$ik z&}lFcNT2YVB5!{b!qK2M_y-!6CzdbE8Zrlx3No9jWmEHHD%a7FLy*oTRVUf_VM;{i zn{~MkLdP<&tRQ|u3PGzAQsllWz^X>jQBoK&9QkxXiV`pO4@b zNcbw&ZElVy3>9#o%!~>>Tb==ce{|#G>bOA~rU83&@rOeLvwluf%pCkxS zhDSSt>6prX*}Agcj6@QM<{fKN;Tps7PS)ACHQdjB9m=d&3P8O;mHVrpbSoWuF0h{x zoou>qSb8?f{^)9Dt9DT-7iG5xHcQV%*|lA3_=9_K5sZ&T*@5m2;`K1R_S=%^(EiXq|*I-J5$AQ5;(nq4$ z_}7iWEPrsg%Ybpgh2yUt+~l6Gr0)er_$GUGZ-;bK#aq|Ht#Wp;4#yA|%9Q^Jk7r|S`bc60A9_X%J5x~*?*NP+ Vj%;ZX=KNnsn8U==oktIc{{-&L78C#g delta 415 zcmdmRnep=mM%D(_sTmO)StVU3JBFD~&USU3{9Z|V^0lx4rn#(>|Eq~kwhb?4Tr{~c zKzFi3G&|FL*2&Mq6&dGGULR!2R-GZ0HJf#Eptcs6IfHd_Nkj?LA&9>J5#5Z(;rfoS zPCgi^#&`s*uLh{^07M^%3Dg%HRm$`nqVIl`G2nOrUWSVxCS;4bcO+m{DQ!>R4GO1-8k8vNDsO#U?VE zP2L!;JJ~>v9V9r>K#Q#os7Zzm>x{sByA20Of&# z3tdDeCnb0>R&HLKaD<6z9^2;PWNsGrLN*45tUR{Kt?8yRnILu=kSOip%uCEoEvYO> pEuK<4MI)<_ZSsS3B|eaX&e9A8kPuLhScVBZNIB5>&Cwa5i~!X1j?4f6 diff --git a/_sources/api.rst.txt b/_sources/api.rst.txt index 7bc0506..72e5ee5 100644 --- a/_sources/api.rst.txt +++ b/_sources/api.rst.txt @@ -12,6 +12,20 @@ The central object of every Responder application. It holds your routes, middleware, templates, and configuration. Create one at the top of your module and use it to define your entire web service. +Quick example:: + + import responder + + api = responder.API( + title="My Service", # OpenAPI title + version="1.0", # OpenAPI version + openapi="3.0.2", # enable OpenAPI + docs_route="/docs", # Swagger UI at /docs + cors=True, # enable CORS + secret_key="change-me", # session signing key + allowed_hosts=["example.com"], + ) + .. module:: responder .. autoclass:: API @@ -28,6 +42,27 @@ parameters, the request body, cookies, and more. Most properties are synchronous, but reading the body requires ``await`` because it involves I/O. +Common patterns:: + + # Headers (case-insensitive) + token = req.headers.get("Authorization") + + # Query parameters: /search?q=python&page=2 + query = req.params["q"] + + # JSON body + data = await req.media() + + # Form data + form = await req.media("form") + + # File uploads + files = await req.media("files") + + # Client info + ip, port = req.client + is_https = req.is_secure + .. autoclass:: Request :inherited-members: @@ -39,6 +74,19 @@ The response object is passed into every view as the second argument. Mutate it to control what gets sent back to the client — the body, status code, headers, and cookies. +Common patterns:: + + resp.text = "plain text" # text/plain + resp.html = "

Hello

" # text/html + resp.media = {"key": "value"} # application/json + resp.content = b"raw bytes" # application/octet-stream + resp.file("path/to/file.pdf") # auto content-type + resp.stream_file("large/export.csv") # streamed + + resp.status_code = 201 + resp.headers["X-Custom"] = "value" + resp.cookies["session"] = "abc123" + .. autoclass:: Response :inherited-members: @@ -47,7 +95,13 @@ Route Groups ------------ Group related routes under a shared URL prefix — useful for API versioning -and organizing large applications. +and organizing large applications:: + + v1 = api.group("/v1") + + @v1.route("/users") + def list_users(req, resp): + resp.media = [] .. autoclass:: responder.api.RouteGroup :members: @@ -57,7 +111,19 @@ Background Queue ---------------- Run tasks in background threads without blocking the response. Available -as ``api.background``. +as ``api.background``:: + + @api.route("/submit") + async def submit(req, resp): + data = await req.media() + + @api.background.task + def process(data): + # runs in a thread pool + ... + + process(data) + resp.media = {"status": "accepted"} .. autoclass:: responder.background.BackgroundQueue :members: @@ -67,6 +133,8 @@ Query Dict ---------- A dictionary subclass for query string parameters with multi-value support. +Behaves like a normal dict for single values, but supports ``getlist()`` +for parameters that appear multiple times (e.g. ``?tag=a&tag=b``). .. autoclass:: responder.models.QueryDict :members: @@ -76,7 +144,15 @@ Rate Limiter ------------ In-memory token bucket rate limiter. Limits requests per client IP address -and returns ``429 Too Many Requests`` when exceeded. +and returns ``429 Too Many Requests`` when exceeded:: + + from responder.ext.ratelimit import RateLimiter + + limiter = RateLimiter(requests=100, period=60) # 100 req/min + limiter.install(api) + +Response headers: ``X-RateLimit-Limit``, ``X-RateLimit-Remaining``, +and ``Retry-After`` (when limited). .. autoclass:: responder.ext.ratelimit.RateLimiter :members: @@ -86,7 +162,14 @@ Status Code Helpers ------------------- Convenience functions for checking which category a status code falls -into. Useful in middleware and after-request hooks. +into. Useful in middleware and after-request hooks:: + + from responder.status_codes import is_200, is_400, is_500 + + @api.after_request() + def log_errors(req, resp): + if is_400(resp.status_code) or is_500(resp.status_code): + print(f"Error: {req.method} {req.url.path} -> {resp.status_code}") .. autofunction:: responder.status_codes.is_100 diff --git a/_sources/backlog.md.txt b/_sources/backlog.md.txt index 73f717c..7dfd145 100644 --- a/_sources/backlog.md.txt +++ b/_sources/backlog.md.txt @@ -1,7 +1,8 @@ # Backlog ## Future Ideas -- Consider adding `after_request` hooks (complement to `before_request`) -- Explore WebSocket before_request short-circuit support -- Add rate limiting middleware -- Consider async template rendering by default +- WebSocket before_request short-circuit support (reject before accept) +- Per-route rate limiting (different limits for different endpoints) +- Built-in structured logging with request context +- OpenAPI 3.1 support +- HTTP/2 server push diff --git a/_sources/cli.rst.txt b/_sources/cli.rst.txt index d7a0447..e465912 100644 --- a/_sources/cli.rst.txt +++ b/_sources/cli.rst.txt @@ -71,6 +71,25 @@ For URLs, use a fragment:: $ responder run https://example.com/app.py#service +Environment Variables +--------------------- + +Responder automatically reads the ``PORT`` environment variable at +runtime: + +- ``PORT`` — bind to ``0.0.0.0`` on this port (cloud platform convention) + +When ``PORT`` is set, the server binds to all interfaces automatically. +This is how cloud platforms like Fly.io, Railway, and Heroku inject the +listen port. + +For other settings like ``SECRET_KEY``, read them in your application +code and pass them to ``responder.API()``:: + + import os + api = responder.API(secret_key=os.environ["SECRET_KEY"]) + + Building Frontend Assets ------------------------- diff --git a/_sources/deployment.rst.txt b/_sources/deployment.rst.txt index 7644ceb..6eb7b33 100644 --- a/_sources/deployment.rst.txt +++ b/_sources/deployment.rst.txt @@ -67,6 +67,27 @@ The pattern is always the same: deploy your code, set the start command to ``python api.py``, and the platform handles the rest. +Health Check Endpoint +--------------------- + +Every production deployment needs a health check — a lightweight endpoint +that monitoring tools, load balancers, and orchestrators can poll to verify +your service is running:: + + @api.route("/health") + def health(req, resp): + resp.media = {"status": "healthy"} + +Keep it simple. Don't query the database or do expensive work — the health +check should return instantly. Cloud platforms, Docker, and Kubernetes all +look for an HTTP 200 to confirm your service is alive. + +For Docker, add a ``HEALTHCHECK`` instruction:: + + HEALTHCHECK --interval=30s --timeout=3s \ + CMD curl -f http://localhost/health || exit 1 + + Uvicorn Directly ---------------- @@ -82,6 +103,45 @@ Uvicorn supports many options — SSL certificates, access logging, graceful shutdown timeouts, and more. See the `uvicorn documentation `_ for details. +For platforms like Heroku or Railway that use a ``Procfile``:: + + web: uvicorn api:api --host 0.0.0.0 --port $PORT --workers 4 + + +Docker Compose +-------------- + +For local development with databases and other services, Docker Compose +ties everything together:: + + # docker-compose.yml + services: + api: + build: . + ports: + - "5042:80" + environment: + - PORT=80 + - DATABASE_URL=postgresql+asyncpg://user:pass@db/myapp + - SECRET_KEY=dev-secret + depends_on: + - db + + db: + image: docker.io/postgres:16-alpine + environment: + POSTGRES_USER: user + POSTGRES_PASSWORD: pass + POSTGRES_DB: myapp + volumes: + - pgdata:/var/lib/postgresql/data + + volumes: + pgdata: + +Run with ``docker compose up``. The API waits for ``db`` to start, then +connects using the ``DATABASE_URL`` environment variable. + Reverse Proxy ------------- @@ -95,9 +155,31 @@ front of your application for: - **Static asset serving** — offload static files to the proxy - **Rate limiting** — at the infrastructure level +A minimal Caddy config that handles HTTPS automatically:: + + # Caddyfile + example.com { + reverse_proxy localhost:5042 + } + Responder's ``TrustedHostMiddleware`` and ``HTTPSRedirectMiddleware`` work correctly behind proxies that set standard forwarding headers (``X-Forwarded-For``, ``X-Forwarded-Proto``). That said, uvicorn is production-ready on its own. Many applications run uvicorn directly without a reverse proxy and do just fine. + + +Production Checklist +-------------------- + +Before going live: + +- **Set a secret key** — ``SECRET_KEY`` env var, never the default +- **Disable debug mode** — ``DEBUG=false`` or omit it entirely +- **Set allowed hosts** — restrict to your actual domain names +- **Use multiple workers** — ``--workers 4`` or more, depending on CPU cores +- **Add a health check** — ``/health`` endpoint for monitoring +- **Enable HTTPS** — via your proxy, cloud platform, or uvicorn's ``--ssl-*`` flags +- **Set up logging** — uvicorn logs requests by default; pipe them to your log aggregator +- **Pin your dependencies** — commit ``uv.lock`` for reproducible deploys diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt index 6b9ba39..f48987b 100644 --- a/_sources/index.rst.txt +++ b/_sources/index.rst.txt @@ -59,21 +59,25 @@ What You Get One ``pip install``, batteries included: +- Pydantic request validation and response serialization. - Mount Flask, Django, or any WSGI/ASGI app at a subroute. - Gzip compression, HSTS, CORS, and trusted host validation. -- Before-request hooks that can short-circuit for auth guards. +- Before-request and after-request hooks for auth and logging. - A test client for fast, in-process testing with pytest. - Route parameters with f-string syntax and type convertors. - Lifespan context managers for startup and shutdown logic. - Custom exception handlers for clean error responses. - `GraphQL`_ with Graphene and a built-in GraphiQL IDE. +- Server-Sent Events for real-time streaming. - File serving with automatic content-type detection. - Sync and async views — ``async`` is always optional. - Class-based views with ``on_get``, ``on_post``, ``on_request``. +- Built-in rate limiting with ``X-RateLimit`` headers. +- Content negotiation: JSON, YAML, and MessagePack. - A pleasant API with a single import statement. - OpenAPI schema generation with Swagger UI. - A production `uvicorn`_ server, ready to deploy. -- HTTP method filtering for REST APIs. +- Route groups for API versioning. - Signed cookie-based sessions. - Background tasks in a thread pool. - WebSocket support. diff --git a/_sources/testing.rst.txt b/_sources/testing.rst.txt index 6271d2d..fe3ba0f 100644 --- a/_sources/testing.rst.txt +++ b/_sources/testing.rst.txt @@ -269,6 +269,57 @@ just like in production. You can verify their effects on the response:: assert r.headers["X-Served-By"] == "responder" +Testing Rate Limiting +--------------------- + +Rate limiters are just hooks — they run automatically during tests. +Verify the headers and the 429 response:: + + from responder.ext.ratelimit import RateLimiter + + def test_rate_limiting(): + api = responder.API(allowed_hosts=["localhost"]) + limiter = RateLimiter(requests=2, period=60) + limiter.install(api) + + @api.route("/") + def view(req, resp): + resp.text = "ok" + + # First two requests succeed + for _ in range(2): + r = api.requests.get("http://localhost/") + assert r.status_code == 200 + assert "X-RateLimit-Remaining" in r.headers + + # Third request is rate limited + r = api.requests.get("http://localhost/") + assert r.status_code == 429 + + +Testing Mounted Apps +-------------------- + +When testing WSGI apps mounted at a subroute, use ``localhost`` as the +host to avoid Werkzeug's trusted host validation:: + + from flask import Flask + + def test_flask_mount(): + api = responder.API(allowed_hosts=["localhost"]) + + flask_app = Flask(__name__) + @flask_app.route("/") + def hello(): + return "Hello from Flask!" + + api.mount("/flask", flask_app) + + r = api.requests.get("http://localhost/flask") + assert r.status_code == 200 + assert "Hello from Flask" in r.text + + Tips ---- @@ -284,3 +335,6 @@ Tips - **Test the contract, not the implementation.** Assert on status codes, response bodies, and headers — not on internal state. + +- **Use ``localhost`` for mounted WSGI apps.** Werkzeug 3.1.7+ validates + the ``Host`` header, so avoid synthetic hosts like ``;`` in tests. diff --git a/_sources/tour.rst.txt b/_sources/tour.rst.txt index f041e3f..6063fa8 100644 --- a/_sources/tour.rst.txt +++ b/_sources/tour.rst.txt @@ -596,6 +596,73 @@ can pace themselves. The rate limiter is per-client, keyed by IP address. +Pydantic Validation +------------------- + +`Pydantic `_ models integrate directly with +Responder's routing. Set ``request_model`` to validate incoming data and +``response_model`` to control the shape of outgoing data:: + + from pydantic import BaseModel + + class ItemIn(BaseModel): + name: str + price: float + + class ItemOut(BaseModel): + id: int + name: str + price: float + + @api.route("/items", methods=["POST"], + request_model=ItemIn, response_model=ItemOut) + async def create_item(req, resp): + data = await req.media() + resp.media = {"id": 1, **data} + +When ``request_model`` is set: + +- Valid requests are parsed and the data is available via ``await req.media()`` +- Invalid requests get an automatic ``422 Unprocessable Entity`` response + with detailed error messages — you don't write any validation code + +When ``response_model`` is set: + +- The response is serialized through the model before being sent +- Extra fields are stripped automatically +- Type coercion happens at the boundary + +This is the recommended way to build validated REST APIs with Responder. +See the :doc:`tutorial-rest` for a complete walkthrough. + + +Content Negotiation +------------------- + +Responder automatically negotiates the response format based on the +client's ``Accept`` header. Set ``resp.media`` to a Python object and +the right thing happens: + +- ``Accept: application/json`` (default) → JSON +- ``Accept: application/x-yaml`` → YAML +- ``Accept: application/x-msgpack`` → MessagePack + +This means a single endpoint serves multiple formats without any +conditional logic in your code:: + + @api.route("/data") + def data(req, resp): + resp.media = {"key": "value"} + +Clients get the format they ask for:: + + $ curl http://localhost:5042/data + {"key": "value"} + + $ curl -H "Accept: application/x-yaml" http://localhost:5042/data + key: value + + MessagePack ----------- @@ -608,6 +675,10 @@ Responder supports MessagePack alongside JSON and YAML:: # Decode a MessagePack request body data = await req.media("msgpack") -Content negotiation works too — clients can send + # Respond with MessagePack + resp.media = {"result": [1, 2, 3]} + +Content negotiation works automatically — clients can send ``Accept: application/x-msgpack`` to receive MessagePack responses -instead of JSON. +instead of JSON. You can also explicitly decode MessagePack request +bodies by passing ``"msgpack"`` to ``req.media()``. diff --git a/_sources/tutorial-middleware.rst.txt b/_sources/tutorial-middleware.rst.txt index 5679d35..63032d6 100644 --- a/_sources/tutorial-middleware.rst.txt +++ b/_sources/tutorial-middleware.rst.txt @@ -117,6 +117,47 @@ the existing stack. Keep this in mind for ordering dependencies — if middleware A depends on middleware B having run first, add B before A. +Writing Pure ASGI Middleware +---------------------------- + +For maximum performance and control, you can write middleware as a plain +ASGI application. This bypasses Starlette's ``BaseHTTPMiddleware`` +abstraction — it's faster and gives you direct access to the ASGI +protocol:: + + class SecurityHeadersMiddleware: + def __init__(self, app): + self.app = app + + async def __call__(self, scope, receive, send): + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + async def send_with_headers(message): + if message["type"] == "http.response.start": + extra = [ + (b"x-content-type-options", b"nosniff"), + (b"x-frame-options", b"DENY"), + (b"referrer-policy", b"strict-origin-when-cross-origin"), + ] + message["headers"] = list(message["headers"]) + extra + await send(message) + + await self.app(scope, receive, send_with_headers) + + api.add_middleware(SecurityHeadersMiddleware) + +This is the same pattern used internally by Starlette and uvicorn. The +middleware receives the ASGI ``scope``, ``receive``, and ``send`` callables, +and wraps ``send`` to inject headers into the response. + +For most cases, ``BaseHTTPMiddleware`` is simpler and perfectly fine. +Use the pure ASGI approach when you need to handle WebSocket connections, +streaming responses, or want to avoid the overhead of request/response +object creation. + + When to Use What ----------------- diff --git a/api.html b/api.html index 7cdf388..92c476f 100644 --- a/api.html +++ b/api.html @@ -49,6 +49,20 @@ and explanations, see the <

The central object of every Responder application. It holds your routes, middleware, templates, and configuration. Create one at the top of your module and use it to define your entire web service.

+

Quick example:

+
import responder
+
+api = responder.API(
+    title="My Service",           # OpenAPI title
+    version="1.0",                # OpenAPI version
+    openapi="3.0.2",              # enable OpenAPI
+    docs_route="/docs",           # Swagger UI at /docs
+    cors=True,                    # enable CORS
+    secret_key="change-me",       # session signing key
+    allowed_hosts=["example.com"],
+)
+
+
class responder.API(*, debug=False, title=None, version=None, description=None, terms_of_service=None, contact=None, license=None, openapi=None, openapi_route='/schema.yml', static_dir='static', static_route='/static', templates_dir='templates', auto_escape=True, secret_key='NOTASECRET', enable_hsts=False, docs_route=None, cors=False, cors_params={'allow_credentials': False, 'allow_headers': (), 'allow_methods': ('GET',), 'allow_origin_regex': None, 'allow_origins': (), 'expose_headers': (), 'max_age': 600}, allowed_hosts=None, openapi_theme='swagger_ui', lifespan=None, request_id=False)[source]
@@ -418,6 +432,27 @@ gives you access to everything the client sent — headers, query parameters, the request body, cookies, and more.

Most properties are synchronous, but reading the body requires await because it involves I/O.

+

Common patterns:

+
# Headers (case-insensitive)
+token = req.headers.get("Authorization")
+
+# Query parameters: /search?q=python&page=2
+query = req.params["q"]
+
+# JSON body
+data = await req.media()
+
+# Form data
+form = await req.media("form")
+
+# File uploads
+files = await req.media("files")
+
+# Client info
+ip, port = req.client
+is_https = req.is_secure
+
+
class responder.Request(scope, receive, api=None, formats=None)[source]
@@ -558,6 +593,19 @@ actual route handler.

The response object is passed into every view as the second argument. Mutate it to control what gets sent back to the client — the body, status code, headers, and cookies.

+

Common patterns:

+
resp.text = "plain text"            # text/plain
+resp.html = "<h1>Hello</h1>"        # text/html
+resp.media = {"key": "value"}       # application/json
+resp.content = b"raw bytes"         # application/octet-stream
+resp.file("path/to/file.pdf")       # auto content-type
+resp.stream_file("large/export.csv") # streamed
+
+resp.status_code = 201
+resp.headers["X-Custom"] = "value"
+resp.cookies["session"] = "abc123"
+
+
class responder.Response(req, *, formats)[source]
@@ -707,7 +755,14 @@ as they are produced, without buffering the full response in memory.

Route Groups

Group related routes under a shared URL prefix — useful for API versioning -and organizing large applications.

+and organizing large applications:

+
v1 = api.group("/v1")
+
+@v1.route("/users")
+def list_users(req, resp):
+    resp.media = []
+
+
class responder.api.RouteGroup(api, prefix)[source]
@@ -718,7 +773,20 @@ and organizing large applications.

Background Queue

Run tasks in background threads without blocking the response. Available -as api.background.

+as api.background:

+
@api.route("/submit")
+async def submit(req, resp):
+    data = await req.media()
+
+    @api.background.task
+    def process(data):
+        # runs in a thread pool
+        ...
+
+    process(data)
+    resp.media = {"status": "accepted"}
+
+
class responder.background.BackgroundQueue(n=None)[source]
@@ -772,7 +840,9 @@ Exceptions are printed to stderr via traceback.

Query Dict

-

A dictionary subclass for query string parameters with multi-value support.

+

A dictionary subclass for query string parameters with multi-value support. +Behaves like a normal dict for single values, but supports getlist() +for parameters that appear multiple times (e.g. ?tag=a&tag=b).

class responder.models.QueryDict(query_string)[source]
@@ -812,7 +882,15 @@ associated with the key.

Rate Limiter

In-memory token bucket rate limiter. Limits requests per client IP address -and returns 429 Too Many Requests when exceeded.

+and returns 429 Too Many Requests when exceeded:

+
from responder.ext.ratelimit import RateLimiter
+
+limiter = RateLimiter(requests=100, period=60)  # 100 req/min
+limiter.install(api)
+
+
+

Response headers: X-RateLimit-Limit, X-RateLimit-Remaining, +and Retry-After (when limited).

class responder.ext.ratelimit.RateLimiter(requests=100, period=60)[source]
@@ -850,7 +928,15 @@ and returns 429

Status Code Helpers

Convenience functions for checking which category a status code falls -into. Useful in middleware and after-request hooks.

+into. Useful in middleware and after-request hooks:

+
from responder.status_codes import is_200, is_400, is_500
+
+@api.after_request()
+def log_errors(req, resp):
+    if is_400(resp.status_code) or is_500(resp.status_code):
+        print(f"Error: {req.method} {req.url.path} -> {resp.status_code}")
+
+
responder.status_codes.is_100(status_code)[source]
diff --git a/backlog.html b/backlog.html index affdd9d..646eef9 100644 --- a/backlog.html +++ b/backlog.html @@ -44,10 +44,11 @@

Future Ideas

    -
  • Consider adding after_request hooks (complement to before_request)

  • -
  • Explore WebSocket before_request short-circuit support

  • -
  • Add rate limiting middleware

  • -
  • Consider async template rendering by default

  • +
  • WebSocket before_request short-circuit support (reject before accept)

  • +
  • Per-route rate limiting (different limits for different endpoints)

  • +
  • Built-in structured logging with request context

  • +
  • OpenAPI 3.1 support

  • +
  • HTTP/2 server push

diff --git a/cli.html b/cli.html index 6703801..b14704b 100644 --- a/cli.html +++ b/cli.html @@ -104,6 +104,23 @@ $ responder run myapp.py:application
+
+

Environment Variables

+

Responder automatically reads the PORT environment variable at +runtime:

+
    +
  • PORT — bind to 0.0.0.0 on this port (cloud platform convention)

  • +
+

When PORT is set, the server binds to all interfaces automatically. +This is how cloud platforms like Fly.io, Railway, and Heroku inject the +listen port.

+

For other settings like SECRET_KEY, read them in your application +code and pass them to responder.API():

+
import os
+api = responder.API(secret_key=os.environ["SECRET_KEY"])
+
+
+

Building Frontend Assets

If your project includes a JavaScript frontend with a package.json, @@ -145,6 +162,7 @@ $ responder build /path/to/frontend

  • Launching from a File
  • Launching from a URL
  • Custom Instance Names
  • +
  • Environment Variables
  • Building Frontend Assets
  • diff --git a/deployment.html b/deployment.html index 15acddd..ab84d3d 100644 --- a/deployment.html +++ b/deployment.html @@ -99,6 +99,25 @@ the convention that virtually every cloud platform uses.

    The pattern is always the same: deploy your code, set the start command to python api.py, and the platform handles the rest.

    +
    +

    Health Check Endpoint

    +

    Every production deployment needs a health check — a lightweight endpoint +that monitoring tools, load balancers, and orchestrators can poll to verify +your service is running:

    +
    @api.route("/health")
    +def health(req, resp):
    +    resp.media = {"status": "healthy"}
    +
    +
    +

    Keep it simple. Don’t query the database or do expensive work — the health +check should return instantly. Cloud platforms, Docker, and Kubernetes all +look for an HTTP 200 to confirm your service is alive.

    +

    For Docker, add a HEALTHCHECK instruction:

    +
    HEALTHCHECK --interval=30s --timeout=3s \
    +    CMD curl -f http://localhost/health || exit 1
    +
    +
    +

    Uvicorn Directly

    For production deployments where you want more control, bypass @@ -111,6 +130,43 @@ independently. A good starting point is 2-4 workers per CPU core.

    Uvicorn supports many options — SSL certificates, access logging, graceful shutdown timeouts, and more. See the uvicorn documentation for details.

    +

    For platforms like Heroku or Railway that use a Procfile:

    +
    web: uvicorn api:api --host 0.0.0.0 --port $PORT --workers 4
    +
    +
    +
    +
    +

    Docker Compose

    +

    For local development with databases and other services, Docker Compose +ties everything together:

    +
    # docker-compose.yml
    +services:
    +  api:
    +    build: .
    +    ports:
    +      - "5042:80"
    +    environment:
    +      - PORT=80
    +      - DATABASE_URL=postgresql+asyncpg://user:pass@db/myapp
    +      - SECRET_KEY=dev-secret
    +    depends_on:
    +      - db
    +
    +  db:
    +    image: docker.io/postgres:16-alpine
    +    environment:
    +      POSTGRES_USER: user
    +      POSTGRES_PASSWORD: pass
    +      POSTGRES_DB: myapp
    +    volumes:
    +      - pgdata:/var/lib/postgresql/data
    +
    +volumes:
    +  pgdata:
    +
    +
    +

    Run with docker compose up. The API waits for db to start, then +connects using the DATABASE_URL environment variable.

    Reverse Proxy

    @@ -123,12 +179,33 @@ front of your application for:

  • Static asset serving — offload static files to the proxy

  • Rate limiting — at the infrastructure level

  • +

    A minimal Caddy config that handles HTTPS automatically:

    +
    # Caddyfile
    +example.com {
    +    reverse_proxy localhost:5042
    +}
    +
    +

    Responder’s TrustedHostMiddleware and HTTPSRedirectMiddleware work correctly behind proxies that set standard forwarding headers (X-Forwarded-For, X-Forwarded-Proto).

    That said, uvicorn is production-ready on its own. Many applications run uvicorn directly without a reverse proxy and do just fine.

    +
    +

    Production Checklist

    +

    Before going live:

    +
      +
    • Set a secret keySECRET_KEY env var, never the default

    • +
    • Disable debug modeDEBUG=false or omit it entirely

    • +
    • Set allowed hosts — restrict to your actual domain names

    • +
    • Use multiple workers--workers 4 or more, depending on CPU cores

    • +
    • Add a health check/health endpoint for monitoring

    • +
    • Enable HTTPS — via your proxy, cloud platform, or uvicorn’s --ssl-* flags

    • +
    • Set up logging — uvicorn logs requests by default; pipe them to your log aggregator

    • +
    • Pin your dependencies — commit uv.lock for reproducible deploys

    • +
    +
    @@ -160,8 +237,11 @@ uvicorn directly without a reverse proxy and do just fine.

  • Running Locally
  • Docker
  • Cloud Platforms
  • +
  • Health Check Endpoint
  • Uvicorn Directly
  • +
  • Docker Compose
  • Reverse Proxy
  • +
  • Production Checklist
  • diff --git a/index.html b/index.html index c9cc951..e61e9fd 100644 --- a/index.html +++ b/index.html @@ -89,21 +89,25 @@ work with — welcome.

    What You Get

    One pip install, batteries included:

      +
    • Pydantic request validation and response serialization.

    • Mount Flask, Django, or any WSGI/ASGI app at a subroute.

    • Gzip compression, HSTS, CORS, and trusted host validation.

    • -
    • Before-request hooks that can short-circuit for auth guards.

    • +
    • Before-request and after-request hooks for auth and logging.

    • A test client for fast, in-process testing with pytest.

    • Route parameters with f-string syntax and type convertors.

    • Lifespan context managers for startup and shutdown logic.

    • Custom exception handlers for clean error responses.

    • GraphQL with Graphene and a built-in GraphiQL IDE.

    • +
    • Server-Sent Events for real-time streaming.

    • File serving with automatic content-type detection.

    • Sync and async views — async is always optional.

    • Class-based views with on_get, on_post, on_request.

    • +
    • Built-in rate limiting with X-RateLimit headers.

    • +
    • Content negotiation: JSON, YAML, and MessagePack.

    • A pleasant API with a single import statement.

    • OpenAPI schema generation with Swagger UI.

    • A production uvicorn server, ready to deploy.

    • -
    • HTTP method filtering for REST APIs.

    • +
    • Route groups for API versioning.

    • Signed cookie-based sessions.

    • Background tasks in a thread pool.

    • WebSocket support.

    • @@ -152,6 +156,8 @@ work with — welcome.

    • Trusted Hosts
    • Request ID
    • Rate Limiting
    • +
    • Pydantic Validation
    • +
    • Content Negotiation
    • MessagePack
    @@ -159,8 +165,11 @@ work with — welcome.

  • Running Locally
  • Docker
  • Cloud Platforms
  • +
  • Health Check Endpoint
  • Uvicorn Directly
  • +
  • Docker Compose
  • Reverse Proxy
  • +
  • Production Checklist
  • Testing
  • @@ -193,6 +204,7 @@ work with — welcome.

  • Launching from a File
  • Launching from a URL
  • Custom Instance Names
  • +
  • Environment Variables
  • Building Frontend Assets
  • @@ -251,6 +263,7 @@ work with — welcome.

  • Built-in Middleware
  • Adding Third-Party Middleware
  • Middleware Order
  • +
  • Writing Pure ASGI Middleware
  • When to Use What
  • diff --git a/searchindex.js b/searchindex.js index 61a1de7..751d86a 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles":{"API Key Authentication":[[11,"api-key-authentication"]],"API Reference":[[0,null]],"Added":[[2,"added"],[2,"id2"],[2,"id4"],[2,"id7"],[2,"id11"],[2,"id17"],[2,"id18"],[2,"id21"],[2,"id24"],[2,"id29"],[2,"id36"],[2,"id42"],[2,"id43"],[2,"id44"],[2,"id45"],[2,"id46"],[2,"id49"],[2,"id50"],[2,"id52"],[2,"id55"],[2,"id58"],[2,"id59"],[2,"id60"],[2,"id64"]],"Adding Third-Party Middleware":[[13,"adding-third-party-middleware"]],"After-Request Hooks":[[10,"after-request-hooks"]],"Allowed Hosts":[[5,"allowed-hosts"]],"Authentication":[[11,null]],"Background Queue":[[0,"background-queue"]],"Background Tasks":[[7,"background-tasks"]],"Backlog":[[1,null]],"Bearer Token Authentication":[[11,"bearer-token-authentication"]],"Before-Request Hooks":[[10,"before-request-hooks"]],"Before-Request Hooks for WebSockets":[[16,"before-request-hooks-for-websockets"]],"Blueprints \u2192 Route Groups":[[12,"blueprints-route-groups"]],"Building Frontend Assets":[[3,"building-frontend-assets"]],"Building a REST API":[[14,null]],"Built-in Middleware":[[13,"built-in-middleware"]],"CORS":[[10,"cors"]],"CRUD Endpoints":[[15,"crud-endpoints"]],"Changed":[[2,"changed"],[2,"id1"],[2,"id3"],[2,"id5"],[2,"id8"],[2,"id16"],[2,"id19"],[2,"id22"],[2,"id25"],[2,"id28"],[2,"id33"],[2,"id34"],[2,"id35"],[2,"id37"],[2,"id38"],[2,"id40"],[2,"id41"],[2,"id47"],[2,"id51"],[2,"id56"],[2,"id57"],[2,"id63"]],"Changelog":[[2,null]],"Chat Room":[[16,"chat-room"]],"Class-Based Views":[[10,"class-based-views"]],"Cloud Platforms":[[4,"cloud-platforms"]],"Command Line Interface":[[3,null]],"Configuration":[[5,null]],"Configuration Class Pattern":[[5,"configuration-class-pattern"]],"Cookie-Based Sessions":[[10,"cookie-based-sessions"]],"Cookies":[[10,"cookies"]],"Create a Book":[[14,"create-a-book"]],"Create a Web Service":[[7,"create-a-web-service"]],"Custom Error Handling":[[10,"custom-error-handling"]],"Custom Exception for Auth Errors":[[11,"custom-exception-for-auth-errors"]],"Custom Instance Names":[[3,"custom-instance-names"]],"Data Formats":[[16,"data-formats"]],"Database Setup":[[15,"database-setup"]],"Debug Mode":[[5,"debug-mode"]],"Define Your Models":[[14,"define-your-models"],[15,"define-your-models"]],"Delete a Book":[[14,"delete-a-book"]],"Deployment":[[4,null]],"Deprecated":[[2,"deprecated"]],"Development Sandbox":[[8,null]],"Docker":[[4,"docker"]],"Echo Server":[[16,"echo-server"]],"Environment Variables":[[5,"environment-variables"]],"Error Handling":[[14,"error-handling"]],"Feature Tour":[[10,null]],"Fixed":[[2,"fixed"],[2,"id6"],[2,"id10"],[2,"id12"],[2,"id13"],[2,"id14"],[2,"id15"],[2,"id20"],[2,"id23"],[2,"id26"],[2,"id27"],[2,"id30"],[2,"id31"],[2,"id32"],[2,"id39"],[2,"id48"],[2,"id53"],[2,"id54"],[2,"id61"],[2,"id62"]],"Future Ideas":[[1,"future-ideas"]],"Get a Single Book":[[14,"get-a-single-book"]],"Getting Started":[[9,"getting-started"]],"Gradual Migration":[[12,"gradual-migration"]],"GraphQL":[[10,"graphql"]],"HSTS":[[10,"hsts"]],"HTML Client":[[16,"html-client"]],"Hello World":[[7,"hello-world"]],"Hooks vs. Middleware":[[13,"hooks-vs-middleware"]],"How WebSockets Work":[[16,"how-websockets-work"]],"In-Memory Storage":[[14,"in-memory-storage"]],"Installation":[[6,"installation"],[15,"installation"]],"JSON APIs":[[12,"json-apis"]],"Launching from a File":[[3,"launching-from-a-file"]],"Launching from a Module":[[3,"launching-from-a-module"]],"Launching from a URL":[[3,"launching-from-a-url"]],"Lifespan Events":[[10,"lifespan-events"]],"Lifespan for Startup and Shutdown":[[15,"lifespan-for-startup-and-shutdown"]],"List All Books":[[14,"list-all-books"]],"MessagePack":[[10,"messagepack"]],"Method Filtering":[[10,"method-filtering"]],"Middleware Order":[[13,"middleware-order"]],"Migrating from Flask":[[12,null]],"Mounting Other Apps":[[10,"mounting-other-apps"]],"OpenAPI Documentation":[[10,"openapi-documentation"]],"Operations":[[8,"operations"]],"Project":[[6,null]],"Project Setup":[[14,"project-setup"]],"Putting It All Together":[[5,"putting-it-all-together"],[7,"putting-it-all-together"]],"Query Dict":[[0,"query-dict"]],"Quick Reference":[[12,"quick-reference"]],"Quick Start":[[7,null]],"Rate Limiter":[[0,"rate-limiter"]],"Rate Limiting":[[10,"rate-limiting"]],"Reading Requests":[[7,"reading-requests"]],"Removed":[[2,"removed"],[2,"id9"]],"Rendering Templates":[[7,"rendering-templates"]],"Request":[[0,"request"]],"Request ID":[[10,"request-id"]],"Responder":[[6,null]],"Response":[[0,"response"]],"Reverse Proxy":[[4,"reverse-proxy"]],"Route Groups":[[0,"route-groups"],[10,"route-groups"]],"Route Parameters":[[7,"route-parameters"],[12,"route-parameters"]],"Run It":[[14,"run-it"],[15,"run-it"]],"Run the Server":[[7,"run-the-server"]],"Running Locally":[[4,"running-locally"]],"Secret Key":[[5,"secret-key"]],"Sending Responses":[[7,"sending-responses"]],"Server-Sent Events (SSE)":[[10,"server-sent-events-sse"]],"Serving Files":[[10,"serving-files"]],"Setup":[[8,"setup"]],"Skipping Auth for Public Routes":[[11,"skipping-auth-for-public-routes"]],"Static Files":[[10,"static-files"]],"Status Code Helpers":[[0,"status-code-helpers"]],"Templates":[[12,"templates"]],"Testing":[[9,null]],"Testing Before and After Hooks":[[9,"testing-before-and-after-hooks"]],"Testing Error Handling":[[9,"testing-error-handling"]],"Testing File Uploads":[[9,"testing-file-uploads"]],"Testing Headers and Cookies":[[9,"testing-headers-and-cookies"]],"Testing JSON APIs":[[9,"testing-json-apis"]],"Testing Lifespan Events":[[9,"testing-lifespan-events"]],"Testing Request Validation":[[9,"testing-request-validation"]],"Testing WebSockets":[[9,"testing-websockets"],[16,"testing-websockets"]],"The API Class":[[0,"the-api-class"]],"The Big Differences":[[12,"the-big-differences"]],"The Idea":[[6,"the-idea"]],"Tips":[[9,"tips"],[15,"tips"]],"Trusted Hosts":[[10,"trusted-hosts"]],"Try It Out":[[14,"try-it-out"]],"Tutorials":[[6,null]],"Type Convertors":[[7,"type-convertors"]],"Unreleased":[[2,"unreleased"]],"Update a Book":[[14,"update-a-book"]],"User Guide":[[6,null]],"Using .env Files":[[5,"using-env-files"]],"Using Fixtures":[[9,"using-fixtures"]],"Using PostgreSQL":[[15,"using-postgresql"]],"Using SQLAlchemy":[[15,null]],"Using Sessions for Web Apps":[[11,"using-sessions-for-web-apps"]],"Using Starlette Middleware":[[13,"using-starlette-middleware"]],"Uvicorn Directly":[[4,"uvicorn-directly"]],"WebSocket Support":[[10,"websocket-support"]],"WebSocket Tutorial":[[16,null]],"What You Get":[[6,"what-you-get"]],"What\u2019s Next":[[14,"what-s-next"]],"When to Use What":[[13,"when-to-use-what"]],"Writing Middleware":[[13,null]],"v0.0.1 - 2018-10-12":[[2,"v0-0-1-2018-10-12"]],"v0.0.10 - 2018-10-17":[[2,"v0-0-10-2018-10-17"]],"v0.0.2 - 2018-10-13":[[2,"v0-0-2-2018-10-13"]],"v0.0.3 - 2018-10-13":[[2,"v0-0-3-2018-10-13"]],"v0.0.4 - 2018-10-15":[[2,"v0-0-4-2018-10-15"]],"v0.0.5 - 2018-10-15":[[2,"v0-0-5-2018-10-15"]],"v0.0.6 - 2018-10-16":[[2,"v0-0-6-2018-10-16"]],"v0.0.7 - 2018-10-16":[[2,"v0-0-7-2018-10-16"]],"v0.0.8 - 2018-10-17":[[2,"v0-0-8-2018-10-17"]],"v0.0.9 - 2018-10-17":[[2,"v0-0-9-2018-10-17"]],"v0.1.0 - 2018-10-17":[[2,"v0-1-0-2018-10-17"]],"v0.1.1 - 2018-10-17":[[2,"v0-1-1-2018-10-17"]],"v0.1.2 - 2018-10-18":[[2,"v0-1-2-2018-10-18"]],"v0.1.3 - 2018-10-18":[[2,"v0-1-3-2018-10-18"]],"v0.1.4 - 2018-10-19":[[2,"v0-1-4-2018-10-19"]],"v0.1.5 - 2018-10-20":[[2,"v0-1-5-2018-10-20"]],"v0.1.6 - 2018-10-20":[[2,"v0-1-6-2018-10-20"]],"v0.2.0 - 2018-10-22":[[2,"v0-2-0-2018-10-22"]],"v0.2.1 - 2018-10-23":[[2,"v0-2-1-2018-10-23"]],"v0.2.2 - 2018-10-23":[[2,"v0-2-2-2018-10-23"]],"v0.2.3 - 2018-10-24":[[2,"v0-2-3-2018-10-24"]],"v0.3.0 - 2018-10-24":[[2,"v0-3-0-2018-10-24"]],"v0.3.1 - 2018-10-24":[[2,"v0-3-1-2018-10-24"]],"v0.3.2 - 2018-10-25":[[2,"v0-3-2-2018-10-25"]],"v0.3.3 - 2018-10-25":[[2,"v0-3-3-2018-10-25"]],"v1.0.0 - 2018-10-26":[[2,"v1-0-0-2018-10-26"]],"v1.0.1 - 2018-10-26":[[2,"v1-0-1-2018-10-26"]],"v1.0.2 - 2018-10-27":[[2,"v1-0-2-2018-10-27"]],"v1.0.3 - 2018-10-27":[[2,"v1-0-3-2018-10-27"]],"v1.0.4 - 2018-10-27":[[2,"v1-0-4-2018-10-27"]],"v1.0.5- 2018-10-27":[[2,"v1-0-5-2018-10-27"]],"v1.1.0 - 2018-10-27":[[2,"v1-1-0-2018-10-27"]],"v1.1.1 - 2018-10-29":[[2,"v1-1-1-2018-10-29"]],"v1.1.2 - 2018-11-11":[[2,"v1-1-2-2018-11-11"]],"v1.1.3 - 2019-01-12":[[2,"v1-1-3-2019-01-12"]],"v1.2.0 - 2018-12-29":[[2,"v1-2-0-2018-12-29"]],"v1.3.0 - 2019-02-22":[[2,"v1-3-0-2019-02-22"]],"v1.3.1 - 2019-04-28":[[2,"v1-3-1-2019-04-28"]],"v1.3.2 - 2019-08-15":[[2,"v1-3-2-2019-08-15"]],"v2.0.0 - 2019-09-19":[[2,"v2-0-0-2019-09-19"]],"v2.0.1 - 2019-09-20":[[2,"v2-0-1-2019-09-20"]],"v2.0.2 - 2019-09-20":[[2,"v2-0-2-2019-09-20"]],"v2.0.3 - 2019-09-20":[[2,"v2-0-3-2019-09-20"]],"v2.0.4 - 2019-11-19":[[2,"v2-0-4-2019-11-19"]],"v2.0.5 - 2019-12-15":[[2,"v2-0-5-2019-12-15"]],"v3.0.0 - 2026-03-22":[[2,"v3-0-0-2026-03-22"]],"v3.2.0 - 2026-03-22":[[2,"v3-2-0-2026-03-22"]],"v3.3.0 - 2026-03-22":[[2,"v3-3-0-2026-03-22"]],"v3.4.0 - 2026-03-22":[[2,"v3-4-0-2026-03-22"]],"v3.5.0 - 2026-03-24":[[2,"v3-5-0-2026-03-24"]]},"docnames":["api","backlog","changes","cli","deployment","guide-config","index","quickstart","sandbox","testing","tour","tutorial-auth","tutorial-flask","tutorial-middleware","tutorial-rest","tutorial-sqlalchemy","tutorial-websockets"],"envversion":{"sphinx":65,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.viewcode":1},"filenames":["api.rst","backlog.md","changes.md","cli.rst","deployment.rst","guide-config.rst","index.rst","quickstart.rst","sandbox.md","testing.rst","tour.rst","tutorial-auth.rst","tutorial-flask.rst","tutorial-middleware.rst","tutorial-rest.rst","tutorial-sqlalchemy.rst","tutorial-websockets.rst"],"indexentries":{"accepts() (responder.request method)":[[0,"responder.Request.accepts",false]],"add_event_handler() (responder.api method)":[[0,"responder.API.add_event_handler",false]],"add_middleware() (responder.api method)":[[0,"responder.API.add_middleware",false]],"add_route() (responder.api method)":[[0,"responder.API.add_route",false]],"after_request() (responder.api method)":[[0,"responder.API.after_request",false]],"api (class in responder)":[[0,"responder.API",false]],"apparent_encoding (responder.request property)":[[0,"responder.Request.apparent_encoding",false]],"backgroundqueue (class in responder.background)":[[0,"responder.background.BackgroundQueue",false]],"before_request() (responder.api method)":[[0,"responder.API.before_request",false]],"check() (responder.ext.ratelimit.ratelimiter method)":[[0,"responder.ext.ratelimit.RateLimiter.check",false]],"client (responder.request property)":[[0,"responder.Request.client",false]],"content (responder.request property)":[[0,"responder.Request.content",false]],"cookies (responder.request property)":[[0,"responder.Request.cookies",false]],"encoding (responder.request property)":[[0,"responder.Request.encoding",false]],"exception_handler() (responder.api method)":[[0,"responder.API.exception_handler",false]],"file() (responder.response method)":[[0,"responder.Response.file",false]],"full_url (responder.request property)":[[0,"responder.Request.full_url",false]],"get() (responder.models.querydict method)":[[0,"responder.models.QueryDict.get",false]],"get_list() (responder.models.querydict method)":[[0,"responder.models.QueryDict.get_list",false]],"graphql() (responder.api method)":[[0,"responder.API.graphql",false]],"group() (responder.api method)":[[0,"responder.API.group",false]],"headers (responder.request property)":[[0,"responder.Request.headers",false]],"install() (responder.ext.ratelimit.ratelimiter method)":[[0,"responder.ext.ratelimit.RateLimiter.install",false]],"is_100() (in module responder.status_codes)":[[0,"responder.status_codes.is_100",false]],"is_200() (in module responder.status_codes)":[[0,"responder.status_codes.is_200",false]],"is_300() (in module responder.status_codes)":[[0,"responder.status_codes.is_300",false]],"is_400() (in module responder.status_codes)":[[0,"responder.status_codes.is_400",false]],"is_500() (in module responder.status_codes)":[[0,"responder.status_codes.is_500",false]],"is_json (responder.request property)":[[0,"responder.Request.is_json",false]],"is_secure (responder.request property)":[[0,"responder.Request.is_secure",false]],"items() (responder.models.querydict method)":[[0,"responder.models.QueryDict.items",false]],"items_list() (responder.models.querydict method)":[[0,"responder.models.QueryDict.items_list",false]],"media() (responder.request method)":[[0,"responder.Request.media",false]],"method (responder.request property)":[[0,"responder.Request.method",false]],"mimetype (responder.request property)":[[0,"responder.Request.mimetype",false]],"module":[[0,"module-responder",false]],"mount() (responder.api method)":[[0,"responder.API.mount",false]],"ok (responder.response property)":[[0,"responder.Response.ok",false]],"on_event() (responder.api method)":[[0,"responder.API.on_event",false]],"params (responder.request property)":[[0,"responder.Request.params",false]],"path_matches_route() (responder.api method)":[[0,"responder.API.path_matches_route",false]],"path_params (responder.request property)":[[0,"responder.Request.path_params",false]],"querydict (class in responder.models)":[[0,"responder.models.QueryDict",false]],"ratelimiter (class in responder.ext.ratelimit)":[[0,"responder.ext.ratelimit.RateLimiter",false]],"redirect() (responder.api method)":[[0,"responder.API.redirect",false]],"redirect() (responder.response method)":[[0,"responder.Response.redirect",false]],"request (class in responder)":[[0,"responder.Request",false]],"requests (responder.api property)":[[0,"responder.API.requests",false]],"responder":[[0,"module-responder",false]],"response (class in responder)":[[0,"responder.Response",false]],"route() (responder.api method)":[[0,"responder.API.route",false]],"routegroup (class in responder.api)":[[0,"responder.api.RouteGroup",false]],"run() (responder.api method)":[[0,"responder.API.run",false]],"run() (responder.background.backgroundqueue method)":[[0,"responder.background.BackgroundQueue.run",false]],"schema() (responder.api method)":[[0,"responder.API.schema",false]],"serve() (responder.api method)":[[0,"responder.API.serve",false]],"session (responder.request property)":[[0,"responder.Request.session",false]],"session() (responder.api method)":[[0,"responder.API.session",false]],"set_cookie() (responder.response method)":[[0,"responder.Response.set_cookie",false]],"sse() (responder.response method)":[[0,"responder.Response.sse",false]],"state (responder.request property)":[[0,"responder.Request.state",false]],"static_app (responder.api property)":[[0,"responder.API.static_app",false]],"status_code_safe (responder.response property)":[[0,"responder.Response.status_code_safe",false]],"stream() (responder.response method)":[[0,"responder.Response.stream",false]],"stream_file() (responder.response method)":[[0,"responder.Response.stream_file",false]],"task() (responder.background.backgroundqueue method)":[[0,"responder.background.BackgroundQueue.task",false]],"template() (responder.api method)":[[0,"responder.API.template",false]],"template_string() (responder.api method)":[[0,"responder.API.template_string",false]],"text (responder.request property)":[[0,"responder.Request.text",false]],"url (responder.request property)":[[0,"responder.Request.url",false]],"url_for() (responder.api method)":[[0,"responder.API.url_for",false]]},"objects":{"":[[0,0,0,"-","responder"]],"responder":[[0,1,1,"","API"],[0,1,1,"","Request"],[0,1,1,"","Response"]],"responder.API":[[0,2,1,"","add_event_handler"],[0,2,1,"","add_middleware"],[0,2,1,"","add_route"],[0,2,1,"","after_request"],[0,2,1,"","before_request"],[0,2,1,"","exception_handler"],[0,2,1,"","graphql"],[0,2,1,"","group"],[0,2,1,"","mount"],[0,2,1,"","on_event"],[0,2,1,"","path_matches_route"],[0,2,1,"","redirect"],[0,3,1,"","requests"],[0,2,1,"","route"],[0,2,1,"","run"],[0,2,1,"","schema"],[0,2,1,"","serve"],[0,2,1,"","session"],[0,3,1,"","static_app"],[0,2,1,"","template"],[0,2,1,"","template_string"],[0,2,1,"","url_for"]],"responder.Request":[[0,2,1,"","accepts"],[0,3,1,"","apparent_encoding"],[0,3,1,"","client"],[0,3,1,"","content"],[0,3,1,"","cookies"],[0,3,1,"","encoding"],[0,3,1,"","full_url"],[0,3,1,"","headers"],[0,3,1,"","is_json"],[0,3,1,"","is_secure"],[0,2,1,"","media"],[0,3,1,"","method"],[0,3,1,"","mimetype"],[0,3,1,"","params"],[0,3,1,"","path_params"],[0,3,1,"","session"],[0,3,1,"","state"],[0,3,1,"","text"],[0,3,1,"","url"]],"responder.Response":[[0,2,1,"","file"],[0,3,1,"","ok"],[0,2,1,"","redirect"],[0,2,1,"","set_cookie"],[0,2,1,"","sse"],[0,3,1,"","status_code_safe"],[0,2,1,"","stream"],[0,2,1,"","stream_file"]],"responder.api":[[0,1,1,"","RouteGroup"]],"responder.background":[[0,1,1,"","BackgroundQueue"]],"responder.background.BackgroundQueue":[[0,2,1,"","run"],[0,2,1,"","task"]],"responder.ext.ratelimit":[[0,1,1,"","RateLimiter"]],"responder.ext.ratelimit.RateLimiter":[[0,2,1,"","check"],[0,2,1,"","install"]],"responder.models":[[0,1,1,"","QueryDict"]],"responder.models.QueryDict":[[0,2,1,"","get"],[0,2,1,"","get_list"],[0,2,1,"","items"],[0,2,1,"","items_list"]],"responder.status_codes":[[0,4,1,"","is_100"],[0,4,1,"","is_200"],[0,4,1,"","is_300"],[0,4,1,"","is_400"],[0,4,1,"","is_500"]]},"objnames":{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","property","Python property"],"4":["py","function","Python function"]},"objtypes":{"0":"py:module","1":"py:class","2":"py:method","3":"py:property","4":"py:function"},"terms":{"":[0,2,3,4,5,6,7,9,10,11,12,13,15,16],"0":[3,4,5,7,10,14,15],"00":0,"01":0,"0441172719":14,"1":[0,3,4,5,7,10,11,12,14,16],"10":[0,6,7,10],"100":[0,2,10],"127":[3,4,5],"13":4,"14":2,"150mb":4,"1965":14,"2":[4,7,9,10,14,15,16],"200":[0,7,9,10,14],"201":[7,9,12,14,15],"2026":0,"204":[14,15],"24":11,"2xx":0,"3":[4,6,7,9,10,14,16],"3000":5,"301":[0,7],"308":2,"32":5,"3600":[0,10],"3f":13,"4":[4,7],"40":2,"400":[0,2,9,10,14],"401":[0,10,11],"404":[0,7,12,14,15],"41d4":7,"422":[2,9,10,14],"429":[0,10],"446655440000":7,"500":[2,7,9,10,13,14],"5000":10,"5042":[3,4,7,11,14,16],"550e8400":7,"561":2,"60":[0,2,10],"600":[0,10],"7":11,"8":0,"80":4,"8000":[4,7],"8192":0,"9":9,"978":14,"99":9,"A":[0,4,5,6,7,10,13,16],"And":[5,6,7],"As":[0,10],"But":[7,9,10],"By":[3,7,9,10,13,14],"For":[0,3,4,5,7,9,10,11,14,15],"If":[0,3,5,6,7,9,10,12,15],"In":[0,5,6,7,10,11,12,15,16],"It":[0,3,6,9,10,13],"No":[6,9,10,12,14],"Not":7,"On":[5,10],"One":[6,7,9],"Or":[0,5],"That":[4,6,7,9],"The":[2,3,4,5,7,9,10,11,13,14,15,16],"There":[9,10],"These":7,"To":[14,15],"Will":0,"With":[0,5],"__init__":11,"__main__":[4,6,7,9,14,15],"__name__":[4,6,7,9,10,12,14,15],"__tablename__":15,"_route_for":2,"a2wsgi":2,"a716":7,"abc":14,"abc123":[0,9,10,11],"abil":2,"abl":0,"abort":12,"about":[4,7,9,12],"abov":[6,11],"abstract":15,"accept":[0,2,7,9,10,16],"access":[0,2,4,10,11,15],"acm":3,"acquir":8,"across":[2,4,10,15],"activ":[8,16],"actual":[0,7,10],"ad":[0,1,6,10],"adapt":10,"add":[0,1,2,5,7,11,13,14,15,16],"add_event_handl":0,"add_head":[10,13],"add_middlewar":[0,13],"add_request_id":0,"add_rout":[0,10],"add_tim":[9,10],"add_vers":9,"addeventlisten":16,"addit":[0,13],"address":[0,5,7,10],"adher":2,"admin":11,"affect":10,"after":[0,6,7,11,15,16],"after_request":[0,1,2,9,10,13],"ag":[0,10],"again":11,"against":[0,4,10,11],"agre":7,"ahead":2,"ai":10,"aiosqlit":15,"alemb":15,"algorithm":11,"alias":2,"alic":10,"all":[0,2,3,4,6,8,9,10,12,13,15,16],"alloc":9,"allow":[6,10],"allow_credenti":[0,10],"allow_head":[0,10],"allow_method":[0,5,10],"allow_origin":[0,5,10],"allow_origin_regex":0,"allowed_host":[0,5,10],"alongsid":10,"alpin":4,"alreadi":[0,9,10],"also":[0,2,3,7,9,10],"altern":[0,10],"alwai":[4,5,6,7,10],"an":[0,3,5,7,10,12,13,14,15,16],"analysi":10,"angle_bracket":12,"angular":10,"ani":[0,3,4,5,6,7,9,10,11,13,14,15,16],"annot":[2,6,7,10],"annual":[7,10],"answer":[10,16],"anyon":6,"anyth":7,"anywher":[4,10],"api":[2,3,4,5,6,7,10,13,15,16],"api_kei":11,"api_v1":12,"apispec":2,"app":[0,2,3,4,5,6,7,9,12,14,15,16],"appar":0,"apparent_encod":0,"appear":10,"appendchild":16,"appli":[0,13],"applic":[0,2,3,4,5,7,9,10,11,13,14,15],"approach":[5,10,11,12],"appropri":[10,15],"ar":[0,2,3,4,6,7,9,10,11,12,13,15,16],"architectur":10,"aren":[7,13],"arg":[0,12],"argument":[0,2,7,12,13],"around":[0,6],"arriv":[7,12],"asgi":[0,2,4,6,7,10,12,13],"ask":[6,10,16],"assert":[9,16],"asset":[0,4,6,10],"assign":14,"associ":0,"async":[0,1,2,4,6,7,9,10,11,12,13,14,15,16],"async_sess":15,"async_sessionmak":15,"asynccontextmanag":[10,15],"asynchron":[2,4],"asyncio":[2,15],"asyncpg":15,"attach":10,"attack":[4,5,10],"attribut":[0,3,15],"audio":16,"auth":[2,6,10,13],"auth_check":10,"auth_guard":11,"authent":[6,7,10,13,16],"autherror":11,"author":[0,7,8,10,11,13,14,15],"auto":[2,10,16],"auto_escap":0,"autobuild":8,"autoincr":15,"automat":[0,2,4,5,6,7,9,10,11,12,13,14,15],"avail":[0,7],"avoid":[9,10],"aw":4,"await":[0,2,7,9,10,11,12,13,14,15,16],"azur":[3,4],"b":[7,9,13,15,16],"back":[0,7,10,15,16],"background":[2,6],"backgroundqueu":0,"backlog":6,"bad":[9,10,14],"balanc":4,"bandwidth":10,"bar":10,"bare":2,"base":[0,2,6,11,13,15],"base_url":0,"basehttpmiddlewar":13,"basemodel":[0,9,10,14,15],"basic":7,"batteri":6,"battl":6,"bearer":6,"becaus":[0,6,7,11,12,14],"becom":[0,15],"been":0,"befor":[0,2,6,7,11,13,15],"before_request":[0,1,2,9,10,11,12,13,16],"begin":15,"behavior":[5,13],"behind":[4,10],"being":0,"best":6,"better":6,"between":13,"bidirect":[10,16],"big":6,"biggest":12,"bin":8,"binari":[7,10,16],"bind":[0,4,5,7],"blob":3,"block":[0,7,9,10,12,16],"blueprint":6,"bodi":[0,2,7,9,10,12,14,16],"boilerpl":6,"book":[6,15],"book_id":[14,15],"bookin":[14,15],"bookout":15,"books_db":14,"bool":5,"born":6,"both":[6,7,10,12,16],"bottom":14,"box":13,"bp":12,"break":[2,9],"bring":6,"broad":2,"broadcast":16,"broke":[7,9],"broker":7,"browser":[7,8,10,11,14,16],"bucket":[0,10],"buffer":[0,7],"bufix":2,"bug":[2,9],"bugfix":2,"build":[2,4,6,7,8,10,11,15,16],"builder":15,"built":[2,4,6,7,9,10,16],"bump":2,"bypass":4,"byte":[0,2,6,7,13,16],"c":[5,16],"cach":[7,9,10],"caddi":4,"call":[2,3,7,9,10,13,14,16],"call_next":13,"callabl":0,"came":7,"can":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"carri":7,"case":[0,6,7,13],"cat":10,"catalog":14,"catch":[10,11,13],"categori":0,"cd":8,"ceas":2,"celeri":7,"cell":10,"central":[0,7],"certain":0,"certif":4,"chang":[0,15],"changelog":6,"channel":[10,16],"chardet":0,"chat":[2,6,10],"check":[0,8,9,10,11,13,16],"check_api_kei":11,"check_auth":0,"check_exist":[0,10,14,15],"choic":[7,10],"choos":10,"chunk":[0,10],"chunk_siz":0,"ci":2,"circuit":[0,1,2,6,10],"class":[2,6,7,9,11,13,14,15],"clean":[6,10,14],"cleaner":[10,11],"cleanli":5,"cleanup":[2,10],"clear":11,"cli":2,"click":6,"client":[0,2,6,7,9,10,11,14],"clone":8,"close":[9,10,15,16],"close_database_connection_pool":0,"cloud":[3,5,6,7],"cmd":4,"code":[2,3,4,5,6,7,8,9,10,11,14,15,16],"codebas":2,"collabor":[10,16],"colon":3,"column":15,"com":[0,3,5,7,8,10],"combin":7,"come":[7,10,12],"command":[4,6],"commit":[5,15],"common":[3,4,5,7,10,11,12,13,14],"commonli":7,"commun":[10,11],"compact":10,"compat":[0,2],"complement":[1,10],"complet":[7,10,14,16],"complex":[13,15],"compon":13,"compos":15,"comprehens":2,"compress":[6,7,13],"compromis":5,"comput":7,"concept":[2,10,12],"concern":[7,13],"concurr":[0,4],"condit":[9,10],"config":[5,15],"configur":[0,2,4,6,7,9,10,13],"conflict":2,"confus":9,"conn":15,"connect":[0,4,7,9,10,15,16],"consid":[1,7,15],"consist":[7,10],"consol":[10,15],"const":[10,16],"constructor":[0,13],"consum":10,"contact":0,"contain":[0,4,7],"container":4,"content":[0,2,6,7,9,10,14],"content_typ":[0,9,10],"context":[2,6,9,10,15,16],"contextlib":[10,15],"continu":7,"contract":9,"control":[0,4,5,7,10,11,15],"conveni":[0,5,15],"convent":[4,14],"convert":[2,7],"convertor":[2,6,12],"cooki":[0,2,5,6,7,11,12,13],"copi":4,"cor":[0,2,5,6,9,13],"core":[2,4],"coroutin":0,"correctli":4,"correspond":15,"cors_en":5,"cors_origin":5,"cors_param":[0,5,10],"corsmiddlewar":13,"count":2,"cover":[5,11,13],"coverag":2,"cpu":[0,4,7],"crash":2,"creat":[0,6,8,9,10,11,12,15],"create_al":15,"create_asgi_app":10,"create_async_engin":15,"create_book":[14,15],"create_connect":16,"create_item":[0,10,12],"create_pet":10,"create_token":11,"createel":16,"creation":15,"credenti":11,"cross":[10,13],"crud":[6,7,14],"css":10,"csv":10,"curl":[3,7,11,14],"curly_brac":12,"custom":[0,2,6,7,9,14,16],"cut":13,"cycl":7,"d":[7,9,14],"dashboard":[5,10,11,16],"data":[0,2,5,6,7,9,10,11,12,14,15],"databas":[5,6,7,9,10,11,14],"database_url":[5,15],"date":0,"datetim":11,"db":[5,15],"debug":[0,2,6,10,12],"decim":7,"declar":[2,7],"declarativebas":15,"decod":[2,10,11],"decor":[0,2,7,10],"deep":6,"def":[0,6,7,9,10,11,12,13,14,15,16],"def456":11,"default":[0,1,2,3,5,7,9,10,15],"default_valu":[0,10],"defend":10,"defin":[0,6,7,10,11],"definit":0,"del":14,"delet":[5,6,7,10,15],"delete_book":[14,15],"deliber":7,"demo":3,"denpend":2,"dep":2,"depend":[2,4,9,13],"deploi":[4,6],"deploy":[2,6],"depth":10,"describ":10,"descript":[0,10],"design":[7,10,14],"detail":[4,5,10,14],"detect":[0,6,10],"dev":[2,5],"develop":[3,4,5,10,15],"devic":10,"dict":[6,7,10,11,14,15],"dictionari":0,"differ":[0,3,5,6,9,10,15],"digit":7,"direct":[0,2,10],"directli":[3,6,7,9,14,15],"directori":[0,7,10],"disabl":[9,15],"discard":16,"disconnect":16,"disk":[0,7,10],"dispatch":[2,10,13],"dispos":15,"distribut":[4,10],"div":16,"django":[6,10],"do":[4,5,7,10],"doc":[2,8,9,10,11,14],"docker":[5,6],"dockerfil":4,"docs_rout":[0,10,14],"docstr":[2,10],"doctyp":16,"document":[0,2,4,6,8,14,16],"doe":15,"doesn":[0,10,14,15],"domain":[0,5,10],"don":[5,7,9,10,11,12,15],"done":4,"dot":3,"dotenv":5,"doubl":14,"down":[10,15],"download":10,"dramat":2,"driver":15,"drop":[2,16],"dump":2,"dune":14,"duplex":10,"duplic":10,"durat":13,"dure":[3,4,9,15],"duti":14,"dynam":7,"e":[0,16],"e29b":7,"each":[0,4,9,10,15],"easi":[3,5,7],"echo":[6,7,15],"ecosystem":[6,7],"edit":8,"editor":[10,16],"effect":[9,14],"effici":4,"either":[0,16],"element":[0,10],"els":[7,10,11,12,15],"email":7,"emb":10,"empti":[0,14],"enabl":[2,10,13,14],"enable_async":7,"enable_hst":[0,10,13],"encod":[0,2,11],"encrypt":11,"end":[7,14],"endpoint":[0,2,6,9,10,11,12,14],"enforc":10,"engin":[7,15],"enough":[4,13],"ensur":[10,14,15,16],"enter":[9,16],"entir":[0,10,11,13,14],"entri":14,"env":[4,6],"environ":[0,3,4,6,7],"eol":2,"equival":12,"error":[0,2,5,6,15],"errorhandl":12,"escap":0,"essenti":10,"establish":16,"etc":[7,9,10],"even":[3,4,10,16],"event":[0,2,6,7,12,16],"event_typ":0,"eventsourc":10,"ever":[5,6],"everi":[0,4,5,6,7,9,10,11,13,14,15],"everyth":[0,2,4,7,10,12,14,15,16],"everywher":[3,5],"evolv":15,"exact":2,"exactli":[9,10],"exampl":[0,2,3,5,7,10,11],"exc":[0,9,10,11,14],"exceed":[0,10],"except":[0,2,6,9,10,13,16],"exception_cl":0,"exception_handl":[0,2,9,10,11,12,14],"exceptionmiddlewar":13,"execut":15,"exist":[0,2,6,12,13],"exit":[9,10,16],"exp":11,"expand":2,"expect":7,"expir":[0,10,11],"expire_on_commit":15,"explain":10,"explan":0,"explicit":[7,10,12],"explicitli":[10,12],"explor":[1,7,10],"export":[5,10],"expos":[4,5],"expose_head":0,"express":[6,7],"ext":[0,2,10,15],"extens":[2,7],"extern":7,"extra":[2,4,10],"extract":0,"extrem":7,"f":[0,6,7,9,10,11,13,14,16],"factori":15,"fail":[9,10,15],"failur":[2,9],"falcon":[6,10],"fall":0,"fals":[0,5,9,10,14,15],"familiar":[6,12],"fast":[4,6,7,9],"fastapi":6,"faster":10,"featur":[0,6,7],"feed":10,"feel":6,"fetch":3,"few":12,"fido":10,"field":[0,2,9,10,14],"figur":7,"file":[0,2,4,6,7,14,15,16],"filenam":[0,9],"filepath":7,"filesystem":[2,3],"fill":7,"filter":[6,7],"final":16,"find":[3,10,12],"fine":[4,10,15],"fire":[0,9],"first":[0,10,11,13,14,15],"fit":6,"fix":8,"fixtur":6,"flag":[4,10,15],"flask":[2,6,10],"flask_app":[10,12],"flatten":2,"float":[0,7,9],"flow":[11,13],"fly":4,"fmt":2,"follow":7,"font":10,"forg":[5,10],"forget":0,"form":[0,7,11,12],"format":[0,2,6,7,8,10,11],"formerli":10,"forward":[4,10],"found":[2,7,14,15],"foundat":10,"fragment":3,"framework":[6,10],"franca":7,"frank":14,"free":2,"freeli":16,"fresh":9,"from":[0,2,4,5,6,7,9,10,11,13,14,15,16],"from_attribut":15,"front":4,"frontend":[6,10],"fsspec":3,"full":[0,2,3,7,10],"full_url":[0,7,10],"fulli":7,"fun":6,"func":0,"function":[0,7,10,12,13],"futur":[0,2,6],"g":0,"game":[10,16],"gatewai":4,"gener":[0,2,5,6,9,10,13,14],"get":[0,2,5,7,10,11,15],"get_book":[14,15],"get_list":0,"get_m":11,"get_us":[0,10,12],"getelementbyid":16,"getenv":5,"git":[5,8],"github":[2,3,8],"gitignor":5,"give":[0,9,10,13,15],"given":[0,9],"global":[12,14],"gmt":0,"go":[7,12],"goe":[10,12],"good":[4,6,10],"googl":[3,4],"grace":4,"grade":7,"gradual":[6,10],"graduat":13,"grain":15,"graphen":[0,2,6,10],"graphiql":[2,6,10],"graphql":[0,2,6],"great":[3,6,10],"greet":[6,7,10],"greet_world":6,"greetingresourc":10,"group":[2,6],"grow":10,"guard":[6,11],"guid":[2,5,7,11,12,15],"guido":7,"gzip":[6,7],"gzipmiddlewar":13,"h":[7,11,14],"h1":[7,11],"ha":[7,9,12,14,16],"half":7,"halv":10,"hand":0,"handl":[0,2,4,5,6,7,11,16],"handle_auth_error":11,"handle_value_error":[0,10,14],"handler":[0,6,9,10,11,13,14],"handshak":16,"happen":[6,7],"hard":9,"hasn":0,"have":[0,2,3,7,9,12,13,14],"hdf":3,"head":3,"header":[0,2,4,5,6,7,10,11,12,13,16],"health":11,"heavi":7,"hello":[0,3,6,9,10,12,16],"hello_html":7,"hello_json":7,"hello_to":7,"hello_world":7,"helloworld":3,"help":[0,15],"helper":[6,11],"herbert":14,"here":[4,5,7,10,12,16],"high":[4,10],"hold":[0,6,7],"home":6,"homepag":2,"honor":[4,7],"hood":10,"hook":[0,1,2,6,7,11],"host":[0,2,4,6,7,13],"hostnam":10,"hour":[10,11],"how":[5,6,7,10,11,12,14,15],"hs256":11,"hst":6,"html":[0,2,6,7,10,11,12],"http":[0,2,3,4,5,6,7,8,9,10,11,14,16],"httponli":[0,10],"httpsredirect":0,"httpsredirectmiddlewar":[0,4,13],"httpx":[2,9],"i":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"id":[0,2,6,7,12,13,14,15,16],"idea":12,"idempot":14,"ident":12,"identifi":10,"imag":[4,7,10,16],"immedi":[0,6,7,10],"immut":2,"imperson":5,"implement":9,"import":[0,2,3,5,6,7,9,10,11,12,13,14,15,16],"improv":2,"inaccess":0,"includ":[3,4,6,7,8,9,10,11,14],"incom":[0,7,14],"incredibli":10,"independ":4,"index":[0,7,10,16],"individu":10,"industri":10,"info":[0,2,10],"inform":[0,14],"infrastructur":[4,6],"inherit":[0,10],"initi":[0,9],"inject":10,"innermost":13,"input":[2,9,10,14,16],"insensit":[0,6,7],"insid":13,"inspect":[0,2],"instal":[0,2,3,4,5,8,10,11,16],"instanc":[0,4,6,7,9],"instant":7,"instead":[0,7,9,10,13,14,15,16],"int":[0,2,7,10,11,12,14,15],"integ":[0,7,14,15],"integr":[13,14,15],"intens":7,"intent":6,"intention":10,"interact":[2,10,14],"interfac":[2,4,6,7,12],"intern":[9,10,13],"invalid":[5,9,10,11],"invalidtokenerror":11,"involv":0,"io":4,"iot":10,"ip":[0,7,10],"is_100":0,"is_200":0,"is_300":0,"is_400":0,"is_500":0,"is_class_bas":2,"is_json":[0,2,7],"is_secur":[0,7],"isbn":[14,15],"iscoroutinefunct":2,"isn":[7,10,12],"issu":[2,11],"item":[0,9,10,12,15],"itemin":0,"itemout":0,"items_list":0,"iter":16,"its":[0,2,4,14,15],"itself":11,"j":10,"jan":0,"javascript":[0,3,10],"jinja2":[0,7,12],"jpeg":10,"jpg":10,"json":[0,3,6,7,10,11,14,16],"jsonifi":12,"jump":7,"just":[4,9,10,13,15,16],"jwt":11,"keep":[2,5,7,9,10,13,15,16],"kei":[0,6,7,9,10,12,15,16],"kennethreitz":[3,8],"keypress":16,"keyword":[0,7,12,13],"know":[5,7],"known":[0,11],"kwarg":0,"languag":10,"larg":[0,2,10],"larger":[5,9,13],"last":[0,13],"later":[7,9],"launch":[4,6],"layer":13,"lazi":2,"lazili":0,"lead":9,"learn":10,"legaci":12,"less":10,"let":[3,4,7,10,14,15],"level":[4,13],"librari":[9,10,16],"licens":0,"lifecycl":16,"lifespan":[0,2,6,14],"lift":7,"lightn":4,"lightweight":7,"like":[4,7,9,10,11,13,14,16],"limit":[1,2,4,6,13,15,16],"line":[6,7],"liner":2,"lingua":7,"list":[0,6,7,9,10,15],"list_book":[14,15],"list_item":10,"list_pet":10,"list_us":[0,10,12],"list_users_v2":10,"live":[10,16],"ll":[6,7,10,12,14,15],"load":[0,2,3,4,5,7,10],"load_dotenv":5,"local":[3,5,6,12],"localhost":[5,7,11,14,15,16],"locat":[0,7,11,12],"log":[4,10,11,13],"log_level":2,"log_request":13,"log_respons":10,"logic":[6,7,10],"login":[10,11],"logout":11,"long":7,"look":[3,6,7],"loop":[7,12,16],"lose":[2,15],"lower":[0,5],"lowercas":7,"machin":10,"made":[0,6],"magic":12,"mai":4,"main":3,"make":[4,5,7,9,10,11,12],"malici":10,"manag":[2,5,6,9,10,11,13,15,16],"mani":[0,4,7,10],"manual":0,"map":[2,7,10,12,15],"mapper":15,"marimo":[2,10],"mark":[2,10],"marker":2,"marshmallow":[0,2,10],"match":[0,5,7,10,14],"matter":10,"max_ag":[0,10],"maximum":0,"me":11,"mean":[4,7,12],"mechan":10,"media":[0,2,6,7,9,10,11,12,14,15],"memori":[0,2,6,7,10],"messag":[0,7,10,11,16],"messagepack":[2,6],"metadata":[0,7,15],"method":[0,6,7,9,11,12,13,14,15,16],"microservic":10,"middelwar":0,"middlewar":[0,1,2,6,7,10],"middleware_cl":0,"middleware_config":0,"might":7,"migrat":[2,6,10,15],"mime":0,"mimetyp":[0,7,10],"min":[0,10],"mind":13,"minim":[4,16],"minimum":2,"minor":2,"miss":[2,9,10,11],"mix":10,"ml":10,"mode":[0,6,8],"model":[0,2,6,9,10],"model_dump":15,"model_valid":15,"modern":[4,10,11,12,15],"modifi":[0,10,13,14,15],"modul":[0,2,6,7,10],"more":[0,3,4,7,10,11,12,13,14,16],"most":[0,3,4,5,7,9,10,11,13,15],"mount":[0,2,6,12],"move":[2,7,10,12],"msgpack":[2,10],"much":[7,10],"multi":0,"multipart":[2,7],"multipl":[2,4,10,14],"multiplay":[10,16],"must":[0,7,10,11,14,16],"mutabl":6,"mutat":[0,7,12],"my_templ":7,"myapi":4,"myapp":3,"mydb":15,"mysql":15,"n":[0,7],"name":[0,5,6,7,9,10,12],"namespac":2,"narrow":2,"nativ":12,"natur":[9,15],"nearli":12,"need":[4,5,6,7,9,10,11,12,13,15,16],"negoti":[0,6,7,9,10],"nervou":7,"network":9,"never":[5,10,11,14],"new":[0,7,9,10,12,14,16],"new_endpoint":12,"next":[6,13],"next_id":14,"nginx":4,"non":7,"none":[0,2,11,14,15],"normal":[10,16],"notabl":2,"notasecret":0,"note":[7,10,12,14],"notebook":[2,10],"notic":7,"notif":10,"now":[2,7,10,11,15,16],"npm":3,"nullabl":15,"number":[0,7],"o":[0,5,7,12],"object":[0,2,7,10,12,13,15,16],"objecttyp":[0,10],"obviou":9,"off":[5,7],"offload":4,"offset":15,"often":[3,7,10],"ok":[0,7,9,14],"old":12,"on_delet":10,"on_ev":[0,9,10],"on_get":[6,10],"on_post":[6,10],"on_put":10,"on_request":[6,10],"on_startup":9,"onc":[10,12,14],"one":[0,2,5,6,7,10,12,15],"ones":[6,7,10],"onion":13,"onli":[0,5,7,10,12,14],"onmessag":[10,16],"open":[2,7,8,15],"open_database_connection_pool":0,"openapi":[0,2,6,14],"openapi_rout":0,"openapi_them":0,"oper":[7,10,12,14],"opt":10,"option":[0,2,4,6,7,13],"option1":13,"option2":13,"order":[0,6],"order_bi":15,"organ":[0,5,9,10,12],"origin":10,"orm":15,"other":[0,2,6,7,15],"otherwis":[0,10],"our":14,"out":[5,6,7,13],"outermost":13,"outgo":7,"output":14,"outsid":13,"over":[0,6,7,10,12,15],"overal":2,"overhead":9,"overrid":[0,10],"overwhelm":10,"own":[4,10,15],"p":[4,11,16],"pace":10,"packag":[2,3,4],"page":[0,2,5,7,10,11,16],"pagin":7,"painless":9,"pair":0,"param":[0,2,6,7,12],"paramet":[0,6,9,10,14],"parameter":0,"pars":[0,2,7,9,10],"parser":2,"part":[2,6,7,10],"parti":6,"pass":[0,7,9,12,13,15,16],"passion":6,"password":11,"patch":[7,10],"path":[0,2,3,6,7,9,10,11,13],"path_matches_rout":0,"path_param":[0,2,7],"pattern":[4,6,7,10,11,12,14,15],"payload":11,"pdf":[7,9,10],"pep":2,"per":[0,4,9,10],"perfect":10,"period":[0,2,10],"perman":7,"permit":10,"persist":[0,10,16],"person":6,"pet":[0,10],"petin":10,"petout":10,"petschema":[0,10],"photo":10,"piec":10,"pin":2,"pip":[2,3,4,5,6,8,11,15,16],"place":[5,10],"placehold":[7,16],"plain":[0,7,10,16],"platform":[2,5,6,7],"pleasant":6,"plot":10,"plu":15,"plugin":2,"poethepoet":2,"point":[3,4,14],"polici":10,"pool":[0,6,7,10,12,15],"popular":[7,10,15],"port":[0,4,5,7,9],"portion":0,"possibl":7,"post":[0,5,7,9,10,11,12,14,15],"postgresql":6,"potenti":2,"power":[6,9,10,13,15,16],"practic":10,"prefer":10,"prefix":[0,2,10],"present":7,"prevent":[5,10],"price":[0,9],"primari":0,"primary_kei":15,"print":[0,5,10,13,15,16],"privat":10,"proce":16,"process":[4,6,7,9,10,13],"process_data":7,"prod":5,"produc":[0,7],"product":[2,3,4,5,6,7,9,10,11,15],"profil":10,"programmat":10,"progress":10,"project":[2,3,8],"propag":9,"proper":[7,11,15],"properli":[2,5,9,15],"properti":[0,2,7,9],"prose":2,"protect":[4,11],"proto":4,"protocol":[3,7,9,10,16],"prototyp":[2,3,6],"provid":0,"proxi":6,"public":[0,6,10],"public_path":11,"push":[4,6,10],"put":[6,10,14,15],"py":[2,3,4,5,7,9,10,14,15],"pydant":[0,2,9,10,14,15],"pyjwt":11,"pypi":2,"pyproject":2,"pytest":[6,8,9],"python":[0,2,3,4,5,6,7,10,14,15,16],"pythonpath":3,"q":[7,12],"queri":[2,6,7,10,15,16],"query_str":0,"querydict":0,"queue":[6,7],"quick":[0,3,6],"r":[7,9],"race":9,"railwai":4,"rais":[0,2,9,10,11],"raise_server_except":9,"random":[0,5],"rang":[0,7,10],"rapidoc":[0,10],"rare":7,"rate":[1,2,4,6,13],"rate_limit":0,"ratelimit":[0,2,10,13],"rather":9,"raw":[0,3,6,7,10,13,15,16],"re":[0,4,7,9,10,12,13,14,16],"reach":[11,13],"react":[2,10],"reactiv":10,"read":[0,2,5,6,10,11,12,14,15],"readabl":10,"readi":[4,5,6,7],"real":[2,5,10,11,14,15],"realli":[9,10],"receiv":[0,6,7,9,10,11,13,16],"receive_byt":[10,16],"receive_incom":7,"receive_json":[10,16],"receive_text":[9,10,16],"recommend":10,"reconnect":10,"recv":16,"redirect":[0,2,7,11,12],"redoc":[0,10],"reduc":2,"ref":3,"refactor":[2,9],"refer":[2,6,9],"refresh":15,"refus":10,"regist":[0,9,10,11],"register_blueprint":12,"reject":[9,10],"relat":[0,10,15],"releas":8,"reliabl":9,"remain":10,"rememb":11,"remov":[10,12,14,16],"renam":9,"render":[0,1,4,6,10],"render_async":7,"render_templ":12,"replac":[2,7,10,14],"report":[7,9,10],"repres":0,"represent":0,"req":[0,2,6,7,9,10,11,12,13,14,15,16],"request":[2,3,4,6,11,12,13,14,15],"request_id":[0,2,10,13],"request_model":[0,2,9,10,14,15],"requir":[0,2,9,10],"research":6,"resolv":[2,10],"resolve_hello":[0,10],"resourc":[7,10,14],"resp":[0,2,6,7,9,10,11,12,13,14,15,16],"respect":3,"respond":[0,2,3,4,5,7,8,9,10,11,12,13,14,15,16],"respons":[2,6,9,10,12,13,14,15,16],"response_model":[0,2,10,14,15],"rest":[2,4,6,7,10],"restrict":10,"result":[0,2,7,10,15],"resum":2,"resume_incomplet":2,"retri":[0,10],"retriev":[0,10,14],"return":[0,2,6,7,9,10,11,12,13,14,15],"reusabl":11,"revers":[0,6],"rework":2,"rewrit":2,"rewrot":2,"rfc3986":2,"right":[6,7,10,12,13],"roll":15,"room":6,"root":[2,10],"rotat":5,"rout":[2,6,9,13,14,15,16],"routegroup":0,"router":2,"rst":2,"ruff":[2,8],"rule":5,"run":[0,2,3,6,8,9,10,12,13,16],"run_sync":15,"runner":[2,4],"runtimeerror":0,"s3":3,"safe":[2,14],"sai":7,"said":4,"same":[3,4,6,7,10,12,14,15],"sandbox":6,"save":[7,16],"scalar":15,"scale":6,"schema":[0,2,6,10,11,14,15],"scope":[0,10,13],"scratch":[6,14],"script":16,"search":[0,2,7,10],"second":0,"secret":[6,10,11],"secret_kei":[0,5,10,11],"section":10,"secur":[0,10,13],"see":[0,4,5,7,9,10,13,14,15],"select":[0,2,15],"self":[0,10,11,13],"semant":2,"send":[0,2,6,9,10,11,14,16],"send_byt":[10,16],"send_email":0,"send_json":[10,16],"send_text":[9,10,16],"sensit":11,"sent":[0,2,6,7,13],"separ":[7,9,14],"sequenti":2,"serial":[0,2,7,10,16],"serializ":7,"serv":[0,2,3,4,5,6,7,9,14,16],"server":[0,2,3,4,5,6,9,11,13,14,15],"servererrormiddlewar":13,"servestat":2,"servic":[0,3,6,9,10,14],"session":[0,2,5,6,7,9,12,13,15],"session_id":10,"sessionmiddlewar":13,"set":[0,2,4,5,6,7,8,9,10,11,15,16],"set_cooki":[0,2,10],"set_text":0,"setattr":15,"setup":[2,5,6,9],"sever":[10,13],"sftp":3,"share":[0,3,7,9,10,15],"shell":5,"short":[0,1,2,6,10],"shorthand":0,"should":[5,14,15],"shouldn":0,"show":[2,10,12,15,16],"shut":[10,15],"shutdown":[0,4,6,9,10],"shutdwown":2,"sibl":6,"side":[7,10,11,16],"sign":[0,5,6,7,10,11,13],"signatur":[7,10,12],"signup":11,"simpl":[3,9,10,11,13,14,16],"simplecooki":0,"simpler":[7,10,11,13],"simplest":[5,7,11,13,16],"simpli":11,"simplic":[6,15],"simul":7,"sinc":[7,9],"singl":[0,2,3,6,7,10,12,15],"sit":13,"size":[0,15],"sk":11,"skip":[0,6,10],"slash":7,"sleep":[7,9],"slim":4,"slow":7,"slowlori":4,"slug":7,"small":[4,6,9,10],"smaller":4,"so":[9,10,12,13,14,15],"solv":10,"some":[4,5,10],"some_packag":13,"somemiddlewar":13,"someon":[5,7,10,16],"someth":[6,7,9,10],"sometim":[7,10],"somewher":7,"sourc":[0,5,8,10],"spawn":4,"spec":[7,10],"special":[6,10],"specif":[0,2,5,9,10,13,14],"specifi":3,"sphinx":8,"spin":7,"split":5,"sprawl":6,"sql":15,"sqlalchemi":[2,6,7,14],"sqlite":[5,15],"sse":[0,2,6],"ssl":4,"stabil":2,"stack":13,"stai":[12,15],"standard":[3,4,10,11,14],"starlett":[0,2,6,9,16],"start":[0,3,4,6,10,13,14,15],"startswith":11,"startup":[0,2,6,9,10],"state":[0,2,9,10,11],"statement":6,"static":[0,2,4,6,7,16],"static_app":0,"static_dir":[0,10],"static_rout":[0,2,10],"staticfil":0,"statu":[2,6,7,9,10,14],"status_cod":[0,6,7,9,10,11,12,13,14,15],"status_code_saf":0,"stderr":0,"stdlib":2,"still":[10,12],"stop":10,"storag":[3,6],"store":[0,5,10,11,14],"str":[0,7,9,10,11,14,15],"straightforward":10,"stranger":[0,10],"stream":[0,2,10],"stream_data":0,"stream_fil":[0,2,10],"strict":10,"string":[0,6,7,10,15,16],"strip":[2,10,11],"structur":10,"style":10,"stylesheet":10,"sub":11,"subclass":0,"subcommand":3,"subject":0,"submiss":0,"submit":0,"subrout":[6,10,12],"subsequ":[10,11],"subtl":2,"success":[0,7,14],"successfulli":14,"successor":4,"suit":9,"suppli":2,"support":[0,1,2,3,4,6,7,12,15,16],"swagger":[6,10,14],"swagger_ui":[0,10],"switch":[2,15,16],"sync":[2,6,7,12],"synchron":[0,12],"syntax":[2,6,7,12],"system":[3,7,10],"t":[0,4,5,7,9,10,11,12,13,14,15],"tabl":15,"take":[6,7],"tamper":[10,11],"target":2,"task":[0,2,6],"teach":6,"tear":10,"tell":[7,10,14,15],"templat":[0,1,2,6],"template_str":[0,7],"templates_dir":0,"termin":[3,4],"terms_of_servic":0,"test":[0,2,3,5,6,8,14],"test_500":[2,9],"test_api":9,"test_create_item":9,"test_custom_error":9,"test_echo":16,"test_head":9,"test_hello":9,"test_hook":9,"test_json":9,"test_upload":9,"test_valid":9,"test_websocket":9,"test_with_lifespan":9,"testclient":[0,2,9,16],"text":[0,2,6,7,9,10,12,16],"textcont":16,"than":[9,10,11,12,13,14],"thei":[0,5,7,10,12,13,14,16],"them":[6,7,9,10,11,12,14,16],"theme":[0,10],"themselv":10,"thi":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"thing":[5,6,7,9,13],"think":7,"third":6,"though":4,"thousand":4,"thread":[0,2,6,7,12],"threadpoolexecutor":[0,2],"three":[7,10,16],"through":[0,7,10,13,14,16],"throughput":10,"thu":0,"time":[0,2,6,7,9,10,12,13,14,15,16],"time_start":0,"timedelta":11,"timeout":4,"timingmiddlewar":13,"tip":[2,6],"titl":[0,2,7,10,14,15],"tl":4,"togeth":[6,10],"token":[0,6,7,10,16],"token_hex":5,"toml":2,"too":[0,3,4,9,10],"tool":[8,13],"toolbelt":2,"toolkit":15,"top":[0,5],"total":10,"tour":[0,6,7],"trace":10,"traceback":[0,2,5,10],"track":15,"tradit":[10,11],"traffic":4,"transact":15,"transform":13,"translat":12,"transport":10,"treat":[0,10],"trick":10,"trigger":9,"true":[0,2,5,7,9,10,11,12,13,15,16],"trust":[2,6],"trustedhostmiddlewar":[4,13],"try":[6,7,11,16],"tupl":[0,7,9],"tutori":[2,7,14],"two":[7,10,13],"type":[0,2,6,10,12,14,16],"typic":[7,10],"typo":[2,10],"ui":[2,6,10,14],"unauthor":[0,10,11],"under":[0,7,10,12],"underlin":2,"understand":[6,7],"unexpectedli":16,"unhandl":13,"unicod":0,"union":2,"uniqu":10,"unit":15,"univers":5,"unknown":0,"unless":10,"unlik":10,"unmaintain":2,"unmatch":10,"unpin":2,"unrecogn":10,"until":7,"up":[0,2,7,8,10],"updat":[2,6,7,10,15,16],"update_book":[14,15],"upgrad":[2,8,10,16],"upload":[2,6,7],"url":[0,2,5,6,7,9,10,11,12,13,15],"url_for":[0,2,9],"url_prefix":12,"urllib":2,"us":[0,2,3,4,6,7,10,12,14,16],"usag":[0,2],"user":[0,5,7,10,11,12,15],"user_id":[7,10,11,12],"usernam":[10,11],"usual":9,"utcnow":11,"utf":0,"uuid":[0,2,7,10],"uuid4":0,"uv":[3,5,6,8,11,15],"uvicorn":[0,2,6,7],"uvloop":4,"v":6,"v1":[0,10],"v2":10,"valid":[0,2,6,7,10,11,13,14,15],"valu":[0,6,7,9,10,11,12,13,14,15,16],"valueerror":[0,9,10,12,14],"variabl":[0,4,6,7],"ve":[6,9,12],"venv":8,"verb":10,"veri":[0,7,15],"verifi":[9,11],"verify_token":11,"version":[0,2,9,10,14],"via":[0,2,5,10,12],"view":[0,2,6,7,9,12],"virtual":[3,4],"virtualenv":8,"visit":[10,14],"vue":10,"w":[9,10,16],"wa":[0,2,7,14],"wai":[3,4,6,7,10,11,12,13,15],"wait":12,"walk":[7,10,14],"want":[0,3,4,6,7,9,10,14,15,16],"warn":2,"watch":8,"we":[14,15,16],"web":[0,4,6,10,15],"websit":10,"websocket":[0,1,2,4,6],"websocket_connect":[9,16],"welcom":[6,7,11],"well":6,"went":6,"werkzeug":2,"what":[0,7,9,10,16],"whatev":7,"when":[0,2,4,5,6,7,9,10,12,14,15,16],"where":[0,4,7,10,15,16],"whether":[0,7],"which":[0,2,7,9,10,12,15],"whichev":6,"while":[7,10,12,16],"whitenois":2,"who":[6,7,11],"widget":[9,10],"wildcard":10,"window":2,"wire":7,"with_app":10,"within":[2,10,15],"without":[0,2,4,7,9,10,15],"won":[7,9,10,15],"work":[3,4,5,6,7,10,13,14,15],"workdir":4,"worker":4,"world":[0,3,6,9,10,12],"worri":9,"would":9,"wrap":[0,7,9,10,13],"write":[6,7,10,12],"wrong":10,"ws_auth":16,"wsgi":[0,2,4,6,10,12],"www":5,"x":[0,4,7,9,10,11,12,13,14],"x00":16,"x01":16,"x02":16,"x89png":7,"xml":0,"xss":10,"yaml":[0,2,6,7,9,10],"year":[14,15],"yield":[0,10,15],"yml":[0,10,11],"you":[0,3,4,5,7,9,10,11,12,13,14,15,16],"your":[0,3,4,5,6,7,9,10,11,12,13],"yourself":7,"zero":4},"titles":["API Reference","Backlog","Changelog","Command Line Interface","Deployment","Configuration","Responder","Quick Start","Development Sandbox","Testing","Feature Tour","Authentication","Migrating from Flask","Writing Middleware","Building a REST API","Using SQLAlchemy","WebSocket Tutorial"],"titleterms":{"":14,"0":2,"01":2,"02":2,"03":2,"04":2,"08":2,"09":2,"1":2,"10":2,"11":2,"12":2,"13":2,"15":2,"16":2,"17":2,"18":2,"19":2,"2":2,"20":2,"2018":2,"2019":2,"2026":2,"22":2,"23":2,"24":2,"25":2,"26":2,"27":2,"28":2,"29":2,"3":2,"4":2,"5":2,"6":2,"7":2,"8":2,"9":2,"In":14,"It":[5,7,14,15],"The":[0,6,12],"ad":[2,13],"after":[9,10],"all":[5,7,14],"allow":5,"api":[0,9,11,12,14],"app":[10,11],"asset":3,"auth":11,"authent":11,"background":[0,7],"backlog":1,"base":10,"bearer":11,"befor":[9,10,16],"big":12,"blueprint":12,"book":14,"build":[3,14],"built":13,"chang":2,"changelog":2,"chat":16,"class":[0,5,10],"client":16,"cloud":4,"code":0,"command":3,"configur":5,"convertor":7,"cooki":[9,10],"cor":10,"creat":[7,14],"crud":15,"custom":[3,10,11],"data":16,"databas":15,"debug":5,"defin":[14,15],"delet":14,"deploy":4,"deprec":2,"develop":8,"dict":0,"differ":12,"directli":4,"docker":4,"document":10,"echo":16,"endpoint":15,"env":5,"environ":5,"error":[9,10,11,14],"event":[9,10],"except":11,"featur":10,"file":[3,5,9,10],"filter":10,"fix":2,"fixtur":9,"flask":12,"format":16,"from":[3,12],"frontend":3,"futur":1,"get":[6,9,14],"gradual":12,"graphql":10,"group":[0,10,12],"guid":6,"handl":[9,10,14],"header":9,"hello":7,"helper":0,"hook":[9,10,13,16],"host":[5,10],"how":16,"hst":10,"html":16,"id":10,"idea":[1,6],"instal":[6,15],"instanc":3,"interfac":3,"json":[9,12],"kei":[5,11],"launch":3,"lifespan":[9,10,15],"limit":[0,10],"line":3,"list":14,"local":4,"memori":14,"messagepack":10,"method":10,"middlewar":13,"migrat":12,"mode":5,"model":[14,15],"modul":3,"mount":10,"name":3,"next":14,"openapi":10,"oper":8,"order":13,"other":10,"out":14,"paramet":[7,12],"parti":13,"pattern":5,"platform":4,"postgresql":15,"project":[6,14],"proxi":4,"public":11,"put":[5,7],"queri":0,"queue":0,"quick":[7,12],"rate":[0,10],"read":7,"refer":[0,12],"remov":2,"render":7,"request":[0,7,9,10,16],"respond":6,"respons":[0,7],"rest":14,"revers":4,"room":16,"rout":[0,7,10,11,12],"run":[4,7,14,15],"sandbox":8,"secret":5,"send":7,"sent":10,"serv":10,"server":[7,10,16],"servic":7,"session":[10,11],"setup":[8,14,15],"shutdown":15,"singl":14,"skip":11,"sqlalchemi":15,"sse":10,"starlett":13,"start":[7,9],"startup":15,"static":10,"statu":0,"storag":14,"support":10,"task":7,"templat":[7,12],"test":[9,16],"third":13,"tip":[9,15],"togeth":[5,7],"token":11,"tour":10,"trust":10,"try":14,"tutori":[6,16],"type":7,"unreleas":2,"updat":14,"upload":9,"url":3,"us":[5,9,11,13,15],"user":6,"uvicorn":4,"v":13,"v0":2,"v1":2,"v2":2,"v3":2,"valid":9,"variabl":5,"view":10,"web":[7,11],"websocket":[9,10,16],"what":[6,13,14],"when":13,"work":16,"world":7,"write":13,"you":6,"your":[14,15]}}) \ No newline at end of file +Search.setIndex({"alltitles":{"API Key Authentication":[[11,"api-key-authentication"]],"API Reference":[[0,null]],"Added":[[2,"added"],[2,"id2"],[2,"id4"],[2,"id7"],[2,"id11"],[2,"id17"],[2,"id18"],[2,"id21"],[2,"id24"],[2,"id29"],[2,"id36"],[2,"id42"],[2,"id43"],[2,"id44"],[2,"id45"],[2,"id46"],[2,"id49"],[2,"id50"],[2,"id52"],[2,"id55"],[2,"id58"],[2,"id59"],[2,"id60"],[2,"id64"]],"Adding Third-Party Middleware":[[13,"adding-third-party-middleware"]],"After-Request Hooks":[[10,"after-request-hooks"]],"Allowed Hosts":[[5,"allowed-hosts"]],"Authentication":[[11,null]],"Background Queue":[[0,"background-queue"]],"Background Tasks":[[7,"background-tasks"]],"Backlog":[[1,null]],"Bearer Token Authentication":[[11,"bearer-token-authentication"]],"Before-Request Hooks":[[10,"before-request-hooks"]],"Before-Request Hooks for WebSockets":[[16,"before-request-hooks-for-websockets"]],"Blueprints \u2192 Route Groups":[[12,"blueprints-route-groups"]],"Building Frontend Assets":[[3,"building-frontend-assets"]],"Building a REST API":[[14,null]],"Built-in Middleware":[[13,"built-in-middleware"]],"CORS":[[10,"cors"]],"CRUD Endpoints":[[15,"crud-endpoints"]],"Changed":[[2,"changed"],[2,"id1"],[2,"id3"],[2,"id5"],[2,"id8"],[2,"id16"],[2,"id19"],[2,"id22"],[2,"id25"],[2,"id28"],[2,"id33"],[2,"id34"],[2,"id35"],[2,"id37"],[2,"id38"],[2,"id40"],[2,"id41"],[2,"id47"],[2,"id51"],[2,"id56"],[2,"id57"],[2,"id63"]],"Changelog":[[2,null]],"Chat Room":[[16,"chat-room"]],"Class-Based Views":[[10,"class-based-views"]],"Cloud Platforms":[[4,"cloud-platforms"]],"Command Line Interface":[[3,null]],"Configuration":[[5,null]],"Configuration Class Pattern":[[5,"configuration-class-pattern"]],"Content Negotiation":[[10,"content-negotiation"]],"Cookie-Based Sessions":[[10,"cookie-based-sessions"]],"Cookies":[[10,"cookies"]],"Create a Book":[[14,"create-a-book"]],"Create a Web Service":[[7,"create-a-web-service"]],"Custom Error Handling":[[10,"custom-error-handling"]],"Custom Exception for Auth Errors":[[11,"custom-exception-for-auth-errors"]],"Custom Instance Names":[[3,"custom-instance-names"]],"Data Formats":[[16,"data-formats"]],"Database Setup":[[15,"database-setup"]],"Debug Mode":[[5,"debug-mode"]],"Define Your Models":[[14,"define-your-models"],[15,"define-your-models"]],"Delete a Book":[[14,"delete-a-book"]],"Deployment":[[4,null]],"Deprecated":[[2,"deprecated"]],"Development Sandbox":[[8,null]],"Docker":[[4,"docker"]],"Docker Compose":[[4,"docker-compose"]],"Echo Server":[[16,"echo-server"]],"Environment Variables":[[3,"environment-variables"],[5,"environment-variables"]],"Error Handling":[[14,"error-handling"]],"Feature Tour":[[10,null]],"Fixed":[[2,"fixed"],[2,"id6"],[2,"id10"],[2,"id12"],[2,"id13"],[2,"id14"],[2,"id15"],[2,"id20"],[2,"id23"],[2,"id26"],[2,"id27"],[2,"id30"],[2,"id31"],[2,"id32"],[2,"id39"],[2,"id48"],[2,"id53"],[2,"id54"],[2,"id61"],[2,"id62"]],"Future Ideas":[[1,"future-ideas"]],"Get a Single Book":[[14,"get-a-single-book"]],"Getting Started":[[9,"getting-started"]],"Gradual Migration":[[12,"gradual-migration"]],"GraphQL":[[10,"graphql"]],"HSTS":[[10,"hsts"]],"HTML Client":[[16,"html-client"]],"Health Check Endpoint":[[4,"health-check-endpoint"]],"Hello World":[[7,"hello-world"]],"Hooks vs. Middleware":[[13,"hooks-vs-middleware"]],"How WebSockets Work":[[16,"how-websockets-work"]],"In-Memory Storage":[[14,"in-memory-storage"]],"Installation":[[6,"installation"],[15,"installation"]],"JSON APIs":[[12,"json-apis"]],"Launching from a File":[[3,"launching-from-a-file"]],"Launching from a Module":[[3,"launching-from-a-module"]],"Launching from a URL":[[3,"launching-from-a-url"]],"Lifespan Events":[[10,"lifespan-events"]],"Lifespan for Startup and Shutdown":[[15,"lifespan-for-startup-and-shutdown"]],"List All Books":[[14,"list-all-books"]],"MessagePack":[[10,"messagepack"]],"Method Filtering":[[10,"method-filtering"]],"Middleware Order":[[13,"middleware-order"]],"Migrating from Flask":[[12,null]],"Mounting Other Apps":[[10,"mounting-other-apps"]],"OpenAPI Documentation":[[10,"openapi-documentation"]],"Operations":[[8,"operations"]],"Production Checklist":[[4,"production-checklist"]],"Project":[[6,null]],"Project Setup":[[14,"project-setup"]],"Putting It All Together":[[5,"putting-it-all-together"],[7,"putting-it-all-together"]],"Pydantic Validation":[[10,"pydantic-validation"]],"Query Dict":[[0,"query-dict"]],"Quick Reference":[[12,"quick-reference"]],"Quick Start":[[7,null]],"Rate Limiter":[[0,"rate-limiter"]],"Rate Limiting":[[10,"rate-limiting"]],"Reading Requests":[[7,"reading-requests"]],"Removed":[[2,"removed"],[2,"id9"]],"Rendering Templates":[[7,"rendering-templates"]],"Request":[[0,"request"]],"Request ID":[[10,"request-id"]],"Responder":[[6,null]],"Response":[[0,"response"]],"Reverse Proxy":[[4,"reverse-proxy"]],"Route Groups":[[0,"route-groups"],[10,"route-groups"]],"Route Parameters":[[7,"route-parameters"],[12,"route-parameters"]],"Run It":[[14,"run-it"],[15,"run-it"]],"Run the Server":[[7,"run-the-server"]],"Running Locally":[[4,"running-locally"]],"Secret Key":[[5,"secret-key"]],"Sending Responses":[[7,"sending-responses"]],"Server-Sent Events (SSE)":[[10,"server-sent-events-sse"]],"Serving Files":[[10,"serving-files"]],"Setup":[[8,"setup"]],"Skipping Auth for Public Routes":[[11,"skipping-auth-for-public-routes"]],"Static Files":[[10,"static-files"]],"Status Code Helpers":[[0,"status-code-helpers"]],"Templates":[[12,"templates"]],"Testing":[[9,null]],"Testing Before and After Hooks":[[9,"testing-before-and-after-hooks"]],"Testing Error Handling":[[9,"testing-error-handling"]],"Testing File Uploads":[[9,"testing-file-uploads"]],"Testing Headers and Cookies":[[9,"testing-headers-and-cookies"]],"Testing JSON APIs":[[9,"testing-json-apis"]],"Testing Lifespan Events":[[9,"testing-lifespan-events"]],"Testing Mounted Apps":[[9,"testing-mounted-apps"]],"Testing Rate Limiting":[[9,"testing-rate-limiting"]],"Testing Request Validation":[[9,"testing-request-validation"]],"Testing WebSockets":[[9,"testing-websockets"],[16,"testing-websockets"]],"The API Class":[[0,"the-api-class"]],"The Big Differences":[[12,"the-big-differences"]],"The Idea":[[6,"the-idea"]],"Tips":[[9,"tips"],[15,"tips"]],"Trusted Hosts":[[10,"trusted-hosts"]],"Try It Out":[[14,"try-it-out"]],"Tutorials":[[6,null]],"Type Convertors":[[7,"type-convertors"]],"Unreleased":[[2,"unreleased"]],"Update a Book":[[14,"update-a-book"]],"User Guide":[[6,null]],"Using .env Files":[[5,"using-env-files"]],"Using Fixtures":[[9,"using-fixtures"]],"Using PostgreSQL":[[15,"using-postgresql"]],"Using SQLAlchemy":[[15,null]],"Using Sessions for Web Apps":[[11,"using-sessions-for-web-apps"]],"Using Starlette Middleware":[[13,"using-starlette-middleware"]],"Uvicorn Directly":[[4,"uvicorn-directly"]],"WebSocket Support":[[10,"websocket-support"]],"WebSocket Tutorial":[[16,null]],"What You Get":[[6,"what-you-get"]],"What\u2019s Next":[[14,"what-s-next"]],"When to Use What":[[13,"when-to-use-what"]],"Writing Middleware":[[13,null]],"Writing Pure ASGI Middleware":[[13,"writing-pure-asgi-middleware"]],"v0.0.1 - 2018-10-12":[[2,"v0-0-1-2018-10-12"]],"v0.0.10 - 2018-10-17":[[2,"v0-0-10-2018-10-17"]],"v0.0.2 - 2018-10-13":[[2,"v0-0-2-2018-10-13"]],"v0.0.3 - 2018-10-13":[[2,"v0-0-3-2018-10-13"]],"v0.0.4 - 2018-10-15":[[2,"v0-0-4-2018-10-15"]],"v0.0.5 - 2018-10-15":[[2,"v0-0-5-2018-10-15"]],"v0.0.6 - 2018-10-16":[[2,"v0-0-6-2018-10-16"]],"v0.0.7 - 2018-10-16":[[2,"v0-0-7-2018-10-16"]],"v0.0.8 - 2018-10-17":[[2,"v0-0-8-2018-10-17"]],"v0.0.9 - 2018-10-17":[[2,"v0-0-9-2018-10-17"]],"v0.1.0 - 2018-10-17":[[2,"v0-1-0-2018-10-17"]],"v0.1.1 - 2018-10-17":[[2,"v0-1-1-2018-10-17"]],"v0.1.2 - 2018-10-18":[[2,"v0-1-2-2018-10-18"]],"v0.1.3 - 2018-10-18":[[2,"v0-1-3-2018-10-18"]],"v0.1.4 - 2018-10-19":[[2,"v0-1-4-2018-10-19"]],"v0.1.5 - 2018-10-20":[[2,"v0-1-5-2018-10-20"]],"v0.1.6 - 2018-10-20":[[2,"v0-1-6-2018-10-20"]],"v0.2.0 - 2018-10-22":[[2,"v0-2-0-2018-10-22"]],"v0.2.1 - 2018-10-23":[[2,"v0-2-1-2018-10-23"]],"v0.2.2 - 2018-10-23":[[2,"v0-2-2-2018-10-23"]],"v0.2.3 - 2018-10-24":[[2,"v0-2-3-2018-10-24"]],"v0.3.0 - 2018-10-24":[[2,"v0-3-0-2018-10-24"]],"v0.3.1 - 2018-10-24":[[2,"v0-3-1-2018-10-24"]],"v0.3.2 - 2018-10-25":[[2,"v0-3-2-2018-10-25"]],"v0.3.3 - 2018-10-25":[[2,"v0-3-3-2018-10-25"]],"v1.0.0 - 2018-10-26":[[2,"v1-0-0-2018-10-26"]],"v1.0.1 - 2018-10-26":[[2,"v1-0-1-2018-10-26"]],"v1.0.2 - 2018-10-27":[[2,"v1-0-2-2018-10-27"]],"v1.0.3 - 2018-10-27":[[2,"v1-0-3-2018-10-27"]],"v1.0.4 - 2018-10-27":[[2,"v1-0-4-2018-10-27"]],"v1.0.5- 2018-10-27":[[2,"v1-0-5-2018-10-27"]],"v1.1.0 - 2018-10-27":[[2,"v1-1-0-2018-10-27"]],"v1.1.1 - 2018-10-29":[[2,"v1-1-1-2018-10-29"]],"v1.1.2 - 2018-11-11":[[2,"v1-1-2-2018-11-11"]],"v1.1.3 - 2019-01-12":[[2,"v1-1-3-2019-01-12"]],"v1.2.0 - 2018-12-29":[[2,"v1-2-0-2018-12-29"]],"v1.3.0 - 2019-02-22":[[2,"v1-3-0-2019-02-22"]],"v1.3.1 - 2019-04-28":[[2,"v1-3-1-2019-04-28"]],"v1.3.2 - 2019-08-15":[[2,"v1-3-2-2019-08-15"]],"v2.0.0 - 2019-09-19":[[2,"v2-0-0-2019-09-19"]],"v2.0.1 - 2019-09-20":[[2,"v2-0-1-2019-09-20"]],"v2.0.2 - 2019-09-20":[[2,"v2-0-2-2019-09-20"]],"v2.0.3 - 2019-09-20":[[2,"v2-0-3-2019-09-20"]],"v2.0.4 - 2019-11-19":[[2,"v2-0-4-2019-11-19"]],"v2.0.5 - 2019-12-15":[[2,"v2-0-5-2019-12-15"]],"v3.0.0 - 2026-03-22":[[2,"v3-0-0-2026-03-22"]],"v3.2.0 - 2026-03-22":[[2,"v3-2-0-2026-03-22"]],"v3.3.0 - 2026-03-22":[[2,"v3-3-0-2026-03-22"]],"v3.4.0 - 2026-03-22":[[2,"v3-4-0-2026-03-22"]],"v3.5.0 - 2026-03-24":[[2,"v3-5-0-2026-03-24"]]},"docnames":["api","backlog","changes","cli","deployment","guide-config","index","quickstart","sandbox","testing","tour","tutorial-auth","tutorial-flask","tutorial-middleware","tutorial-rest","tutorial-sqlalchemy","tutorial-websockets"],"envversion":{"sphinx":65,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.viewcode":1},"filenames":["api.rst","backlog.md","changes.md","cli.rst","deployment.rst","guide-config.rst","index.rst","quickstart.rst","sandbox.md","testing.rst","tour.rst","tutorial-auth.rst","tutorial-flask.rst","tutorial-middleware.rst","tutorial-rest.rst","tutorial-sqlalchemy.rst","tutorial-websockets.rst"],"indexentries":{"accepts() (responder.request method)":[[0,"responder.Request.accepts",false]],"add_event_handler() (responder.api method)":[[0,"responder.API.add_event_handler",false]],"add_middleware() (responder.api method)":[[0,"responder.API.add_middleware",false]],"add_route() (responder.api method)":[[0,"responder.API.add_route",false]],"after_request() (responder.api method)":[[0,"responder.API.after_request",false]],"api (class in responder)":[[0,"responder.API",false]],"apparent_encoding (responder.request property)":[[0,"responder.Request.apparent_encoding",false]],"backgroundqueue (class in responder.background)":[[0,"responder.background.BackgroundQueue",false]],"before_request() (responder.api method)":[[0,"responder.API.before_request",false]],"check() (responder.ext.ratelimit.ratelimiter method)":[[0,"responder.ext.ratelimit.RateLimiter.check",false]],"client (responder.request property)":[[0,"responder.Request.client",false]],"content (responder.request property)":[[0,"responder.Request.content",false]],"cookies (responder.request property)":[[0,"responder.Request.cookies",false]],"encoding (responder.request property)":[[0,"responder.Request.encoding",false]],"exception_handler() (responder.api method)":[[0,"responder.API.exception_handler",false]],"file() (responder.response method)":[[0,"responder.Response.file",false]],"full_url (responder.request property)":[[0,"responder.Request.full_url",false]],"get() (responder.models.querydict method)":[[0,"responder.models.QueryDict.get",false]],"get_list() (responder.models.querydict method)":[[0,"responder.models.QueryDict.get_list",false]],"graphql() (responder.api method)":[[0,"responder.API.graphql",false]],"group() (responder.api method)":[[0,"responder.API.group",false]],"headers (responder.request property)":[[0,"responder.Request.headers",false]],"install() (responder.ext.ratelimit.ratelimiter method)":[[0,"responder.ext.ratelimit.RateLimiter.install",false]],"is_100() (in module responder.status_codes)":[[0,"responder.status_codes.is_100",false]],"is_200() (in module responder.status_codes)":[[0,"responder.status_codes.is_200",false]],"is_300() (in module responder.status_codes)":[[0,"responder.status_codes.is_300",false]],"is_400() (in module responder.status_codes)":[[0,"responder.status_codes.is_400",false]],"is_500() (in module responder.status_codes)":[[0,"responder.status_codes.is_500",false]],"is_json (responder.request property)":[[0,"responder.Request.is_json",false]],"is_secure (responder.request property)":[[0,"responder.Request.is_secure",false]],"items() (responder.models.querydict method)":[[0,"responder.models.QueryDict.items",false]],"items_list() (responder.models.querydict method)":[[0,"responder.models.QueryDict.items_list",false]],"media() (responder.request method)":[[0,"responder.Request.media",false]],"method (responder.request property)":[[0,"responder.Request.method",false]],"mimetype (responder.request property)":[[0,"responder.Request.mimetype",false]],"module":[[0,"module-responder",false]],"mount() (responder.api method)":[[0,"responder.API.mount",false]],"ok (responder.response property)":[[0,"responder.Response.ok",false]],"on_event() (responder.api method)":[[0,"responder.API.on_event",false]],"params (responder.request property)":[[0,"responder.Request.params",false]],"path_matches_route() (responder.api method)":[[0,"responder.API.path_matches_route",false]],"path_params (responder.request property)":[[0,"responder.Request.path_params",false]],"querydict (class in responder.models)":[[0,"responder.models.QueryDict",false]],"ratelimiter (class in responder.ext.ratelimit)":[[0,"responder.ext.ratelimit.RateLimiter",false]],"redirect() (responder.api method)":[[0,"responder.API.redirect",false]],"redirect() (responder.response method)":[[0,"responder.Response.redirect",false]],"request (class in responder)":[[0,"responder.Request",false]],"requests (responder.api property)":[[0,"responder.API.requests",false]],"responder":[[0,"module-responder",false]],"response (class in responder)":[[0,"responder.Response",false]],"route() (responder.api method)":[[0,"responder.API.route",false]],"routegroup (class in responder.api)":[[0,"responder.api.RouteGroup",false]],"run() (responder.api method)":[[0,"responder.API.run",false]],"run() (responder.background.backgroundqueue method)":[[0,"responder.background.BackgroundQueue.run",false]],"schema() (responder.api method)":[[0,"responder.API.schema",false]],"serve() (responder.api method)":[[0,"responder.API.serve",false]],"session (responder.request property)":[[0,"responder.Request.session",false]],"session() (responder.api method)":[[0,"responder.API.session",false]],"set_cookie() (responder.response method)":[[0,"responder.Response.set_cookie",false]],"sse() (responder.response method)":[[0,"responder.Response.sse",false]],"state (responder.request property)":[[0,"responder.Request.state",false]],"static_app (responder.api property)":[[0,"responder.API.static_app",false]],"status_code_safe (responder.response property)":[[0,"responder.Response.status_code_safe",false]],"stream() (responder.response method)":[[0,"responder.Response.stream",false]],"stream_file() (responder.response method)":[[0,"responder.Response.stream_file",false]],"task() (responder.background.backgroundqueue method)":[[0,"responder.background.BackgroundQueue.task",false]],"template() (responder.api method)":[[0,"responder.API.template",false]],"template_string() (responder.api method)":[[0,"responder.API.template_string",false]],"text (responder.request property)":[[0,"responder.Request.text",false]],"url (responder.request property)":[[0,"responder.Request.url",false]],"url_for() (responder.api method)":[[0,"responder.API.url_for",false]]},"objects":{"":[[0,0,0,"-","responder"]],"responder":[[0,1,1,"","API"],[0,1,1,"","Request"],[0,1,1,"","Response"]],"responder.API":[[0,2,1,"","add_event_handler"],[0,2,1,"","add_middleware"],[0,2,1,"","add_route"],[0,2,1,"","after_request"],[0,2,1,"","before_request"],[0,2,1,"","exception_handler"],[0,2,1,"","graphql"],[0,2,1,"","group"],[0,2,1,"","mount"],[0,2,1,"","on_event"],[0,2,1,"","path_matches_route"],[0,2,1,"","redirect"],[0,3,1,"","requests"],[0,2,1,"","route"],[0,2,1,"","run"],[0,2,1,"","schema"],[0,2,1,"","serve"],[0,2,1,"","session"],[0,3,1,"","static_app"],[0,2,1,"","template"],[0,2,1,"","template_string"],[0,2,1,"","url_for"]],"responder.Request":[[0,2,1,"","accepts"],[0,3,1,"","apparent_encoding"],[0,3,1,"","client"],[0,3,1,"","content"],[0,3,1,"","cookies"],[0,3,1,"","encoding"],[0,3,1,"","full_url"],[0,3,1,"","headers"],[0,3,1,"","is_json"],[0,3,1,"","is_secure"],[0,2,1,"","media"],[0,3,1,"","method"],[0,3,1,"","mimetype"],[0,3,1,"","params"],[0,3,1,"","path_params"],[0,3,1,"","session"],[0,3,1,"","state"],[0,3,1,"","text"],[0,3,1,"","url"]],"responder.Response":[[0,2,1,"","file"],[0,3,1,"","ok"],[0,2,1,"","redirect"],[0,2,1,"","set_cookie"],[0,2,1,"","sse"],[0,3,1,"","status_code_safe"],[0,2,1,"","stream"],[0,2,1,"","stream_file"]],"responder.api":[[0,1,1,"","RouteGroup"]],"responder.background":[[0,1,1,"","BackgroundQueue"]],"responder.background.BackgroundQueue":[[0,2,1,"","run"],[0,2,1,"","task"]],"responder.ext.ratelimit":[[0,1,1,"","RateLimiter"]],"responder.ext.ratelimit.RateLimiter":[[0,2,1,"","check"],[0,2,1,"","install"]],"responder.models":[[0,1,1,"","QueryDict"]],"responder.models.QueryDict":[[0,2,1,"","get"],[0,2,1,"","get_list"],[0,2,1,"","items"],[0,2,1,"","items_list"]],"responder.status_codes":[[0,4,1,"","is_100"],[0,4,1,"","is_200"],[0,4,1,"","is_300"],[0,4,1,"","is_400"],[0,4,1,"","is_500"]]},"objnames":{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","property","Python property"],"4":["py","function","Python function"]},"objtypes":{"0":"py:module","1":"py:class","2":"py:method","3":"py:property","4":"py:function"},"terms":{"":[0,2,3,4,5,6,7,9,10,11,12,13,15,16],"0":[0,3,4,5,7,10,14,15],"00":0,"01":0,"0441172719":14,"1":[0,1,3,4,5,7,9,10,11,12,14,16],"10":[0,6,7,10],"100":[0,2,10],"127":[3,4,5],"13":4,"14":2,"150mb":4,"16":4,"1965":14,"2":[0,1,4,7,9,10,14,15,16],"200":[0,4,7,9,10,14],"201":[0,7,9,12,14,15],"2026":0,"204":[14,15],"24":11,"2xx":0,"3":[0,1,4,6,7,9,10,14,16],"30":4,"3000":5,"301":[0,7],"308":2,"32":5,"3600":[0,10],"3f":13,"4":[4,7],"40":2,"400":[0,2,9,10,14],"401":[0,10,11],"404":[0,7,12,14,15],"41d4":7,"422":[2,9,10,14],"429":[0,9,10],"446655440000":7,"500":[2,7,9,10,13,14],"5000":10,"5042":[3,4,7,10,11,14,16],"550e8400":7,"561":2,"60":[0,2,9,10],"600":[0,10],"7":[9,11],"8":0,"80":4,"8000":[4,7],"8192":0,"9":9,"978":14,"99":9,"A":[0,4,5,6,7,10,13,16],"And":[5,6,7],"As":[0,10],"But":[7,9,10],"By":[3,7,9,10,13,14],"For":[0,3,4,5,7,9,10,11,13,14,15],"If":[0,3,5,6,7,9,10,12,15],"In":[0,5,6,7,10,11,12,15,16],"It":[0,3,6,9,10,13],"No":[6,9,10,12,14],"Not":7,"On":[5,10],"One":[6,7,9],"Or":[0,5],"That":[4,6,7,9],"The":[2,3,4,5,7,9,10,11,13,14,15,16],"There":[9,10],"These":7,"To":[14,15],"Will":0,"With":[0,5],"_":9,"__call__":13,"__init__":[11,13],"__main__":[4,6,7,9,14,15],"__name__":[4,6,7,9,10,12,14,15],"__tablename__":15,"_route_for":2,"a2wsgi":2,"a716":7,"abc":14,"abc123":[0,9,10,11],"abil":2,"abl":0,"abort":12,"about":[4,7,9,12],"abov":[6,11],"abstract":[13,15],"accept":[0,1,2,7,9,10,16],"access":[0,2,4,10,11,13,15],"acm":3,"acquir":8,"across":[2,4,10,15],"activ":[8,16],"actual":[0,4,7,10],"ad":[0,6,10],"adapt":10,"add":[0,2,4,5,7,11,13,14,15,16],"add_event_handl":0,"add_head":[10,13],"add_middlewar":[0,13],"add_request_id":0,"add_rout":[0,10],"add_tim":[9,10],"add_vers":9,"addeventlisten":16,"addit":[0,13],"address":[0,5,7,10],"adher":2,"admin":11,"affect":10,"after":[0,6,7,11,15,16],"after_request":[0,2,9,10,13],"ag":[0,10],"again":11,"against":[0,4,10,11],"aggreg":4,"agre":7,"ahead":2,"ai":10,"aiosqlit":15,"alemb":15,"algorithm":11,"alias":2,"alic":10,"aliv":4,"all":[0,2,3,4,6,8,9,10,12,13,15,16],"alloc":9,"allow":[4,6,10],"allow_credenti":[0,10],"allow_head":[0,10],"allow_method":[0,5,10],"allow_origin":[0,5,10],"allow_origin_regex":0,"allowed_host":[0,5,9,10],"alongsid":10,"alpin":4,"alreadi":[0,9,10],"also":[0,2,3,7,9,10],"altern":[0,10],"alwai":[4,5,6,7,10],"an":[0,3,4,5,7,10,12,13,14,15,16],"analysi":10,"angle_bracket":12,"angular":10,"ani":[0,3,4,5,6,7,9,10,11,13,14,15,16],"annot":[2,6,7,10],"annual":[7,10],"answer":[10,16],"anyon":6,"anyth":7,"anywher":[4,10],"api":[2,3,4,5,6,7,10,13,15,16],"api_kei":11,"api_v1":12,"apispec":2,"app":[0,2,3,4,5,6,7,12,13,14,15,16],"appar":0,"apparent_encod":0,"appear":[0,10],"appendchild":16,"appli":[0,13],"applic":[0,2,3,4,5,7,9,10,11,13,14,15],"approach":[5,10,11,12,13],"appropri":[10,15],"ar":[0,2,3,4,6,7,9,10,11,12,13,15,16],"architectur":10,"aren":[7,13],"arg":[0,12],"argument":[0,2,7,12,13],"around":[0,6],"arriv":[7,12],"asgi":[0,2,4,6,7,10,12],"ask":[6,10,16],"assert":[9,16],"asset":[0,4,6,10],"assign":14,"associ":0,"async":[0,2,4,6,7,9,10,11,12,13,14,15,16],"async_sess":15,"async_sessionmak":15,"asynccontextmanag":[10,15],"asynchron":[2,4],"asyncio":[2,15],"asyncpg":[4,15],"attach":10,"attack":[4,5,10],"attribut":[0,3,15],"audio":16,"auth":[2,6,10,13],"auth_check":10,"auth_guard":11,"authent":[6,7,10,13,16],"autherror":11,"author":[0,7,8,10,11,13,14,15],"auto":[0,2,10,16],"auto_escap":0,"autobuild":8,"autoincr":15,"automat":[0,2,3,4,5,6,7,9,10,11,12,13,14,15],"avail":[0,7,10],"avoid":[9,10,13],"aw":4,"await":[0,2,7,9,10,11,12,13,14,15,16],"azur":[3,4],"b":[0,7,9,13,15,16],"back":[0,7,10,15,16],"background":[2,6],"backgroundqueu":0,"backlog":6,"bad":[9,10,14],"balanc":4,"bandwidth":10,"bar":10,"bare":2,"base":[0,2,6,11,13,15],"base_url":0,"basehttpmiddlewar":13,"basemodel":[0,9,10,14,15],"basic":7,"batteri":6,"battl":6,"bearer":6,"becaus":[0,6,7,11,12,14],"becom":[0,15],"been":0,"befor":[0,1,2,4,6,7,11,13,15],"before_request":[0,1,2,9,10,11,12,13,16],"begin":15,"behav":0,"behavior":[5,13],"behind":[4,10],"being":[0,10],"best":6,"better":6,"between":13,"bidirect":[10,16],"big":6,"biggest":12,"bin":8,"binari":[7,10,16],"bind":[0,3,4,5,7],"blob":3,"block":[0,7,9,10,12,16],"blueprint":6,"bodi":[0,2,7,9,10,12,14,16],"boilerpl":6,"book":[6,15],"book_id":[14,15],"bookin":[14,15],"bookout":15,"books_db":14,"bool":5,"born":6,"both":[6,7,10,12,16],"bottom":14,"boundari":10,"box":13,"bp":12,"break":[2,9],"bring":6,"broad":2,"broadcast":16,"broke":[7,9],"broker":7,"browser":[7,8,10,11,14,16],"bucket":[0,10],"buffer":[0,7],"bufix":2,"bug":[2,9],"bugfix":2,"build":[2,4,6,7,8,10,11,15,16],"builder":15,"built":[1,2,4,6,7,9,10,16],"bump":2,"bypass":[4,13],"byte":[0,2,6,7,13,16],"c":[5,16],"cach":[7,9,10],"caddi":4,"caddyfil":4,"call":[2,3,7,9,10,13,14,16],"call_next":13,"callabl":[0,13],"came":7,"can":[0,2,3,4,5,7,9,10,11,12,13,14,15,16],"carri":7,"case":[0,6,7,13],"cat":10,"catalog":14,"catch":[10,11,13],"categori":0,"cd":8,"ceas":2,"celeri":7,"cell":10,"central":[0,7],"certain":0,"certif":4,"chang":[0,15],"changelog":6,"channel":[10,16],"chardet":0,"chat":[2,6,10],"check":[0,6,8,9,10,11,13,16],"check_api_kei":11,"check_auth":0,"check_exist":[0,10,14,15],"checklist":6,"choic":[7,10],"choos":10,"chunk":[0,10],"chunk_siz":0,"ci":2,"circuit":[0,1,2,10],"class":[2,6,7,9,11,13,14,15],"clean":[6,10,14],"cleaner":[10,11],"cleanli":5,"cleanup":[2,10],"clear":11,"cli":2,"click":6,"client":[0,2,6,7,9,10,11,14],"clone":8,"close":[9,10,15,16],"close_database_connection_pool":0,"cloud":[3,5,6,7],"cmd":4,"code":[2,3,4,5,6,7,8,9,10,11,14,15,16],"codebas":2,"coercion":10,"collabor":[10,16],"colon":3,"column":15,"com":[0,3,4,5,7,8,10],"combin":7,"come":[7,10,12],"command":[4,6],"commit":[4,5,15],"common":[0,3,4,5,7,10,11,12,13,14],"commonli":7,"commun":[10,11],"compact":10,"compat":[0,2],"complement":10,"complet":[7,10,14,16],"complex":[13,15],"compon":13,"compos":[6,15],"comprehens":2,"compress":[6,7,13],"compromis":5,"comput":7,"concept":[2,10,12],"concern":[7,13],"concurr":[0,4],"condit":[9,10],"config":[4,5,15],"configur":[0,2,4,6,7,9,10,13],"confirm":4,"conflict":2,"confus":9,"conn":15,"connect":[0,4,7,9,10,13,15,16],"consid":[7,15],"consist":[7,10],"consol":[10,15],"const":[10,16],"constructor":[0,13],"consum":10,"contact":0,"contain":[0,4,7],"container":4,"content":[0,2,6,7,9,13,14],"content_typ":[0,9,10],"context":[1,2,6,9,10,15,16],"contextlib":[10,15],"continu":7,"contract":9,"control":[0,4,5,7,10,11,13,15],"conveni":[0,5,15],"convent":[3,4,14],"convert":[2,7],"convertor":[2,6,12],"cooki":[0,2,5,6,7,11,12,13],"copi":4,"cor":[0,2,5,6,9,13],"core":[2,4],"coroutin":0,"correctli":4,"correspond":15,"cors_en":5,"cors_origin":5,"cors_param":[0,5,10],"corsmiddlewar":13,"count":2,"cover":[5,11,13],"coverag":2,"cpu":[0,4,7],"crash":2,"creat":[0,6,8,9,10,11,12,15],"create_al":15,"create_asgi_app":10,"create_async_engin":15,"create_book":[14,15],"create_connect":16,"create_item":[0,10,12],"create_pet":10,"create_token":11,"createel":16,"creation":[13,15],"credenti":11,"cross":[10,13],"crud":[6,7,14],"css":10,"csv":[0,10],"curl":[3,4,7,10,11,14],"curly_brac":12,"custom":[0,2,6,7,9,14,16],"cut":13,"cycl":7,"d":[7,9,14],"dashboard":[5,10,11,16],"data":[0,2,4,5,6,7,9,10,11,12,14,15],"databas":[4,5,6,7,9,10,11,14],"database_url":[4,5,15],"date":0,"datetim":11,"db":[4,5,15],"debug":[0,2,4,6,10,12],"decim":7,"declar":[2,7],"declarativebas":15,"decod":[2,10,11],"decor":[0,2,7,10],"deep":6,"def":[0,4,6,7,9,10,11,12,13,14,15,16],"def456":11,"default":[0,2,3,4,5,7,9,10,15],"default_valu":[0,10],"defend":10,"defin":[0,6,7,10,11],"definit":0,"del":14,"delet":[5,6,7,10,15],"delete_book":[14,15],"deliber":7,"demo":3,"deni":13,"denpend":2,"dep":2,"depend":[2,4,9,13],"depends_on":4,"deploi":[4,6],"deploy":[2,6],"depth":10,"describ":10,"descript":[0,10],"design":[7,10,14],"detail":[4,5,10,14],"detect":[0,6,10],"dev":[2,4,5],"develop":[3,4,5,10,15],"devic":10,"dict":[6,7,10,11,14,15],"dictionari":0,"differ":[0,1,3,5,6,9,10,15],"digit":7,"direct":[0,2,10,13],"directli":[3,6,7,9,10,14,15],"directori":[0,7,10],"disabl":[4,9,15],"discard":16,"disconnect":16,"disk":[0,7,10],"dispatch":[2,10,13],"dispos":15,"distribut":[4,10],"div":16,"django":[6,10],"do":[4,5,7,10],"doc":[0,2,8,9,10,11,14],"docker":[5,6],"dockerfil":4,"docs_rout":[0,10,14],"docstr":[2,10],"doctyp":16,"document":[0,2,4,6,8,14,16],"doe":15,"doesn":[0,10,14,15],"domain":[0,4,5,10],"don":[4,5,7,9,10,11,12,15],"done":4,"dot":3,"dotenv":5,"doubl":14,"down":[10,15],"download":10,"dramat":2,"driver":15,"drop":[2,16],"dump":2,"dune":14,"duplex":10,"duplic":10,"durat":13,"dure":[3,4,9,15],"duti":14,"dynam":7,"e":[0,16],"e29b":7,"each":[0,4,9,10,15],"easi":[3,5,7],"echo":[6,7,15],"ecosystem":[6,7],"edit":8,"editor":[10,16],"effect":[9,14],"effici":4,"either":[0,16],"element":[0,10],"els":[7,10,11,12,15],"email":7,"emb":10,"empti":[0,14],"enabl":[0,2,4,10,13,14],"enable_async":7,"enable_hst":[0,10,13],"encod":[0,2,11],"encrypt":11,"end":[7,14],"endpoint":[0,1,2,6,9,10,11,12,14],"enforc":10,"engin":[7,15],"enough":[4,13],"ensur":[10,14,15,16],"enter":[9,16],"entir":[0,4,10,11,13,14],"entiti":10,"entri":14,"env":[4,6],"environ":[0,4,6,7],"eol":2,"equival":12,"error":[0,2,5,6,15],"errorhandl":12,"escap":0,"essenti":10,"establish":16,"etc":[7,9,10],"even":[3,4,10,16],"event":[0,2,6,7,12,16],"event_typ":0,"eventsourc":10,"ever":[5,6],"everi":[0,4,5,6,7,9,10,11,13,14,15],"everyth":[0,2,4,7,10,12,14,15,16],"everywher":[3,5],"evolv":15,"exact":2,"exactli":[9,10],"exampl":[0,2,3,4,5,7,10,11],"exc":[0,9,10,11,14],"exceed":[0,10],"except":[0,2,6,9,10,13,16],"exception_cl":0,"exception_handl":[0,2,9,10,11,12,14],"exceptionmiddlewar":13,"execut":15,"exist":[0,2,6,12,13],"exit":[4,9,10,16],"exp":11,"expand":2,"expect":7,"expens":4,"expir":[0,10,11],"expire_on_commit":15,"explain":10,"explan":0,"explicit":[7,10,12],"explicitli":[10,12],"explor":[7,10],"export":[0,5,10],"expos":[4,5],"expose_head":0,"express":[6,7],"ext":[0,2,9,10,15],"extens":[2,7],"extern":7,"extra":[2,4,10,13],"extract":0,"extrem":7,"f":[0,4,6,7,9,10,11,13,14,16],"factori":15,"fail":[9,10,15],"failur":[2,9],"falcon":[6,10],"fall":0,"fals":[0,4,5,9,10,14,15],"familiar":[6,12],"fast":[4,6,7,9],"fastapi":6,"faster":[10,13],"featur":[0,6,7],"feed":10,"feel":6,"fetch":3,"few":12,"fido":10,"field":[0,2,9,10,14],"figur":7,"file":[0,2,4,6,7,14,15,16],"filenam":[0,9],"filepath":7,"filesystem":[2,3],"fill":7,"filter":[6,7],"final":16,"find":[3,10,12],"fine":[4,10,13,15],"fire":[0,9],"first":[0,9,10,11,13,14,15],"fit":6,"fix":8,"fixtur":6,"flag":[4,10,15],"flask":[2,6,9,10],"flask_app":[9,10,12],"flatten":2,"float":[0,7,9,10],"flow":[11,13],"fly":[3,4],"fmt":2,"follow":7,"font":10,"forg":[5,10],"forget":0,"form":[0,7,11,12],"format":[0,2,6,7,8,10,11],"formerli":10,"forward":[4,10],"found":[2,7,14,15],"foundat":10,"fragment":3,"frame":13,"framework":[6,10],"franca":7,"frank":14,"free":2,"freeli":16,"fresh":9,"from":[0,2,4,5,6,7,9,10,11,13,14,15,16],"from_attribut":15,"front":4,"frontend":[6,10],"fsspec":3,"full":[0,2,3,7,10],"full_url":[0,7,10],"fulli":7,"fun":6,"func":0,"function":[0,7,10,12,13],"futur":[0,2,6],"g":0,"game":[10,16],"gatewai":4,"gener":[0,2,5,6,9,10,13,14],"get":[0,2,5,7,10,11,15],"get_book":[14,15],"get_list":0,"get_m":11,"get_us":[0,10,12],"getelementbyid":16,"getenv":5,"getlist":0,"git":[5,8],"github":[2,3,8],"gitignor":5,"give":[0,9,10,13,15],"given":[0,9],"global":[12,14],"gmt":0,"go":[4,7,12],"goe":[10,12],"good":[4,6,10],"googl":[3,4],"grace":4,"grade":7,"gradual":[6,10],"graduat":13,"grain":15,"graphen":[0,2,6,10],"graphiql":[2,6,10],"graphql":[0,2,6],"great":[3,6,10],"greet":[6,7,10],"greet_world":6,"greetingresourc":10,"group":[2,6],"grow":10,"guard":11,"guid":[2,5,7,11,12,15],"guido":7,"gzip":[6,7],"gzipmiddlewar":13,"h":[7,10,11,14],"h1":[0,7,11],"ha":[7,9,12,14,16],"half":7,"halv":10,"hand":0,"handl":[0,2,4,5,6,7,11,13,16],"handle_auth_error":11,"handle_value_error":[0,10,14],"handler":[0,6,9,10,11,13,14],"handshak":16,"happen":[6,7,10],"hard":9,"hasn":0,"have":[0,2,3,7,9,12,13,14],"hdf":3,"head":3,"header":[0,2,4,5,6,7,10,11,12,13,16],"health":[6,11],"healthcheck":4,"healthi":4,"heavi":7,"hello":[0,3,6,9,10,12,16],"hello_html":7,"hello_json":7,"hello_to":7,"hello_world":7,"helloworld":3,"help":[0,15],"helper":[6,11],"herbert":14,"here":[4,5,7,10,12,16],"heroku":[3,4],"high":[4,10],"hold":[0,6,7],"home":6,"homepag":2,"honor":[4,7],"hood":10,"hook":[0,2,6,7,11],"host":[0,2,4,6,7,9,13],"hostnam":10,"hour":[10,11],"how":[3,5,6,7,10,11,12,14,15],"hs256":11,"hst":6,"html":[0,2,6,7,10,11,12],"http":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,16],"httponli":[0,10],"httpsredirect":0,"httpsredirectmiddlewar":[0,4,13],"httpx":[2,9],"i":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"id":[0,2,6,7,12,13,14,15,16],"idea":12,"idempot":14,"ident":12,"identifi":10,"imag":[4,7,10,16],"immedi":[0,6,7,10],"immut":2,"imperson":5,"implement":9,"import":[0,2,3,5,6,7,9,10,11,12,13,14,15,16],"improv":2,"inaccess":0,"includ":[3,4,6,7,8,9,10,11,14],"incom":[0,7,10,14],"incredibli":10,"independ":4,"index":[0,7,10,16],"individu":10,"industri":10,"info":[0,2,10],"inform":[0,14],"infrastructur":[4,6],"inherit":[0,10],"initi":[0,9],"inject":[3,10,13],"innermost":13,"input":[2,9,10,14,16],"insensit":[0,6,7],"insid":13,"inspect":[0,2],"instal":[0,2,3,4,5,8,9,10,11,16],"instanc":[0,4,6,7,9],"instant":7,"instantli":4,"instead":[0,7,9,10,13,14,15,16],"instruct":4,"int":[0,2,7,10,11,12,14,15],"integ":[0,7,14,15],"integr":[10,13,14,15],"intens":7,"intent":6,"intention":10,"interact":[2,10,14],"interfac":[2,4,6,7,12],"intern":[9,10,13],"interv":4,"invalid":[5,9,10,11],"invalidtokenerror":11,"involv":0,"io":[3,4],"iot":10,"ip":[0,7,10],"is_100":0,"is_200":0,"is_300":0,"is_400":0,"is_500":0,"is_class_bas":2,"is_http":0,"is_json":[0,2,7],"is_secur":[0,7],"isbn":[14,15],"iscoroutinefunct":2,"isn":[7,10,12],"issu":[2,11],"item":[0,9,10,12,15],"itemin":[0,10],"itemout":[0,10],"items_list":0,"iter":16,"its":[0,2,4,14,15],"itself":11,"j":10,"jan":0,"javascript":[0,3,10],"jinja2":[0,7,12],"jpeg":10,"jpg":10,"json":[0,3,6,7,10,11,14,16],"jsonifi":12,"jump":7,"just":[4,9,10,13,15,16],"jwt":11,"keep":[2,4,5,7,9,10,13,15,16],"kei":[0,4,6,7,9,10,12,15,16],"kennethreitz":[3,8],"keypress":16,"keyword":[0,7,12,13],"know":[5,7],"known":[0,11],"kubernet":4,"kwarg":0,"languag":10,"larg":[0,2,10],"larger":[5,9,13],"last":[0,13],"later":[7,9],"launch":[4,6],"layer":13,"lazi":2,"lazili":0,"lead":9,"learn":10,"legaci":12,"less":10,"let":[3,4,7,10,14,15],"level":[4,13],"lib":4,"librari":[9,10,16],"licens":0,"lifecycl":16,"lifespan":[0,2,6,14],"lift":7,"lightn":4,"lightweight":[4,7],"like":[0,3,4,7,9,10,11,13,14,16],"limit":[1,2,4,6,13,15,16],"line":[6,7],"liner":2,"lingua":7,"list":[0,6,7,9,10,13,15],"list_book":[14,15],"list_item":10,"list_pet":10,"list_us":[0,10,12],"list_users_v2":10,"listen":3,"live":[4,10,16],"ll":[6,7,10,12,14,15],"load":[0,2,3,4,5,7,10],"load_dotenv":5,"local":[3,5,6,12],"localhost":[4,5,7,9,10,11,14,15,16],"locat":[0,7,11,12],"lock":4,"log":[1,4,6,10,11,13],"log_error":0,"log_level":2,"log_request":13,"log_respons":10,"logic":[6,7,10],"login":[10,11],"logout":11,"long":7,"look":[3,4,6,7],"loop":[7,12,16],"lose":[2,15],"lower":[0,5],"lowercas":7,"machin":10,"made":[0,6],"magic":12,"mai":4,"main":3,"make":[4,5,7,9,10,11,12],"malici":10,"manag":[2,5,6,9,10,11,13,15,16],"mani":[0,4,7,10],"manual":0,"map":[2,7,10,12,15],"mapper":15,"marimo":[2,10],"mark":[2,10],"marker":2,"marshmallow":[0,2,10],"match":[0,5,7,10,14],"matter":10,"max_ag":[0,10],"maximum":[0,13],"me":[0,11],"mean":[4,7,10,12],"mechan":10,"media":[0,2,4,6,7,9,10,11,12,14,15],"memori":[0,2,6,7,10],"messag":[0,7,10,11,13,16],"messagepack":[2,6],"metadata":[0,7,15],"method":[0,6,7,9,11,12,13,14,15,16],"microservic":10,"middelwar":0,"middlewar":[0,2,6,7,10],"middleware_cl":0,"middleware_config":0,"might":7,"migrat":[2,6,10,15],"mime":0,"mimetyp":[0,7,10],"min":[0,10],"mind":13,"minim":[4,16],"minimum":2,"minor":2,"miss":[2,9,10,11],"mix":10,"ml":10,"mode":[0,4,6,8],"model":[0,2,6,9,10],"model_dump":15,"model_valid":15,"modern":[4,10,11,12,15],"modifi":[0,10,13,14,15],"modul":[0,2,6,7,10],"monitor":4,"more":[0,3,4,7,10,11,12,13,14,16],"most":[0,3,4,5,7,9,10,11,13,15],"mount":[0,2,6,12],"move":[2,7,10,12],"msgpack":[2,10],"much":[7,10],"multi":0,"multipart":[2,7],"multipl":[0,2,4,10,14],"multiplay":[10,16],"must":[0,7,10,11,14,16],"mutabl":6,"mutat":[0,7,12],"my":0,"my_templ":7,"myapi":4,"myapp":[3,4],"mydb":15,"mysql":15,"n":[0,7],"name":[0,4,5,6,7,9,10,12],"namespac":2,"narrow":2,"nativ":12,"natur":[9,15],"nearli":12,"need":[4,5,6,7,9,10,11,12,13,15,16],"negoti":[0,6,7,9],"nervou":7,"network":9,"never":[4,5,10,11,14],"new":[0,7,9,10,12,14,16],"new_endpoint":12,"next":[6,13],"next_id":14,"nginx":4,"non":7,"none":[0,2,11,14,15],"normal":[0,10,16],"nosniff":13,"notabl":2,"notasecret":0,"note":[7,10,12,14],"notebook":[2,10],"notic":7,"notif":10,"now":[2,7,10,11,15,16],"npm":3,"nullabl":15,"number":[0,7],"o":[0,3,5,7,12],"object":[0,2,7,10,12,13,15,16],"objecttyp":[0,10],"obviou":9,"octet":0,"off":[5,7],"offload":4,"offset":15,"often":[3,7,10],"ok":[0,7,9,14],"old":12,"omit":4,"on_delet":10,"on_ev":[0,9,10],"on_get":[6,10],"on_post":[6,10],"on_put":10,"on_request":[6,10],"on_startup":9,"onc":[10,12,14],"one":[0,2,5,6,7,10,12,15],"ones":[6,7,10],"onion":13,"onli":[0,5,7,10,12,14],"onmessag":[10,16],"open":[2,7,8,15],"open_database_connection_pool":0,"openapi":[0,1,2,6,14],"openapi_rout":0,"openapi_them":0,"oper":[7,10,12,14],"opt":10,"option":[0,2,4,6,7,13],"option1":13,"option2":13,"orchestr":4,"order":[0,6],"order_bi":15,"organ":[0,5,9,10,12],"origin":[10,13],"orm":15,"other":[0,2,3,4,6,7,15],"otherwis":[0,10],"our":14,"out":[5,6,7,13],"outermost":13,"outgo":[7,10],"output":14,"outsid":13,"over":[0,6,7,10,12,15],"overal":2,"overhead":[9,13],"overrid":[0,10],"overwhelm":10,"own":[4,10,15],"p":[4,11,16],"pace":10,"packag":[2,3,4],"page":[0,2,5,7,10,11,16],"pagin":7,"painless":9,"pair":0,"param":[0,2,6,7,12],"paramet":[0,6,9,10,14],"parameter":0,"pars":[0,2,7,9,10],"parser":2,"part":[2,6,7,10],"parti":6,"pass":[0,3,4,7,9,10,12,13,15,16],"passion":6,"password":11,"patch":[7,10],"path":[0,2,3,6,7,9,10,11,13],"path_matches_rout":0,"path_param":[0,2,7],"pattern":[0,4,6,7,10,11,12,13,14,15],"payload":11,"pdf":[0,7,9,10],"pep":2,"per":[0,1,4,9,10],"perfect":10,"perfectli":13,"perform":13,"period":[0,2,9,10],"perman":7,"permit":10,"persist":[0,10,16],"person":6,"pet":[0,10],"petin":10,"petout":10,"petschema":[0,10],"pgdata":4,"photo":10,"piec":10,"pin":[2,4],"pip":[2,3,4,5,6,8,11,15,16],"pipe":4,"place":[5,10],"placehold":[7,16],"plain":[0,7,10,13,16],"platform":[2,3,5,6,7],"pleasant":6,"plot":10,"plu":15,"plugin":2,"poethepoet":2,"point":[3,4,14],"polici":[10,13],"poll":4,"pool":[0,6,7,10,12,15],"popular":[7,10,15],"port":[0,3,4,5,7,9],"portion":0,"possibl":7,"post":[0,5,7,9,10,11,12,14,15],"postgr":4,"postgres_db":4,"postgres_password":4,"postgres_us":4,"postgresql":[4,6],"potenti":2,"power":[6,9,10,13,15,16],"practic":10,"prefer":10,"prefix":[0,2,10],"present":7,"prevent":[5,10],"price":[0,9,10],"primari":0,"primary_kei":15,"print":[0,5,10,13,15,16],"privat":10,"proce":16,"process":[0,4,6,7,9,10,13],"process_data":7,"procfil":4,"prod":5,"produc":[0,7],"product":[2,3,5,6,7,9,10,11,15],"profil":10,"programmat":10,"progress":10,"project":[2,3,8],"propag":9,"proper":[7,11,15],"properli":[2,5,9,15],"properti":[0,2,7,9],"prose":2,"protect":[4,11],"proto":4,"protocol":[3,7,9,10,13,16],"prototyp":[2,3,6],"provid":0,"proxi":6,"public":[0,6,10],"public_path":11,"pure":6,"push":[1,4,6,10],"put":[6,10,14,15],"py":[2,3,4,5,7,9,10,14,15],"pydant":[0,2,6,9,14,15],"pyjwt":11,"pypi":2,"pyproject":2,"pytest":[6,8,9],"python":[0,2,3,4,5,6,7,10,14,15,16],"pythonpath":3,"q":[0,7,12],"queri":[2,4,6,7,10,15,16],"query_str":0,"querydict":0,"queue":[6,7],"quick":[0,3,6],"r":[7,9],"race":9,"railwai":[3,4],"rais":[0,2,9,10,11],"raise_server_except":9,"random":[0,5],"rang":[0,7,9,10],"rapidoc":[0,10],"rare":7,"rate":[1,2,4,6,13],"rate_limit":0,"ratelimit":[0,2,6,9,10,13],"rather":9,"raw":[0,3,6,7,10,13,15,16],"re":[0,4,7,9,10,12,13,14,16],"reach":[11,13],"react":[2,10],"reactiv":10,"read":[0,2,3,5,6,10,11,12,14,15],"readabl":10,"readi":[4,5,6,7],"real":[2,5,6,10,11,14,15],"realli":[9,10],"receiv":[0,6,7,9,10,11,13,16],"receive_byt":[10,16],"receive_incom":7,"receive_json":[10,16],"receive_text":[9,10,16],"recommend":10,"reconnect":10,"recv":16,"redirect":[0,2,7,11,12],"redoc":[0,10],"reduc":2,"ref":3,"refactor":[2,9],"refer":[2,6,9],"referr":13,"refresh":15,"refus":10,"regist":[0,9,10,11],"register_blueprint":12,"reject":[1,9,10],"relat":[0,10,15],"releas":8,"reliabl":9,"remain":[0,9,10],"rememb":11,"remov":[10,12,14,16],"renam":9,"render":[0,4,6,10],"render_async":7,"render_templ":12,"replac":[2,7,10,14],"report":[7,9,10],"repres":0,"represent":0,"reproduc":4,"req":[0,2,4,6,7,9,10,11,12,13,14,15,16],"request":[1,2,3,4,6,11,12,13,14,15],"request_id":[0,2,10,13],"request_model":[0,2,9,10,14,15],"requir":[0,2,9,10],"research":6,"resolv":[2,10],"resolve_hello":[0,10],"resourc":[7,10,14],"resp":[0,2,4,6,7,9,10,11,12,13,14,15,16],"respect":3,"respond":[0,2,3,4,5,7,8,9,10,11,12,13,14,15,16],"respons":[2,6,9,10,12,13,14,15,16],"response_model":[0,2,10,14,15],"rest":[2,4,6,7,10],"restrict":[4,10],"result":[0,2,7,10,15],"resum":2,"resume_incomplet":2,"retri":[0,10],"retriev":[0,10,14],"return":[0,2,4,6,7,9,10,11,12,13,14,15],"reusabl":11,"revers":[0,6],"reverse_proxi":4,"rework":2,"rewrit":2,"rewrot":2,"rfc3986":2,"right":[6,7,10,12,13],"roll":15,"room":6,"root":[2,10],"rotat":5,"rout":[1,2,4,6,9,13,14,15,16],"routegroup":0,"router":2,"rst":2,"ruff":[2,8],"rule":5,"run":[0,2,3,6,8,9,10,12,13,16],"run_sync":15,"runner":[2,4],"runtim":3,"runtimeerror":0,"s3":3,"safe":[2,14],"sai":7,"said":4,"same":[3,4,6,7,10,12,13,14,15],"sandbox":6,"save":[7,16],"scalar":15,"scale":6,"schema":[0,2,6,10,11,14,15],"scope":[0,10,13],"scratch":[6,14],"script":16,"search":[0,2,7,10],"second":0,"secret":[4,6,10,11],"secret_kei":[0,3,4,5,10,11],"section":10,"secur":[0,10,13],"securityheadersmiddlewar":13,"see":[0,4,5,7,9,10,13,14,15],"select":[0,2,15],"self":[0,10,11,13],"semant":2,"send":[0,2,6,9,10,11,13,14,16],"send_byt":[10,16],"send_email":0,"send_json":[10,16],"send_text":[9,10,16],"send_with_head":13,"sensit":11,"sent":[0,2,6,7,13],"separ":[7,9,14],"sequenti":2,"serial":[0,2,6,7,10,16],"serializ":7,"serv":[0,2,3,4,5,6,7,9,14,16],"server":[0,1,2,3,4,5,6,9,11,13,14,15],"servererrormiddlewar":13,"servestat":2,"servic":[0,3,4,6,9,10,14],"session":[0,2,5,6,7,9,12,13,15],"session_id":10,"sessionmiddlewar":13,"set":[0,2,3,4,5,6,7,8,9,10,11,15,16],"set_cooki":[0,2,10],"set_text":0,"setattr":15,"setup":[2,5,6,9],"sever":[10,13],"sftp":3,"shape":10,"share":[0,3,7,9,10,15],"shell":5,"short":[0,1,2,10],"shorthand":0,"should":[4,5,14,15],"shouldn":0,"show":[2,10,12,15,16],"shut":[10,15],"shutdown":[0,4,6,9,10],"shutdwown":2,"sibl":6,"side":[7,10,11,16],"sign":[0,5,6,7,10,11,13],"signatur":[7,10,12],"signup":11,"simpl":[3,4,9,10,11,13,14,16],"simplecooki":0,"simpler":[7,10,11,13],"simplest":[5,7,11,13,16],"simpli":11,"simplic":[6,15],"simul":7,"sinc":[7,9],"singl":[0,2,3,6,7,10,12,15],"sit":13,"size":[0,15],"sk":11,"skip":[0,6,10],"slash":7,"sleep":[7,9],"slim":4,"slow":7,"slowlori":4,"slug":7,"small":[4,6,9,10],"smaller":4,"so":[9,10,12,13,14,15],"solv":10,"some":[4,5,10],"some_packag":13,"somemiddlewar":13,"someon":[5,7,10,16],"someth":[6,7,9,10],"sometim":[7,10],"somewher":7,"sourc":[0,5,8,10],"spawn":4,"spec":[7,10],"special":[6,10],"specif":[0,2,5,9,10,13,14],"specifi":3,"sphinx":8,"spin":7,"split":5,"sprawl":6,"sql":15,"sqlalchemi":[2,6,7,14],"sqlite":[5,15],"sse":[0,2,6],"ssl":4,"stabil":2,"stack":13,"stai":[12,15],"standard":[3,4,10,11,14],"starlett":[0,2,6,9,16],"start":[0,3,4,6,10,13,14,15],"startswith":11,"startup":[0,2,6,9,10],"state":[0,2,9,10,11],"statement":6,"static":[0,2,4,6,7,16],"static_app":0,"static_dir":[0,10],"static_rout":[0,2,10],"staticfil":0,"statu":[2,4,6,7,9,10,14],"status_cod":[0,6,7,9,10,11,12,13,14,15],"status_code_saf":0,"stderr":0,"stdlib":2,"still":[10,12],"stop":10,"storag":[3,6],"store":[0,5,10,11,14],"str":[0,7,9,10,11,14,15],"straightforward":10,"stranger":[0,10],"stream":[0,2,6,10,13],"stream_data":0,"stream_fil":[0,2,10],"strict":[10,13],"string":[0,6,7,10,15,16],"strip":[2,10,11],"structur":[1,10],"style":10,"stylesheet":10,"sub":11,"subclass":0,"subcommand":3,"subject":0,"submiss":0,"submit":0,"subrout":[6,9,10,12],"subsequ":[10,11],"subtl":2,"succe":9,"success":[0,7,14],"successfulli":14,"successor":4,"suit":9,"suppli":2,"support":[0,1,2,3,4,6,7,12,15,16],"swagger":[0,6,10,14],"swagger_ui":[0,10],"switch":[2,15,16],"sync":[2,6,7,12],"synchron":[0,12],"syntax":[2,6,7,12],"synthet":9,"system":[3,7,10],"t":[0,4,5,7,9,10,11,12,13,14,15],"tabl":15,"tag":0,"take":[6,7],"tamper":[10,11],"target":2,"task":[0,2,6],"teach":6,"tear":10,"tell":[7,10,14,15],"templat":[0,2,6],"template_str":[0,7],"templates_dir":0,"termin":[3,4],"terms_of_servic":0,"test":[0,2,3,5,6,8,14],"test_500":[2,9],"test_api":9,"test_create_item":9,"test_custom_error":9,"test_echo":16,"test_flask_mount":9,"test_head":9,"test_hello":9,"test_hook":9,"test_json":9,"test_rate_limit":9,"test_upload":9,"test_valid":9,"test_websocket":9,"test_with_lifespan":9,"testclient":[0,2,9,16],"text":[0,2,6,7,9,10,12,16],"textcont":16,"than":[9,10,11,12,13,14],"thei":[0,5,7,9,10,12,13,14,16],"them":[3,4,6,7,9,10,11,12,14,16],"theme":[0,10],"themselv":10,"thi":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"thing":[5,6,7,9,10,13],"think":7,"third":[6,9],"though":4,"thousand":4,"thread":[0,2,6,7,12],"threadpoolexecutor":[0,2],"three":[7,10,16],"through":[0,7,10,13,14,16],"throughput":10,"thu":0,"ti":4,"time":[0,2,6,7,9,10,12,13,14,15,16],"time_start":0,"timedelta":11,"timeout":4,"timingmiddlewar":13,"tip":[2,6],"titl":[0,2,7,10,14,15],"tl":4,"togeth":[4,6,10],"token":[0,6,7,10,16],"token_hex":5,"toml":2,"too":[0,3,4,9,10],"tool":[4,8,13],"toolbelt":2,"toolkit":15,"top":[0,5],"total":10,"tour":[0,6,7],"trace":10,"traceback":[0,2,5,10],"track":15,"tradit":[10,11],"traffic":4,"transact":15,"transform":13,"translat":12,"transport":10,"treat":[0,10],"trick":10,"trigger":9,"true":[0,2,5,7,9,10,11,12,13,15,16],"trust":[2,6,9],"trustedhostmiddlewar":[4,13],"try":[6,7,11,16],"tupl":[0,7,9],"tutori":[2,7,14],"two":[7,9,10,13],"type":[0,2,6,10,12,13,14,16],"typic":[7,10],"typo":[2,10],"ui":[0,2,6,10,14],"unauthor":[0,10,11],"under":[0,7,10,12],"underlin":2,"understand":[6,7],"unexpectedli":16,"unhandl":13,"unicod":0,"union":2,"uniqu":10,"unit":15,"univers":5,"unknown":0,"unless":10,"unlik":10,"unmaintain":2,"unmatch":10,"unpin":2,"unprocess":10,"unrecogn":10,"until":7,"up":[0,2,4,7,8,10],"updat":[2,6,7,10,15,16],"update_book":[14,15],"upgrad":[2,8,10,16],"upload":[0,2,6,7],"url":[0,2,5,6,7,9,10,11,12,13,15],"url_for":[0,2,9],"url_prefix":12,"urllib":2,"us":[0,2,3,4,6,7,10,12,14,16],"usag":[0,2],"user":[0,4,5,7,10,11,12,15],"user_id":[7,10,11,12],"usernam":[10,11],"usual":9,"utcnow":11,"utf":0,"uuid":[0,2,7,10],"uuid4":0,"uv":[3,4,5,6,8,11,15],"uvicorn":[0,2,6,7,13],"uvloop":4,"v":6,"v1":[0,10],"v2":10,"valid":[0,2,6,7,11,13,14,15],"valu":[0,6,7,9,10,11,12,13,14,15,16],"valueerror":[0,9,10,12,14],"var":4,"variabl":[0,4,6,7],"ve":[6,9,12],"venv":8,"verb":10,"veri":[0,7,15],"verifi":[4,9,11],"verify_token":11,"version":[0,2,6,9,10,14],"via":[0,2,4,5,10,12],"view":[0,2,6,7,9,12],"virtual":[3,4],"virtualenv":8,"visit":[10,14],"volum":4,"vue":10,"w":[9,10,16],"wa":[0,2,7,14],"wai":[3,4,6,7,10,11,12,13,15],"wait":[4,12],"walk":[7,10,14],"walkthrough":10,"want":[0,3,4,6,7,9,10,13,14,15,16],"warn":2,"watch":8,"we":[14,15,16],"web":[0,4,6,10,15],"websit":10,"websocket":[0,1,2,4,6,13],"websocket_connect":[9,16],"welcom":[6,7,11],"well":6,"went":6,"werkzeug":[2,9],"what":[0,7,9,10,16],"whatev":7,"when":[0,2,3,4,5,6,7,9,10,12,14,15,16],"where":[0,4,7,10,15,16],"whether":[0,7],"which":[0,2,7,9,10,12,15],"whichev":6,"while":[7,10,12,16],"whitenois":2,"who":[6,7,11],"widget":[9,10],"wildcard":10,"window":2,"wire":7,"with_app":10,"within":[2,10,15],"without":[0,2,4,7,9,10,15],"won":[7,9,10,15],"work":[3,4,5,6,7,10,13,14,15],"workdir":4,"worker":4,"world":[0,3,6,9,10,12],"worri":9,"would":9,"wrap":[0,7,9,10,13],"write":[6,7,10,12],"wrong":10,"ws_auth":16,"wsgi":[0,2,4,6,9,10,12],"www":5,"x":[0,4,6,7,9,10,11,12,13,14],"x00":16,"x01":16,"x02":16,"x89png":7,"xml":0,"xss":10,"yaml":[0,2,6,7,9,10],"year":[14,15],"yield":[0,10,15],"yml":[0,4,10,11],"you":[0,3,4,5,7,9,10,11,12,13,14,15,16],"your":[0,3,4,5,6,7,9,10,11,12,13],"yourself":7,"zero":4},"titles":["API Reference","Backlog","Changelog","Command Line Interface","Deployment","Configuration","Responder","Quick Start","Development Sandbox","Testing","Feature Tour","Authentication","Migrating from Flask","Writing Middleware","Building a REST API","Using SQLAlchemy","WebSocket Tutorial"],"titleterms":{"":14,"0":2,"01":2,"02":2,"03":2,"04":2,"08":2,"09":2,"1":2,"10":2,"11":2,"12":2,"13":2,"15":2,"16":2,"17":2,"18":2,"19":2,"2":2,"20":2,"2018":2,"2019":2,"2026":2,"22":2,"23":2,"24":2,"25":2,"26":2,"27":2,"28":2,"29":2,"3":2,"4":2,"5":2,"6":2,"7":2,"8":2,"9":2,"In":14,"It":[5,7,14,15],"The":[0,6,12],"ad":[2,13],"after":[9,10],"all":[5,7,14],"allow":5,"api":[0,9,11,12,14],"app":[9,10,11],"asgi":13,"asset":3,"auth":11,"authent":11,"background":[0,7],"backlog":1,"base":10,"bearer":11,"befor":[9,10,16],"big":12,"blueprint":12,"book":14,"build":[3,14],"built":13,"chang":2,"changelog":2,"chat":16,"check":4,"checklist":4,"class":[0,5,10],"client":16,"cloud":4,"code":0,"command":3,"compos":4,"configur":5,"content":10,"convertor":7,"cooki":[9,10],"cor":10,"creat":[7,14],"crud":15,"custom":[3,10,11],"data":16,"databas":15,"debug":5,"defin":[14,15],"delet":14,"deploy":4,"deprec":2,"develop":8,"dict":0,"differ":12,"directli":4,"docker":4,"document":10,"echo":16,"endpoint":[4,15],"env":5,"environ":[3,5],"error":[9,10,11,14],"event":[9,10],"except":11,"featur":10,"file":[3,5,9,10],"filter":10,"fix":2,"fixtur":9,"flask":12,"format":16,"from":[3,12],"frontend":3,"futur":1,"get":[6,9,14],"gradual":12,"graphql":10,"group":[0,10,12],"guid":6,"handl":[9,10,14],"header":9,"health":4,"hello":7,"helper":0,"hook":[9,10,13,16],"host":[5,10],"how":16,"hst":10,"html":16,"id":10,"idea":[1,6],"instal":[6,15],"instanc":3,"interfac":3,"json":[9,12],"kei":[5,11],"launch":3,"lifespan":[9,10,15],"limit":[0,9,10],"line":3,"list":14,"local":4,"memori":14,"messagepack":10,"method":10,"middlewar":13,"migrat":12,"mode":5,"model":[14,15],"modul":3,"mount":[9,10],"name":3,"negoti":10,"next":14,"openapi":10,"oper":8,"order":13,"other":10,"out":14,"paramet":[7,12],"parti":13,"pattern":5,"platform":4,"postgresql":15,"product":4,"project":[6,14],"proxi":4,"public":11,"pure":13,"put":[5,7],"pydant":10,"queri":0,"queue":0,"quick":[7,12],"rate":[0,9,10],"read":7,"refer":[0,12],"remov":2,"render":7,"request":[0,7,9,10,16],"respond":6,"respons":[0,7],"rest":14,"revers":4,"room":16,"rout":[0,7,10,11,12],"run":[4,7,14,15],"sandbox":8,"secret":5,"send":7,"sent":10,"serv":10,"server":[7,10,16],"servic":7,"session":[10,11],"setup":[8,14,15],"shutdown":15,"singl":14,"skip":11,"sqlalchemi":15,"sse":10,"starlett":13,"start":[7,9],"startup":15,"static":10,"statu":0,"storag":14,"support":10,"task":7,"templat":[7,12],"test":[9,16],"third":13,"tip":[9,15],"togeth":[5,7],"token":11,"tour":10,"trust":10,"try":14,"tutori":[6,16],"type":7,"unreleas":2,"updat":14,"upload":9,"url":3,"us":[5,9,11,13,15],"user":6,"uvicorn":4,"v":13,"v0":2,"v1":2,"v2":2,"v3":2,"valid":[9,10],"variabl":[3,5],"view":10,"web":[7,11],"websocket":[9,10,16],"what":[6,13,14],"when":13,"work":16,"world":7,"write":13,"you":6,"your":[14,15]}}) \ No newline at end of file diff --git a/testing.html b/testing.html index c6c7bc0..6218dea 100644 --- a/testing.html +++ b/testing.html @@ -295,6 +295,55 @@ just like in production. You can verify their effects on the response:

    +
    +

    Testing Rate Limiting

    +

    Rate limiters are just hooks — they run automatically during tests. +Verify the headers and the 429 response:

    +
    from responder.ext.ratelimit import RateLimiter
    +
    +def test_rate_limiting():
    +    api = responder.API(allowed_hosts=["localhost"])
    +    limiter = RateLimiter(requests=2, period=60)
    +    limiter.install(api)
    +
    +    @api.route("/")
    +    def view(req, resp):
    +        resp.text = "ok"
    +
    +    # First two requests succeed
    +    for _ in range(2):
    +        r = api.requests.get("http://localhost/")
    +        assert r.status_code == 200
    +        assert "X-RateLimit-Remaining" in r.headers
    +
    +    # Third request is rate limited
    +    r = api.requests.get("http://localhost/")
    +    assert r.status_code == 429
    +
    +
    +
    +
    +

    Testing Mounted Apps

    +

    When testing WSGI apps mounted at a subroute, use localhost as the +host to avoid Werkzeug’s trusted host validation:

    +
    from flask import Flask
    +
    +def test_flask_mount():
    +    api = responder.API(allowed_hosts=["localhost"])
    +
    +    flask_app = Flask(__name__)
    +    @flask_app.route("/")
    +    def hello():
    +        return "Hello from Flask!"
    +
    +    api.mount("/flask", flask_app)
    +
    +    r = api.requests.get("http://localhost/flask")
    +    assert r.status_code == 200
    +    assert "Hello from Flask" in r.text
    +
    +
    +

    Tips

      @@ -307,6 +356,8 @@ in the test rather than sharing the fixture.

      thing, but it makes refactoring painless.

    • Test the contract, not the implementation. Assert on status codes, response bodies, and headers — not on internal state.

    • +
    • Use ``localhost`` for mounted WSGI apps. Werkzeug 3.1.7+ validates +the Host header, so avoid synthetic hosts like ; in tests.

    @@ -347,6 +398,8 @@ response bodies, and headers — not on internal state.

  • Testing Error Handling
  • Testing Lifespan Events
  • Testing Before and After Hooks
  • +
  • Testing Rate Limiting
  • +
  • Testing Mounted Apps
  • Tips
  • diff --git a/tour.html b/tour.html index 2636ddb..327f57e 100644 --- a/tour.html +++ b/tour.html @@ -581,6 +581,70 @@ response with a Ret can pace themselves.

    The rate limiter is per-client, keyed by IP address.

    +
    +

    Pydantic Validation

    +

    Pydantic models integrate directly with +Responder’s routing. Set request_model to validate incoming data and +response_model to control the shape of outgoing data:

    +
    from pydantic import BaseModel
    +
    +class ItemIn(BaseModel):
    +    name: str
    +    price: float
    +
    +class ItemOut(BaseModel):
    +    id: int
    +    name: str
    +    price: float
    +
    +@api.route("/items", methods=["POST"],
    +           request_model=ItemIn, response_model=ItemOut)
    +async def create_item(req, resp):
    +    data = await req.media()
    +    resp.media = {"id": 1, **data}
    +
    +
    +

    When request_model is set:

    +
      +
    • Valid requests are parsed and the data is available via await req.media()

    • +
    • Invalid requests get an automatic 422 Unprocessable Entity response +with detailed error messages — you don’t write any validation code

    • +
    +

    When response_model is set:

    +
      +
    • The response is serialized through the model before being sent

    • +
    • Extra fields are stripped automatically

    • +
    • Type coercion happens at the boundary

    • +
    +

    This is the recommended way to build validated REST APIs with Responder. +See the Building a REST API for a complete walkthrough.

    +
    +
    +

    Content Negotiation

    +

    Responder automatically negotiates the response format based on the +client’s Accept header. Set resp.media to a Python object and +the right thing happens:

    +
      +
    • Accept: application/json (default) → JSON

    • +
    • Accept: application/x-yaml → YAML

    • +
    • Accept: application/x-msgpack → MessagePack

    • +
    +

    This means a single endpoint serves multiple formats without any +conditional logic in your code:

    +
    @api.route("/data")
    +def data(req, resp):
    +    resp.media = {"key": "value"}
    +
    +
    +

    Clients get the format they ask for:

    +
    $ curl http://localhost:5042/data
    +{"key": "value"}
    +
    +$ curl -H "Accept: application/x-yaml" http://localhost:5042/data
    +key: value
    +
    +
    +

    MessagePack

    MessagePack is a binary serialization format @@ -589,11 +653,15 @@ high-throughput APIs, IoT devices, and anywhere bandwidth matters.

    Responder supports MessagePack alongside JSON and YAML:

    # Decode a MessagePack request body
     data = await req.media("msgpack")
    +
    +# Respond with MessagePack
    +resp.media = {"result": [1, 2, 3]}
     
    -

    Content negotiation works too — clients can send +

    Content negotiation works automatically — clients can send Accept: application/x-msgpack to receive MessagePack responses -instead of JSON.

    +instead of JSON. You can also explicitly decode MessagePack request +bodies by passing "msgpack" to req.media().

    @@ -644,6 +712,8 @@ instead of JSON.

  • Trusted Hosts
  • Request ID
  • Rate Limiting
  • +
  • Pydantic Validation
  • +
  • Content Negotiation
  • MessagePack
  • diff --git a/tutorial-middleware.html b/tutorial-middleware.html index bfc84c9..3a395de 100644 --- a/tutorial-middleware.html +++ b/tutorial-middleware.html @@ -145,6 +145,44 @@ and the response last.

    the existing stack. Keep this in mind for ordering dependencies — if middleware A depends on middleware B having run first, add B before A.

    +
    +

    Writing Pure ASGI Middleware

    +

    For maximum performance and control, you can write middleware as a plain +ASGI application. This bypasses Starlette’s BaseHTTPMiddleware +abstraction — it’s faster and gives you direct access to the ASGI +protocol:

    +
    class SecurityHeadersMiddleware:
    +    def __init__(self, app):
    +        self.app = app
    +
    +    async def __call__(self, scope, receive, send):
    +        if scope["type"] != "http":
    +            await self.app(scope, receive, send)
    +            return
    +
    +        async def send_with_headers(message):
    +            if message["type"] == "http.response.start":
    +                extra = [
    +                    (b"x-content-type-options", b"nosniff"),
    +                    (b"x-frame-options", b"DENY"),
    +                    (b"referrer-policy", b"strict-origin-when-cross-origin"),
    +                ]
    +                message["headers"] = list(message["headers"]) + extra
    +            await send(message)
    +
    +        await self.app(scope, receive, send_with_headers)
    +
    +api.add_middleware(SecurityHeadersMiddleware)
    +
    +
    +

    This is the same pattern used internally by Starlette and uvicorn. The +middleware receives the ASGI scope, receive, and send callables, +and wraps send to inject headers into the response.

    +

    For most cases, BaseHTTPMiddleware is simpler and perfectly fine. +Use the pure ASGI approach when you need to handle WebSocket connections, +streaming responses, or want to avoid the overhead of request/response +object creation.

    +

    When to Use What