From d9abf7d31c71d98fa11cf438db34e80cd16eec7a Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Sun, 4 Mar 2012 15:37:04 +0100 Subject: [PATCH 01/40] Updated screenshot. --- httpie.png | Bin 62052 -> 138364 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/httpie.png b/httpie.png index a931af709a342dc9c0822c89f95000b8a6f858ab..f5642a8dfaa3e17cfb950f7c9205539a35a467c3 100644 GIT binary patch literal 138364 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 kJjZQOaE7UZ?f);p0I=#*Y<~>m8~^|S literal 62052 zcmX_nbzIy#(=RO)cPQ@e?k`1%>WG%90P?-w1FcV^H5lQc>|J>9I;Lt4vPsBNPG}4@v9Zm@S;D zWp?49RCmWgvZ7Fx5p;Xqjm81k#7keH3h^X*pd~(-imB=@P8FP@Kvj!KNefX?o#IAl z=&oD`9$h`*=H>eeOjz~_zc#0D$H|M5F$iVmUcPO_zjcMdj6J`gIm(YoeOk?WS)-iH zAMs5>Iel&FONfG)peFojd71h!PjlzX!9I!_$WJpae#iWS zCWZTQh^W2Q@UCrdc_q-JHqerq+BUUq$?gT-z!_W|$Hq2puEQ0mMhNF^S-$l2d^+fd zI)XMXg!?E)clm+*yQ23(g^*N`GrFR;eB@o!+kS}{E0Yj8NB^8?woU{lh6u2mrpP!M z*xj_i(X^xE_rkv2d3MnrlnM8SA5-{jtn~>>_gK`zk{xPonBLL=-`pb;9r>!g(GbJT3nhQC(-BVwMHjkO5_BSLhIbay{$jf!$__~{n)}6r zj5;)cXJ*KTsfbvPycm={rN7fu#mu5XZw1jF8g*yM z*_sc7<%3T6$w2K6i?fLr)ib;hN2%!Xnc)Q;( zB>-gcWV2+^=sFn8k#Lb}!$jsNS6ERpt`sAQKV-2$BBi7ps9Dj|GTIb5NoYwH<5D0U zY{ZdRObPm;Shd+ou_f^(d`Lb?%wMwMS&mU>tc;9?;hx38y ziQFnKE(aDRmvNN379p0&7fn`lN`FiE68a_T3!G#G#&D&14ck^Gj3UheM>z^-q~7qU z>2afkE=r9s54tb5L1gWS$gr}-a#d9oq*ANWp%S_>r3$I)q>5ByPAzbVeFxy;!>412 z%mS?wb}}qHR=aoQg=tK95u7k;vr~O_f5m!bzy(7fM}S4(lueawo{f`@k&X5fPhVW0 zSf6(du;#ZWy(Ye<$xoRbNC2PPnxWFW>l);a4kv0*&Y9NV1B4B1lArh9;|zkPJLpK1;?jyq~j3DSU}JV`4a;iWduP4t_*<;^ca#dUIkqR^P%{xLau)qk_J%`U|B@& z4}Son7N8eEn;@DHZzGGQn`CWgh-UQV1S)-(>6h3^6pQOe5|1rxD(o{2GELZ_k&6TY z1mrrUd>DrrEGbgyG%2~5V{!jr#-rDv2hap#s^K7D(tpOs42xoje2l?~L5&_5#vb`N zEI$%Hk_2P`76Cs4u`u}%h@*6)2%`AqtmWJ$uqOyyFYbH#tRtp2umGx*Wx<*yy|Uwo*F7z z7Y)W0B8JUI3W9$^fr&Om5wEHKA|K|RVZAttV`mGCPa&)bH zXH{;u;b>rMl85S1NuGyZ3MUHtF(9OXx4e&yz;(mUd<`=zW+ z{{D{NpU!|s>c>ru+opkAuTnanmNl2Jpe5jdXhJR)o=6^DC(0+v9!@u6K78JW*AL3A z6gr8#LP|mkLd)GZ-H6@V-7P(CJsJL7ey)D$e%yX;e%p_B4|&%Hcgx_pdlQsjNOXt~ z*tSGo?9QCy43!MFyestWETIg;lpqf}Nn6#U5VrG%hlX9}#>=J4RrueL-H|P_&Eu1F zbbrM(zj9ITlP%&>61h=WvuJa+@_8`Mve&Wai->UbvWj!bnMX#lCWZ=nLnJU@fnafUxMx6Mj8skB!wVPX6Z1>#Z6@YAeK-kUMV zgiE`|z))vU&$ZLCd8x}C6nq!97GsFJ$m*E!DOD+*Fs)59kpawF#4=*+ z@psy3+Hsob4~c5)`ZZ&J)mlv>|F~;?Ym^$Aa%)KE$!!tgBd`8f>Mv6#nI{V;;{J*+ zT{$GYV}#QLorGzGUvpq`_)6k2sQ$+zfx zr`&n3N$$3;e7lIFhzav{^Qw&kjF2|ZH#P3>Hv{kb4+i=rn~iJnQHc%BTz zJW7IKtcr5G^0cy#O0Pf3^YdcN3a+5W#NznzPyEiT=ZsudM&qdNA30jNJ%SaY%e+p! zqAfcu4Pb%4xA!A^PM1#L46pPb+mpRL&Gzj=H;!*zBWagudB2zLZ!Q!>-~(+RD_mcwL1PuZwozUJy+nbS~LC=s0x-#uZ!i}4qj+r8!nzI6@IN1);DuVW;KYMYih z^M=A>#yyAXORK2%3{IQzy2uJejmGk1*Tn_|i_KI{q>dYoH4W2DDj(485P_t@beE6l zoDT#KGB6^ErV?C(KPi?{dAE5R?}2WZCCT??*=4L#mJ=lDNU5HhzqGNnDCqokj5Uun z9Ml=rM9VQM?W)VFnCpg0rfOs=64=G?p4m3I^f?2*a(orA<1u~x1&p^U`Hgb&mFIWs z@~Pv>GXI9Vz5ADqWzYs_p}lY5_8>^0P2e6jLEAOMreN9af>*@E&-0}UIujZaJRJO4 z;-`etAkm;d1(0G+T1(ng9SJf21P&uOM2TjKCYHa;@G*k##4}1a z%-2#2sDij&r0JxY)TwK^8K?Z1?>ToKs^{rF*Ytm#i4M;m9W8G?h)<7b%l~<|P2x!S zwV<2x+x_pJWn#uW!p+MkMYK@TAEHg?S3X4dRJCm&J0laFx6A(1ou{I>-Ls^N62ZCF zQJzszrS1x^^}(17jg&=7&KFkFJ|Dg(+d9txOS6MpFmM#}2B&TMF+NbrRcpUz3oa$W z`s-tXrD(I?Yxmam{(B?BndY912U?0|^h`C}b6Y z*c1p@Qo2%AQf zi}`DQ|L~WiHQ<$ERTf?8U;H&cKCQb57){-dogi}PwYr*hUHh`~*r?QYCfw!mq#a>B z=2MaFpEkSCBK72EG)KaBoDR$fB>|ML6t4vijer{a1{ceJxA8CeoY`!dyaYhsj=rpD z!!RUM%M0oATASG0ZZtjwhn_?c!^xobh;%2xD2$Sn$qf)o5 zRWjD36>I&~VXoe+4_l@(nd?;3Hqh~G>%BkF9jYE}Q~Ek%z}!_^x&FX2>TxI7?J0LZ zEC>?d?o{l`yMPmw_3=7a(^6UAd!=peDR@GEnT9SE4!LyZRWMuUkJ^Z+r6e0^ZJ_7|w;C;1*;ixT{nou+dhG z3Z52P)b4J_%TLn(^8Rr$X_N8%+gI>{@v!Ke@wR>XRO?2__n~eOkuM4)D z$lmC67nAJf6}d!>QyIKxyn=z z1%LR=sYT5l@QvV>IquU8d9Cu9bY69*mCwkdH!OZQZCrBPp3&g0{qA1XkGgm%{7es-D#`N^g32>MqLspIwruW;+QpfQ^h1F61=wWxBSITXDr zmn?%W4}e^gT9I*sZjfd{m_bN@pGL4%=-k@RX3!KkJ&-18AY&@GV!5HFhzOV{u1^pZ zoX^wuY`W20JI>^C?Hs}1Z+^!Ai7(2rZ8Kw|a;TV}GoCl?n=h)zrpM4y=&8GDkPMpDy zTKTs9wbHeb^Tc!T=HB_v5$Fhbj?>P1C3akNP8mZ|F_y0q>}yd#bDQ^fj)ab=n@v;1 zkX@ZeA6#R~#wI1Vv`{p?@CAG!Cxc_*1_-=Lbb))c#V|vwgHkb+6Y>M)OYqGT2nQ z+eQ>;I5V;+bq($B)|W8T-@m~lVUTN$lOTpH6fzuP{DhYr2sJxM)vr%f->w~8-5I?E zco9D{OMF+aGLr6=l2`xI=!nfc3H>{=T*9|-y-K$VSY>SblT9mC;28c+xJB@mO_|ga zi8Z=UYzW|%o*sP%L!5k0B^>`s1dS`nEgto2=xDfoIJIAK#&EQFm}8h=I^3$-tj+Rm zP;Jm|xMNmp)M21!Mq}he41j6y@DURA%nAdBagc*q$W%>gh=@!a_nnt+gmGa;NF6S; zY)tL@*@WCO&A5uw!2~h=o2y}%eaA{->cQ!ra9v40=hNuD4zYYf zeZu;9_bL5TZFpsvbttnG9za`a&jM&}GPX{8L$t)VK75ktG( z)ZO*Eb-8ykN6TBvQ_;p5aP$@s_}n5o<@Cg;e(Hp>AqLNf%przv3zN`~tsC+SowpQ5 zPf}c!!5!gmu(cU_EU7g-Qt*ENnwirMOgoDZYyiqDfjA%$LkGQD*4q-ZiF70kQBqjU zt=M9|BvoG^<1gVT^kR(GptgFmTEWPGOH{kc1JpCoOh7h*zRVgz=ZpLGjrdItGA;ac z=oe|FQMGcYa-)NfIQZ!S(YJOh1S|J0{d`~ejXEw3i8qpjf`wAL?Eol1o8IbY%MUC; z^aJL}If>tYMLRdkHdS`u#jFH-)dGS`i?BI`rzy z+SRJ{zuOhO3wq|ae((R%`0dHf_eIx%%l>&LbzO04V-wh5RrOo=#M>Y?ucjwwNN>zn z`DB)YCI2bLNM^I)T!7>Xl#|c6H7F9$`#azQ8U&pHa~s|e1{?NGx9r6KmKjpR}WpY-N?N>RCg_4 zzT?zJYR0NfKK+NyZ*OiE-pH2f+cv_5>p_lMle12t*x#?rq;$ge~ciwk0Bba2Do`OXFF|2GXHnMWBzzSxR|$s z)PjuDkBZ2w)Qrg@*~(}5bn-cjIz=nDC4o6LuYYTHcW9!2b>j2v%#`r3TdGd_JxXKd zTzocY1dI>8ohD{>uVf51$;)_lN6pd`;4;= z;#?xP-0<9E!_&LNF6GX~u8Vs*^1d73J?f1eIOMq&n&BgFNUg+|!G>LO3=6f+d6Y&8 z7b}F^sF4UhG##oa8s3T{VqcFz(c7o08ZL967rnSxTD|yHr`eIiT`()|m;3?-5#34u zU2#3#Pjh8gjNV!-zk`=~>O|{$bPIm%ER`+|&Lej9tckd^RhRr=yzPCG%py6uQgzZZ z0ezoGpSx_EziLd6Dn68{kgyRl>6n8sQ!(Wmd@;;7{6sqZ$55mIvheclFlRyeG-18( zlyskw_DRrRjL!%vk=4_4Sq`eu4eBAOr>je&vFm9Mvuq_3wvh8-Zu9ZNP!diIHA)Ug z<~ntf2C{w8{)W`IrHZw>uKVdd;*8)dtLFv-{2iJZ5U{UT7T$|@RLoq)ceDoU43{zrWp4{Uzk(4)9?4;ZE|_S z-@iY6{(3)Z%xM@o#Eh8J{eRMp@MuCR{2w`Yieu1y`j5hhir`a&|09WbRTz2k|A<_M z?qk{i`X^Fi2dS(6N8=dLV)XwT6$C#v!P0;HF=xhFaMkL+c08xyrH@JJrh++Za!F+W z&JlJsvcWrm#Z%hioWmLdkOLO8@?(P_>ZF#-{&o zLOj7(ge<qI}lw@DU`W^u()i>q5I{KMI<;;=4eupwB0d16V9R+S%9I^Igqk-Oe-vhsg3TX4ZpuM<_chtd(M zaX1#ZQhiZ`UxG=gupg#R;ib<=+|uol`d{B4rc?@_b*U9r7qVZhDda1-qO!;NRTBkW z8YR-3Fe;MJf7tJjr)vMVS(*{Qqjos#X$}`>#FG#C^}MAgkEaiWvo_cHw(SNFL8QM*D&IENHG)*3kG*J^&Xe}&KHV@>#A&9wg{ z5Bmm_QKvc&04o?b=r>;xMFnjg!UI32dyb?(KI)$BCl%;tEG1<^W@C%5MXkXkP9&u z33#thZj>n+S13L~ITqfut~(lBhOzpYX>$?uXfOW6Z`4K3nF+TQY$T2u`Nf6O%#*el z;}4aTft;kA+q`Oj)EQrHH(>%1*lS(&kGp4I=lL@Q?_#*ItsA%}JhLX-n^CFK`INJ7 z!Bn4HAxjJ9{HpoQyuSD+S5f<8FJbI~;ENoYb}f zO6HNyJbcyJ-=oy-UP_C}>(b-L-_4>6PXs)=@@%=Xr`K0@7rwdb1&#DJLdS@9ToaO~ z{-(=Uj82<4!ds_JxsuOlQ{$&DQ<&h)Sty@cu6Z8)8fu^VJX6p9M{mO9y@-C6e_h>o zYF;&dgv4~uxqeE^f{^7HI!X8G7Hp-Vn-!-I9z+BKc!vsGNd4@wdpdY7e9~s;K$|IbJ_D4 zL?;uhi-R19uB^Taa^kib>Xa0J&6egOP@<2qSB?Fq0oM6nAr*x{chRWiKYR8YFQibp zD5|&x49YIaA}mE7h-D>K#7>~BTZrdRFO*Vh=+j|;Nf!LMF#$Ma_mI_#ilaoch`>G$ zQ=fEkloc&*ShWXGBw6AY&)Y_GMEaMgPu_pF1NlaA{8PIM>bBBpt(hL>;UH+xWeOi+ zU$O!aKvWzB)kKr}vWh21<#~*Yg{`Q6egyBMo%)O%yJ&!OmT{Wq78a3QBX~X@6_jigajU&6>DS@A z_mhY@4wfksV_z`6d7L!Mze-Ey*CaA3SY#(mSTNdP=`j0TSnj!pWwD*k?p8GgK%f^n;mUn z*_-_9m1y7goapnA=;bu$+>UEUG8F?(%>3qN9*|uD#F$GEJU$MXl&#?)$Hh!T9py@& z(4vXGH}E>{R$AIcfFQAL-Zve=Gw76iT?Vaj4nkDpCSo9yWGXulha8gP}FGM*v2)j0Mc9ywG!xz z=JawwgL<|#2#j$ubzS7Am!}nIsJUs>jrF|m9!g<-LtEG1GG9nlCzz`y$64g}yF_0% z@r%iOYI7Nh{+h+^pxgvKRf4s8IZ;BZCk}d=*heoB@h&wd%9}`B*H4wyHZ_Zt(l1%x zu>BqygyFz6N%5E5(u`*c{YYF94|odZn&((n*Dlq~c_Z5zZHC7WV>; ztyye}{F)ZRhITDi0iExPUXeBdKCVQ}%o*VOUYUwYR*`hSzt?mMc;(57Q>9C_XWVT{ z-)HEm;+!z4yKX>bz~^mb{+p}(>e^fUvfuR1cxkRwj&*V$U4#qFyQbv}o~C&dJM`Gv z{7Z|8h%rMEsFEjL%j*;h_SCRyOSy=reoD@I_7r)c?7bedKB#+ndjQH<15a0{F5dQi z{lKpZ4_B-r%3-r{D3(B3ntTn$rE*Hykg1dCdbVyf-Zr!M%P;jYsIY5qRS6= zKQCa(=620zm$JG8Z^{1%_lEIq8P8cU)_q|6mVzXef>LOUG_RapPQ7_XQCrjBlnft2 zp3ogjNuuXH;t$w-zn{t#oFk^=B~tUVt|B}+%w>L~9Frxqd$O~NuTAqf#~@$Ab?E@9 zRmIn0hfe^4j&5+P3&T~#%ZoNIY;Fh;`1DA8jv~n@X?e+`8YnP2j<#53YX@*^=UcNrC>flhZSw$?J?^!2N`j z{Hq1szj})@>CGZRSo+(yZ+_@F@aS>UE**w)6m(MsyK@%o7jic3_i{s>yz*p5bgU`3 zUliGKU>JxiXJ_74Mz%cZWomt9Of_39fII^=qWYibhC^`#|@Ao`f`K>8zYi zX0c1i8N0>}@G$YRJxw*e_9~U=B7};$;@1FO(Qd9JuD%GAOk~o0*3wF|I*x=chO;tw z7#+`pk(SAQx%Kwn9e4~TCB+>h6u}wmN+9wzeG;Sc5Vcn@v_f5kp|nMgP0Cv@T<>hc zcK(d#+njv2k09F1QH4-P1*h@%&T9zpP-He240u}MvL7b(XzdqyeJBxJG4>ZWdF!&W zt!2Hwb+SLy5Pd>k>=t0_cN6W5V|H`eN6Jv9#DT6acd>uEeg>Mn4Icy)+GDi6Uejio z90Ug$JwF9H9fV(OO^u{{JYDaNLNU;f^cK?OsskNt`=#`4JXmbC-x1+J;JmIXwynov zTc$;?sQLoW$y7&~P2M=td`Wy*hP79g4UdQ>5V$MI>4X*TPrjo_HOYrIdD@;8!C+L$x(Uf;%O|13 z&l(J{2GJXNu@HMF8-)$UPo3&&W6ygJ!s**i&kYg6@0<&S;~;+*RQ5U@fVvBUdfXw4 zgRmHjc#%=RGN+o*Su^2K3OQ%~T{GYC<{?5Zlyb1$9p+AgYSk4z7b5)KGIDA!oC_p? z3#Yfg7bE=bHre1!W{JdsE*!*}PNq7~M!rs_Zyft$VxP!=&$fxFsY`ol^C&pukS6jj zQHI~OBUYYz@(YhE){`}2?THWAfuw^73@^PgH~on@K#By|JNOG8njBf22QnpX#4|{t zQlenQ6K@U1O&lV0C7k+}ilQk1AzTOGNv-~xbfB0lkbCv{nbtqB<|Q&f23f2J=CrX` zsc#EDKbV|@@-tX>a!7OI>mnjox$KqWbZbJo`W~ISIW7YN9zv#^@9)?u@8`=}Fk6lR z6fT1Jr-;sUnYM&RwA+q{`=Z-(lR16EZPhB5Po&S`Z|yGuz1Ib#)D64!?s-phe(fUT z>vPZ97tbz)Umbhn>)twI;L?@MJ#Hm>-RtsZ9BBE*4kggs=btmSn_BF+O`h)Jgzig7 z-Im+>K2C$){7y`c{6M}N_dAq^?ZAS}zelu~Im3s&FB-E|u~)#nx8Z_UH(}h@zXH(? zJRU+1&;fVTFAiQz$@^;zx#r1W8!M!A3o*#A%cZKtDEg-Ear`P+EjL2wAo-Sklv57p{;P9=-^?DQrolx(%oC+W@@Xis zC^@b|QQk_@o+gl;Rg$N;_+^9$n*A|(@AVkO8rwwY#z&+~z@Rqj%$LhlAr#F!X_9IX z03YR`2J5X!Pk5sUZd>I#^*{qq0E8FYcd^{y^NtSM{Rx`=37k4Z%|3An>IWhvygrlg zAhR5sGnZE`bi#%lMxs!Z7u(|J@5Pi81$vrtg6g$G-I=@0k$S*YgLjHtSK(?SN z!DTCBaO3joyiN`9k@TvwH{FBQdOq2FlN~V?O+qsoE66b+Cy2sq@z#a36#$U#e*IpI z*mjUvymS6(Qqg}$q9U{%?Z39|`lK|4cZ#CQFM%Pf%C}|`FO&qPhaPshTeq_yHg08&mSa+2!$7UV}_O&Ime10 z$zDZwu9X;n!wnQjPK<7Zm@d%Y^R~p$1 zWq`K}7RYP%pic=drNYXO7Uv9HN_*o`#v5yz+47G^n=KjN9jMbn;A~H#=CK;hVnz-X zZ^JCGpYpDJ*0~tUwcKj<;nfOxg(9`p;(A`tjch|7G0_@S(Kkte5Ydf^%{fO}oT(uL z^o%YAG^}QR_;vfG0>QMsGa~>p+M%fpBQz@9yN#JIJa;*qU*)$C$J=li7%-71>KCSK zMZML^^F!3nu8A~H`Q4%o^f(Emfn;Q4Trc;%rrr0wy$HQMUu$Y=su~&19L(fo@j8)g zZf?>Wvy%skbA&z18Ntclkwp1l#o`dl(I`tt#HK-%!Q9qVw$nZ8do8G`eCc10W@S^^ zR%by;9IrI>pRshqC?-os1izv>5So-!{Uow!B&{tcke>v?{HVs-JU9QfTUy(NwtdP! zBv5xGJGg?an5`spF$F{Hu|WdI)0U7a_=?y*gE|b0Ai%W-H}u||#{tF|6{Aakf57X0 zCZ*Tawts^o$%&xINbsv5g^DQ0hzf-VK*I=xETzpV5=6^VB?A{ej{$muQs)y_GEma& zsmQs@9l0#U)cN-@3WUs)KWjZtdLv*m^qEmg*MN(?!E{S}^%6_spd7i^rsv@yNfIr@ z4tPq|1)Jo))4TNT#H1-E>1iN=*=6jzQ&>H2KvFarLVcB(B8hFcpMawDkA)I0`Vzg2 z#(eM;_&}kNC!i8=<>a-%{j=Sq-Js<4Z=a3Uvhefy`P-QAV@8K{fSk~_EWDB+U^xn} z#fqS)7w67%m0mU-!QMkq`6=<)H-Tit@t(cw&zNt>*zwu*A`ipvPA_Mr8%(}1sV{t9zLY2vS+IO`96x0^K#kE};)MfWDpaa!#+XQQ5d zwnY0_{|L>}(o$kZ#@Nmd*}EBTx9`N{1`OZ`YGMau zgG}(0bIlhTGk1lMX%&E(_|rlfV1MbbdGty}5S@|!UOju- z8Oy^D>ODePO@DW3DR#?Px?j&8C z$|FnEL;;6TP8WicA5AbwJh6S5wyughmC1oR{vJk8KeRoxkuZ+8QJ)p33Yl9 z7wvDN%FohExe5Lvx8Z{c1r?#-=d`4!Q64UB!SVBzZo+vzwSlB8B68-%+}Ayd(DP2K)YkJ@u1AU zQ#cRUkXrR+ZE#TynaNqPPq_TWnC5q;&zlq!@QaIU{g!qU=EvY7 zsO<9jKrdVa!F9+s+_vQ6?Vp!ySmcYXi( z=)~lfIMoyyL>s@X23XgHHSWynw^O|E2Ct%OYj+6r( z54s=AYIXiH;!&r@Do`;!*dyJ32l@c6_!%Q(D;uKp5IMFsNmLX^ zs6J3P>_91v;q_F@+BwAdE4KeIcDl;dT-Y4Hra z;&_EXrwwlpBK`6x%tPt}V^O@_ag%gh*kJqreQR?6i|nXx*#9!OHRotLaLemQTuh#HCfYua{*6?2R|*PePk z#d{692$)Uj2UoKe9oEme-K(4fFP!?aMyp?=`jB3OMY}JdL=AAAO6W-+d~rf0a&5hX z4tbf)cKNm5b=%D?%5B8B7^{qLe8Hdpd-k9w_Nf7c#$LN&Fdu`=95SR{NBLDhHXR}W z$%T@X?Fl8lfXlH|_>!KK%A{DW6I`7BpFVM=xMjVD&lqvo(;_78cC+^+sm^#E zmt~xXk+Y^Q9xF1`W$qkac{zsetddLp@hXF zNP-U`6Vh;OBdowF@A}3loOgkFBnb1pq7cVql_{Fx5Njka*NZk)Lz~GvKW*-iQX(XTI{hiRWgtEyn$^+)F)mZYB5Z6pBu%$2}ajfk7oFXHYUkb4L(?<^vTlx zrLv^AO#UIiy3hJ&GD#+PkPj(q@*2P~B|82`^d+()!D#qUv>7i@4y9#;2Nw1W8)xO1 z^d|-a%FaSCk^Nc84>JbHfHEr4870x5O2^FDWmMtXC%cRHJk2+Tx=SdvERG8RFG`UbVd;8KG_dVxWw3|N z({C5^)~5#>2Pe6ppnxNY4G(!?b5rTvh4L_;-wgvt#WNCyc6SSP8?!pFmIFMf@_w{L+P|H)8cBU_T~SG8TJ~>^NO>^=EvB_sF14+p9t982m)^(kqRzkyhLJ; zUrnWG{2%vyJx_?XEvlweEZIGJKKaxGXH+NEgoiw?@W(B!oq(~cCxnz3eH4y($|V+XvIALBs%AZfZO)jTN;CQimZ)w+oD>x$j-af z32<2pH$H2CNg3a*IvsEu+1umeV`@|6wlkmN*RNmIX;wjfKDU2!4*M0heWqIlK!vUb4K)t%V?+)RGzo2WGwg*%$0TDsVs8M|Ld>-*T>2hp(1B@6nxz>%jIPg15nO+eqQ~~@VEPd=00-bEIP3Du1#{2=y=ZvZH?ym12#_6zmmH;DB z8M>4lT8ntiP3itHOY=w^j}#y$X~!M_AfUUX9;+tvs9TZYBWXG$~7g84$e$kGXks~z_eQY#c341ST%!qoO1{lq`<`!LsQnH?-Kpu>icLXxszOoDe z(;2*5Q+>&A$JBwPhpfljtugF3-RW&+523DvRiR@v#GFr3@=o0zifn2HuIz(|cJiKz zoc4rrf7lXI(L0aOCG0?ajjD(cCAj$sKm-o4rn_m8SQC<-$0Fhg`Xv2b*nA>Nun>ky zZ{N7V@?H!H;&RLBTKeWhF;SCiWCu*5fDd%?EmpX+A?xIcYX>}R$UnIv*Jy{1-1l?) zh8htfMwZBhX?|0D;^PYJ&P78`GE^J2<&vkvmjCmfwPn?lHWP9;QqeyKiXI34H{qD%|PjXH4Fr+ltY%Zfl4 z>Rr9lT~_-SsUl9!*)(IMe2=Wc>pyn7{I|pXsbo-ge8d*fv;|CwvYj=Pp#DD;nVGqn z-;l9LdK{NkjMzlqar}OCZvFd5S0L+8&F^5Lyr~0kb#kHqFk(>=^FibiR-?S<(=?Ge z4k^~_Ovt=He&uS#W_Z%%FwQWfOoQT*6Ur>wC!zlXYq4F)-ZSwC2$5Z1`*WFfHC`%~ zjp+ImE_`Ow5L#f`w3YCY&M1;XOU+2w?#5XbOmICsI6s|0Sq``5f@;h%^#wr0E4Kv_lGY&~smofLD_P%Uw~ z)gBW3$*szDJt9wuVr69XAmpbN^T=vh1=7KE*#M#C$>^rtz7_S%(a!!TVV!knb6UiC zfLZRkAJ;uWb+3!ZEjv=8up+qr>P&F&defeRpQi8lJnKxUi~U+TE?mqCacaNQAuVij zta(JmEfadb|xj-daU1B$D z*5qJi_mOeklFu3;9X?g5CY;A({5P{r7+uzxO#srI(a2bRPh_~dieKQsm);(z&TZc` zQc*Mi=R(>)T4xjKY;**E4_<;5T!@HR(auc?5l!X9gKKC;$|2k0rH4?gLcQ@uJ<8cQ zO#8v!bs%UO%(#yPz9#-jc`r@k(asIcA>A_h6&ui@l-NrJQ%!o*@9tRMt?%O%Uyw7Y z_VLteaYZ#tegxc+?bdL)S}DG;fY)VFg&i1KKYhM^lQE{7={}C>AD+-751l$8%I_F4 z5Ivz8rrntRY|4yv^9U$SX_1UEh~R_wWcrr8-$D)fOuPZYMH#hfwN8C;(UQ_wT^?VB z%HA-c6J}+WQXHq`I2o}!?G$TQbWRR~Gt|I2w9vQvW|uus&IoRuNvw<;5VlevV%;eV zNf~b74=?1ZM6jl8U@DH+FA>(0bPN_;RmTL7tY|wkBJpw_%1ofZWorL^&stg5-X9{l z_-jZ!o_K54gmg1^sK?Oot>~-WwBX>7XT3suOOM}8I2wnP;9$Wkm4pNfi%CoL$Rgtv zANMaxn8*0W+pG%j?r%qpJ(lzGEc!xm5}tmli@py=uaB4E*q)F{qzTqXe zL$!04!V~eet$-+#9zVAHaih6IC;jj_)S!@@hl$0mGNPK6=9arg^?GEx$BL^k!t}u+ z9moWhD?ZjYqn7X(f?Ru_2Xd1CN7*|ER~CKyzOj=X8y&M_XUE-f$F^i1a`)bix$GwW<^vD_3PGb zB_+|S(}#ZCxA#)may6s8gwsz!LZ9a&Dy9Ap(eloOUm7BBW;@Y-Z1F#4hX^P=5BAvmbkkn%ZbN(X3~0tC-bp0 zkPzDMvfzHZr04j8l9Pgx`tWIya!3uQR*LG|}LytDhI}ndalMPjDy6+^aP;Q49w*%zX?9 zSmO^GUz+-r8HtP(5*liQ_0!2ejxkO*(3UD*7?*O8kAYAJvN0*>-UYviqf}0nD$AcbbEYj%2{nyw-qN%#&XA^sDhYGiZbFz-IT0g^B8$f}mHf)y1IZj^tB$ zh9K|H8d>`n54AWIFr3$5HXcm=^OB|^8J}Ufwt(%*%-#?i)pUc4@~5|wCC2)p7}DkO z*?!TJC0<2VHu*TQxL;d$>)JqT4#MvOHUh(Y)wzAua|>t#I~KanBtFqbV>l<-!^&b9 zg-76NQ{!g#c88HLd##bZVn8{49s)UL9-Cx(G>2cg8C6{{joJ2mu7f}Kc`h8IXlyGT zju%8*9UP!rOl}TjzL(g_6TrKM9Az^fs5D2L){?Eaorv! zyqOEr$_^j#JKx6&0K3Qy-t+f8KvXH3q%K((e9w{p@m>_~8 zW+8F-*UY8p)j?JAQ|(xteYgh?D)nirt{~UU_>0bGS_$fAIG)Xm#$n>r{?I613xl23 z58z3FsM}$cs2Uc;b-ibuCJj&Dbm>Zn2YzKkebU3IcD1FM^voi-w+^gR51$S}xe4ZM z=OcmkMTM?B=!{FERSlmf z)P-+?TX!*Evc>Khy+JcrBg`a$kRaaOD~(^=Kib8aQe^gKipl6iqPWm-=I7B=$gp0Z z=jm}-QWuKoVHbBG%~X~a*nOSTdvE5P>dExtxeWi~`lm_HU6E7swvoi05E$ z)$VN)YqeS5;7pxl54A+BF!!PhJk@#wFwsp<;4Gh#=OJ2o8GX)_`IZP_vuRFBHFpji z<&Wr#{VM)S8TS(v`t*1hz+ydTL>Cc?(aMvFH%4owjgI1YoC?vtN=C`e!ZgG1CHA1e z0B#*`N)*~aC2+5D%7QuBKr@*YJH}?mNYdmmoQ20^VK4E-bEx@Rd-IxoZjr9gQym=S z&gKmwY8dJIg=P9yvt$sL9A$qyJ8%cS$({rz=(sHWps7Ic_H4DdCO()kq#1VURnVCT zQI=^%SS=0Sy)NVT3nbRf?4897X}=a+`XSl;3&rQdG0*vOd&Yqz!}i_WnB5xNeJMdV zRA2~R91I1Cr##L^0d9!!equ`>jYJzG0b;+wA;CD?Izl|w z%jPSH{M#3L^mT$D$1xSE1V2B%i`QjJ;-0-&FMRCB00-oDaTWoOoogbxKZVo1QxCM0 z_l@#wRE1>CbCi)BAxo=nWL2(0j4kp^x~JiPEI;qMQ?p|0Zyf%3TJ-N4hE)t~>X+r` z+T?Z)L0hL6VH7taL!RDtyvr1GSQo2_G#nM{V&pO@vZQ?1aAjr=+NvPLI;x1Rusmlk z$E&V1V&Q*^>D279W}>)T@c$2Jv;E0F{Zh%A~^gBAFAgpf#6Wie~0nCw`M0=5XmHya&Ee9Qtb^7 zXYDz#=wVcuf!55K;Bxy~rA}Mq|^q^cwz80?=Zd(tXDZ2T6_&4 z>RwG&caM11NhZ*oD5E2TY!2kyQ0C>+9)rsgNcFQ#C+h?qe<4Kd?Mg2Ak*pFyiaE|? zuIk0E0lQ^HDta=NMnJ?8GykLFM|P#)pCU<@O;_sy2%2c??A2?Es5=X@=l4zshVD3c zir2L6+)O9D`h>X5*c!-L(_kb^@~An{C_s8pJViXxJwjpUkD=&8lV@Xg56vdulOm*J zo*vR}qI5Cp_5DQ@V@8C19_o?A3KI^Ow?}JCsj8CV;%J=uGwPefntd;L*SB6{XMCWD zp&8q3f5wxvI+iC*T^cNkJns30aSo2!)cllDeMO^8vb&o2TvJKZM+ENm(lkZ4V!@{> z!{#nGCL6aeNabr=o~=a3S&RH|vQY1&NT%^ceZd7b3XSaugM3RlwLSPrWGgJx>t5K# z^G`)Et6pV7*S4hbCC@;33Xk9-mrRK(FPX$_^%Fc;!?W_g5twop!P`4lW?`m7tje$T zN$zSt)p(btD+iDe9M5;+tb`w&hkKn#Bxyr~_ebv!xE}k-Dn@8Y=~kIQ)}Oq{bOvd! z2SdE&TDNgdk=`92g3a#J&c1^L(Vx9sf(gwg+;o*DnK-n?K;hjnY5*iQqj92fC{ttL z?Frn~5El;Yy_$e?K@avf5@|hyw~$exCvkGDFhWb)VhwX7LUJU&?WKl}X14O06ir%* z&l>`<4*~B6N`J`wDUkr3hd?)`gG;Hh$(iX{G{KqhGSp~No$p0Mp6hn-OY3zp!yFZR zlz?-v!Vpgt2EiWQGQWdhNm?&$8i()6HlReEH{5*odrs?by^v<8Mm9$k7YUWx%6}j< zj?cke+`b2?^J{2(W@uN&u1WwPV(QzWj}cKo@elr1NEvGmH_&k8qBY=#9AAH0cCxE1LHoxcOKZ9Mc`#&E9qg4)Ik=9QCMlND*HO<8}`bhB#ttihEGZ{OzK z0hDc325K$Sr-)1)60+uoI;d0>dJeid;$IdopA=sQpQ&nILbt8VT5h}=4hj8AGn?j% zhMw-%m>Ego-_I-HmpERQzFcu-Y-Z(5ZG923-fRIsJ(@Y5%e`W>i7|pHY>gqT|M>hk&W=0C~BwF+Y`)<@pVsrT#F0$XMJg6x`!sZWCVVSJ-ef zwjY$s_2NztT{-npxQy2Dz02c_Bymz>LK(eN-E$ZJwJrVKB3X>+OPpG;v$KXpPQ~B4 z#Nr%MEzn|g*Kaf84rfR-FUbn3AYWnD-D**2mzqv1CP|w2inaq9i7jrSgLSt=(_Er8 z176@_eFQkKWa>#qpQue+X!9mKi^oZ1VP4H8mAO%WazTZfrr_RBqTRa$7dzH{BXy-W zlv47_RwP%>qu|Dg*dh9KH1$RPA#jgj>!yve;u7T-sMyA8mXC4ZE_F?Y!UvXH9$-Efj<^>6z^8Fh)27_3ldYs|MjE4o70W>`ee%qd$u(B`&C-PT ztQO0{QCFZ=8%p3c_i~#ZB>^vY5!;OuKiv3xphtAgPF{C$Rv;I?ULQrE&=M09@V&yr ziKkOAt8YvlxA>Qyd#BxxFT<7oc3fn4(#o3b@ol;H<)zHdN*Yk(m1Jb zc?t02T4#Cv527`H6#SIYtUr!oiaX3hgM-wq?trL`S}b-P*s2&`k*mnXRH#6Z=kik9Lyh6w0 z=_}g237e0xj}al1lI(2tIG)&|>NZuUO+^8d>9c;!<+^MNO0Q|n>fNz2R%r{v!-`c- z(76t&G`4`DVklz{X^BH-Dz=U^BtFm2y>mWH5EIGf z;RF%Y$;f&9$HjIxt*pxK#Os4E-G!@1mQE!{1m3St$pg$VQFLnF^ic`#Kiu0AA{^D{ z9!ut(eab;0`O$oQOcn{y4=_`IXLC6rT9^lf4$ zaJUS?S@TPp!x7Jn7cb5>L`9GzVj!OwDM+??YEJy7$?r)JEj^-|%rYZf;^UVb+ci2p zmtgTRQyj_5`ra7xb+A;lL(Z!x$sO1sBRSTVIqmChKqj1BGjl?{kB`R(qh`jz497Ip z8B82F{U*lZCCFN*#Z$g*U5J{gPtaL!+*FiS{zDd5%bx@BnjkFcXdsNX*4?OCl)E^;i=8a-W$i%d5n z?9GM=DN6VCW>?gP%am}*_l}A7fQGu()))hiP4Umzrg)Ja37_n5uPhe5Y{aSg50;(3_8w}oyZvW& zGyG#SO??o18yww!jmX(dmRQ8n=8?pF8?h>FGg&ZqYOp(TJCBL*J88rUp;M{S(mCI) zqP0usz^!;U_V~601RLx7j%|w{a$u`fYH|)0%(P>K=xbi^*)v45%zCAs)9tj5sPTqQ zzjxGrqh2xIDQPzj)Z_W@_&IE!Sk98ML+MaHUBQqlgMqGc>1-@6i*fpy6QxHP)PDu1 z>k)^jfy%Lxh142+Cr=}(dccuESB&)vJ(kI3mH+B{=4_0$o^q^;j+c5iX*>G*#*u(g zx*WguW9=o0qiCz1988<$dbh)IWxNBf5M62L&80C%Rhl40J4>Ky0Fru`d=mLa&~ zNua81AxlGGp2)a1C4-Bxb@bgKMA}K?&8i3%&jDH&)sl3~cI2ws*7>&WkS4Qk#Vu$q zc2y?SeUCwVaL(&8$@MDnGGw<;KQQ7}yru@Mk8(RGIc}r79#Y$eh}&}$SQ^=<({z-& z^&=O=x*bWg@_Mp_@}Wyd9sZK^I_rqyID7DVp|MB%X(|HEQ3et+C?U{tdhcc%Oqrhw zNP&GNzOPL2)f3CkM}=_nF_<+YH}uXE(pAH1BF8gM>$joAT46eU8^s17fS{UArO4r( zERxDu8oib1f2o$-`JHTk=}I=8+0r7s?kdOg?7GrkOD3J`iNfc#1B)p|7|JkGjaAd# z%IUJpqWnDaw5~L>4@z>qNRK?8>x#FHmm-!^mD>>gY$HSWlb7-EU;=t zD{V8gT_NH8LF4DX<;DoP+~HL!g%)<}cD-P9y-Cqx5V2E;Cb7PM8<$us$T#l}qO+K2 z5KaQE`h;KpuYVRajZ?T-{AiDT_D#_PUWU(@d}9QqZjhfJ=hq}NYLrI-$+Fv1oWyUS zz;bZ)2L#qMZmz)+S@vpy+%`lXZe?74g_$;VvB=)w)`K~@26vvPgfGTj+l|cSHmQU8 z^G?%_l7_>Lg?LH8|I`A&-ug8il4wigzaC>)(b2@9AaaMckuLW)p?GN=kC}4iy%)!Lj zy$Lj6knzjs9HP<4N%y7jt?eAi2<4rWs0_pIBq*wUz0x@d4PPRly)h!= zAfjVGfei@#HMz29btc&6(w=sy*Q@TUwQB{Ux9vD5pCSBqgi1g=xcZ&0Uf=L?Em0R~ z&PyyVwq)NaZqvz*OsvN}67Kj13M+L0j z=EHz-&{y`}EO{}e(?E^ILIyz3aFzeh1z#j*f+kDX4Kk$4( z*T0aiHRN(b<+;c(puMCuMH{v`jf_jsa)SC!q2|b(AX_>diI;WoJG&>aZfDn?x(eN>Kf9VVT)#$c2m^gVk7s!9^o&A!u&( zi&J2>!g&MMD++6I%ha6o0OSHoQzZL1G%_8Usmp&vG4657JwaLyc3lsyv;Y=W61*xZ z=${v26@(54(7E!CJb*-GN?Aa-I%Z50tJ-#;xc0Rx8qxBpZ@fKK4qWq801s;5{#)8j zUDk2%CF6W@|M}1BR?w$G=N@<^ZTWt=u#N=1TCq&ml`xNmeC|M0?bO^}yaVcxAe=FW z@esW{A{ZeJkg@j~TO3aRYdo{Al|p?g+kUo#n^%{=0$~7LN>F>TdDsI&n7@cN`C^>f zmsH4z!s2EfNRS_StVHVYw5X4qGe|`Vx~upth)>@BKQ`Jhi`~A>gI97(l|>T)43lI1 z{rhnIET?zoJ`SqqvIL^wxMPp_r;<`|rz2JB2dJnP(m+|I2z3|ET`f!Qa&PcF<&>ug zL2j38_`KAHP9s(e#!OyXYi6LWCa>KA6>OPUDEZmaxuEprfmQD_YDm8*>t9cK%Jcfgn$;}OO(KaX^F{_wUWU~pQ;8Ap># z$t~}nhyzUK0)zy3{#V4pX9@8EJC1685-9TCGEu(ZiyT4EJ3(?{+R~mHlA$2}HZbu%MoO)c+Lo;EvEJt&MW^|3{?4% zAFtuun?$SU?e?~&BlrDdn`m^s;w>d>qnVhKN@$tjJ59d*^_-b-DFqdDJ$pJHzpu5}wVG*! z_a>cON@wWIP^XDu&%Z%F5WqfE0WcW&NM>Tw0KSI)Z{*nmD;H&VNtq8fBr@FF+ZQEp zt^5HhW<&XW6zzJ~wkVH}s^cqG&NXxsl!w7~AYKI4X!*uWIZ`7svEjEAPhts0P?ZUOT(k4bwG)rK4_Ot}$F}QUAGmU#c4I4ZoI2VjMRLg+ zpQaXO@4A1j$TaVUjiPo2WNqLz3ESD(g3c18q6xO&-7L6OckpLSrBYEdyEFnhmPqVu z0!6j~l@2bm{>BK@G>6qUgHCX!&w*Z&i8y*s2no)yxrq8){6!g53YLf^AWGCgx$Kkn z!?=8GZd3lBMvG$riEIh7x$!;I2KbJ_&$m3bUnDxApUuV4GU#vCzM$5v)L_m$c!W21 zq1Wm^gAbL0CX>x;(q$;{EyF&^v?S-uwAF>~u!XRenD`Tc)bm?O zSi2A{WV`F)=C-35yEv&Iz=vRS4h5HI2dBurBibDlz>{|dq)LNpuJmv2vt60Mhx`4d zOJZxjSMf1ZHFeE~6=rOWN*iEu$BLVl!85dQlm%jG>BGw}%$+6v0di2}H&BrYLtX@) z_ymqFsZb2|XDzSoL|tX^b`){y#{r_=%qyY47Vq|Le_ioYz-y=R)4Mix9LI;bcaf{o zCSp>NtTs0~*myYd+wD(I6u)?LRVL`MjhQ9TZp?AAz)47Sqhr@kXV+)34g^We!BK@A z*n$oZh4nQ>c>>DlypJD*LwNVS1#91O`xCiSIWUajZ4!fSLEc``W-tTuC0guJ5;=Em zSi*zEAS1^~v6&hP57~O-+n%~M;3bXw`pj-*jzPqqS0wj_O=O}zzguIE9Yu%esc^Wy z)#$@kq{1c<9-D{I`y#&`yB&kmlza_D0yTns1Gocpzwkg^$0}*)cey2-DeFL%C6Csp5GvE^D*C$F`X|!rtJ2 zt6%!7LGJ8k#|9j1A`JndugN(f;h*FY*{0WB`@q&`RQ$C{;d6wT8Oa~J4MUCTYb+Ma z;X(tZejuoQ*Rnb)o;?={9w;@ACdu5P^vR%`J?8_;$==Fl=y3>5vHwc116qG|I zTuXBA@Raww8M%ga)hn!C#p)l%^jkverGI+ITVW6nkvh1+><^mD{Y}=z{4^_kt($%| z^PgI!NS-Nku*Unov*#m8JOw@^ewz<4`po9&j1Px*aoVM{2+z{LAYEbYMK0``-3Z6n zB(etyJN=Tm)U~*-4OWH_V{0H=EfDdv%`!n;3fp*qGzO|PB(-q`gim{~T{I5Zx6kuV z4@Y#RuH#Rptjof=ER_(XyoA(P0bgJ&2xuQEn1pAKoZ~fHKD5@JKij%q)}Vh8;V{=8 zJ^`Q6M=AIoUcZ|}~GgrgWAFPgY zO=rR%U7z@JVFqbzHiT-z<5M)S5@;PyC_i+1Z#r#$tNQH3-5M$}6$biEBE7)a-amg> zGb%G6kIj|Y=-uh5dc?^3FHRC>>XRdz@7Fr@&Kg`hu{E6ST#}50`@LfIDUb^%=#YFp zSJ?QTM%Mj1Zjan6qD%@^a@eW!gNh0gO`GA4)q1BcT(KD9c45&APm|?y>N}y)rRK*s z7h{X3-8+_jO&x(c!HBt)Uy~nz<<0c*Hu4k2E3X6{pWSQ|&&3WNwRW=3HwFxTP(d5~#7d>Q8vsTH# zZ}odt5NzBgw!ID!@OfZ)aCcgj5Euo2Q-J>=@nv83lpR4Ot%HkCgbJ4bt6Z9U+t8=r zL-6#xVE^Prj9s0}Ci8Dj-Xk}^-G+)e`qH!IAlApfV`|i$6ED(@4x+D!8dwo5(lZuK z>-M*0Kqazd4Ciu07CbGslHuhRH6oT!#782)zfL>n&WbP_ts?vZb}6tLkcd*3dpy~n&MUpJu{W`w*g&hom^lJMrR?}CS&8_#G%9@ zAGJ!jpinz)UT9Wn7(%8P#m44GM(kAY{xZeW*_SZ6i>g!RwGlA1k_9^^lv z2;bP0D=MS(JMWFf?0I93d(nlogySf+aD+n|k|oGcM;CPO)pJh)_V;fd4B08RK)?-05GW<%@3}Y4q9?kg5j|p3wUSO{{3{6@4xhB18 z_Pmx?$acfL`HAG`d`Wj5inUc;*}J}nGqiywo47B`!cNgC z36Gnp>OygE2cZ%7@;ucJoxU}ua>;wBzuE^8lcjG8c``GEP(NCP z^zvN<1TlHuuoOG>rTMTNfDr`MGX@?0r@p!)tfTKoF-CLv{VmjXI!adq zWImDf>< z9sIuc0pQs_W}QQg-e|BDj5$L<rgRY%v=*)olCxn1|-7#~D|w{g7~ae>r})O=Uj+N8$us*rZ2hdR z#LN4E#OgDAvv@`wDzmpE&XUF|0!~0lEr$R@x|%FhH7JE{TRS;68zBe>2nu)Tb24gf zf5e&Cb@B+=vO$d5)sU5P%9ROOL)+=3sAgsfL@0?yQXUZ^W&=NrLR)j9)U!#rvX`dq zut#9*TZZZ3yKY%^_qTgxrV;}&!Fzjs6)qS4x711djuA;H)1WaA5nxWC#MsSGIC5AU z^}z2(6;uzE=)V&?&$xikO{R$A`I;uLcfz2}sLCB?*EsxG14BK$TV54)b-W-2-fX|g zc2^>iKV{9|TzaXAgLZApKWBoDLG)xoODg!$KW*uRc}3Xx!Da_V+IrFGhWI2xmdzZj z-H}euYf??fC0jrf)+^J}i)`Pa)@C!RwP+Gd_Td&46E@zWWA*Dtl)jF3YiTzZep$7c zKePLH+2pXdx%gH(9b4WKnI+pMf~qWFSc5AfXGUoiH0Q|XsT-F@(`{wn2q@tdM0P=J9R@!&D1E8-Jzg`uaDboEEI~5>sggIJNlo z#Ps(5&k-4dbyI0VbP9oHZPnmR3RN|T9raQ!q;{(=^G6cGkDqoa7weEkzmPLX(0}XD z1q|~c4;xQoN=WU&exgaG*X#aeB`zTRhC=v>V|so)25nug6f^88C4D7l8FZEYv-^+% z)C)~&95rMt29XZ8h7jX67Fu%dr&<)I_cP1Q_=4%SKB?vEUP%FJ*bkCc%}8y?-<8=4 zN9`l{Xrdy{_&8(MCMsw-UGF}!*29(?w={Bqt?~Q`h+FuGmu_o|%Dk>gEv=YN=ou*M zyInz~C9K*W)UZ2Gj2w0V5SVYZ;$fG2OgpvNW90RR)cSa{R%-L{^N8Pf*v7vQVnha{ z97F2RuU6n>k9fMDxrj-i*Ra;g+;4+2pt;dLOg7TID~KQ*-ts7f@y2_ku7{y+n_*pjA0)R8Fv8Dq?Jwq$C|w4U}_7iQG(st3>d zoi_Vrf3m~jy$vIVQa5tp-4^DBL_uJLG#>#=1~-U;&{x>i(^NG9FW zo={D4|J$Ey3~$2>2f%{Xv+ew;1#PT#x~`SHS45I34t$z7QvJEi$@?T zz`@Me$f4~fNaa3|kW->YJNr7R!uG?zVNi`;FL$Cn;OS{b+8Sip1g?&=h4}qj3S|5U zg<#}3d|Fw|52F7*7lg|J0g3;)g*rMD3-{lb;-O-Y694X_hLQacu|ZH&WClzVFccRc z075R6qp$b}vWXTlB{z?CKgi-}tMb8qC+b=Y11BUwGi$Dv0W652#Dti}eVk}NOt&=& zI-CXy1Ufv}F9nzNhMD+>J!8{B=L`lTNx_eU-bED;r&+>R`kWB2=cWHzy^@%2X$|y` zo#@W^c0y|N9=G#3knG0=IJSh*sj*^Z z4Oi`wbJXu%msEH-!1&z4IxM$&Gqs)aR;<^#3=AM3g0HJl6$2(?>|_kx#`RTWLGF8R zi1NWO05Y3Jg-miI5*3I6QH`i*1Y&8m-;p!W0St|@!)k@XVa|73(qtuj^Wc- zqzEPx+D*}J9C;2})%4tDs_UBL0$-bFP$kMwQgGcA<6yeAp^Rg?ch04#qymP!ly5Zn z0ORlh4a68!Vf*%9?lF}IgLIGGC9=jAzlgat-<`=X3O92mjpLoTFJDqQXVNJLTVgd4 zWguA0O@-LohM2d?)8sm9$e_HMqp=9#ggQ*?cQX)@RZ zLvsALz8EZc2Ejeb_A#EihPmuqGH#kMakrS9a!*z&E~6p!SOQ{`4}!;EXD^l+dcYIr;@PwCM2I;E!Q0w zJb1vNC-oQWY>4?oamystuq*zo`V1xnci7uWaJ)H!M}TwFXhkU2K;~L}$vp?@IJG~* z)_cD|)(Z+28&S!=tX#OhXVg*-FbyjC;J&^qKe&DsVjQA+<<6TwGro>!)qkHv){^~e zl1tZvSnNtnmksj5mQYsRmd5Vjo1_$D7c*2sJ=` z^rN?MMB4@bfd=l{C#A>9Mextl%qrX}1IBGBF`G_gO#MnfLJALCkU*Fv6DY6Z;pMYvmLIA@#fd(mc*m96nK0L3vdADwL&O9GOh| z_)v%mjm~NBuEdcHyt!sQM6!82GEMlA-X%M!AZVO$6~O6C&Q! z#K~s9Ac8IM;JoIdWL>MWB%B^}_*!?y)874(E~SW|vzv|105tWOFl3ANl%NGzWRx$< zA7+dNny04IEjqFJjh8)t2at&6+lBpLCW&;1pBHE=vpJ#Q-|T6rt(D!H`k4M=1=~=q z$tvc(mACd+u`c!u5~RA4XXG;-P6#;%*Nd=0)2ZY-FH0pmP0y3OhN(k~+v*?{BJ z^dLC)bXz+teLnTavO?NFgrTR=^Sy#>mP6BBPcVy(f;pI()^fZ*9k)w1pKvl5(n_OR z=iC{O;7-Y?4srsLVhtZ$!)KoupQTc%cYSdIf@aX`J5C+a&w^3nj#n&^cWBv|h2PmA z5=0TJOv<$ZMGS14of}v2NDmsxVq_}tWdd#mZzV%y*nZ9rM7#racqw(%9{6&&h|(oc z^-#xl%-d;N4Cq8T5;233u7okhQ^Eiy(E^l7?4JSuNJbVFcjLg6|vJHH7M=~Yyuk92? z1zzh-jR%Z%qJUSkh3;QqE}-c$aE%bA)4S0s3fHxup7UxV5J_nGNr}cBNL^WYpfkOH#ipy=8-MY8x zR$|y$jMKY6lFC%yKWsGtX1HuvNU_7~=FS9`l!e zb$+Mz_s9W?`bXMbZjsOLQNY<2_N=NPrkB4_a=LHloAlIJZ9g?E6Dt7Zgl!8T&ODlK zhZbr(`-Jjvf-!_9Ib$Gx8(s!x8Fh7coBFvXZMkFGvj|wo(@CnQW*}}U3tG{>9e`BO z`zA_>fz||&f;nzpK$=P-{@$0f`_)DtGXSyeVOkc#jJ97$`?vKYJ>V^w9CcJlm_`;H zTPB(u^%xV=d0eVEYC&jNT>B&D;vDQ-yh)CxOmZ_)UZ5UlR=`%@nvN6Fa6W71LQcJX ztcML_D<+Fv&mcRkXb20#f0mnLtW~Bnq2J?{qy7DX@35dB|a2>E4*c*q&RAS2I7Xu^;`sQP)WUm_TP z0-u3RO)$LMr5pWT41i(WgKMtCQ@4XhpykIqmy%;EfvrAN&DJSUdXJX(E z))$+>bEXGOpc(pQV)r2BWIw2wy0U5_pUuM}g#Ts6>pd-V{3#GTRmnO;1=qKOyiVUm zjrc#c04}{Rm-ccee$$czU9bsBOG_DEQajtfdqRH7{pBnll+nl=u~go@0x?JGp@=y< zx^@u&yKnI>VX9$;J`Skv^83Rc6OJ!itcf<*3?nHgc_9F=m)kUdPfO+oR`W=;o`zHm z%lP^29Fcv)H)pHv3!ls*-617%fLXsRijhqSMJ>q$0MO2F!cuZGi&1Ed#aK6QaHL8b z6o;77n3tSa9twAMQ%(#N>=Y^AE%G@%dc_}Gg@KRaYXdfK}{IAG`+dDpEks7Pz=5F^fhECePXYc=7M6%4;na zbc&ug@?0B#v+%$Db8se8{tI&hTr=Qg;VXaGoLvvVzXjSM(YVAmRnQngg(A#IUp(rc z48ue?2yB7pB)3*C>>AZ9!%&{~>N?8=K9?;Ow)m~e&oO+NToECk4LVxerW1!$m9I5; zA?;#`+~+i1+}kzI0>1*KFMD*uJZF#iYwO&(rv=ZN=GeqwfaRw-Dgd)ME{;D1p=V_w zcoKP7m(+vj%KHs5W}OvL!5oUB2W1H)C)CZj$=WTcG~~)i&KT@D=;!;F1mL3V)$`16 z)w=s9XXxK&setc8o8!K7ohQPsZl;QV9-_jJ;>oq*OB?wW! z7*bAO6&+ujZ=$1C|9t_b19BOyXR_&8OVxwcaIn`O?C~Sn-FEWm1mwO`H^O&N0!Ngk zrYi%g(bVFN{B1+-+1!nLK!X-DG8Vl`m z%>eD*9bTlF;n3zifstB=CEao9FF*fYG79*Wv-H}=WWur3j`r}`fOV}#gp+&x&tVp1 zL9f+@-qORiq`CJzJIy_@SAT?hxaW|%)KvX*ul8XR>G28wvUbbEE@@QnHj+{?Dwsci zf^IZ4WJ=jt32?IE$N_7d9Es+{#)`-?WJZ>%>vwG1G6SY0oY~moibK~3!tVMKMcmc( z2|kDqpq{ne0b_*-O&e{+JPy7ko)Rxgj^or(Nv9>R@1;6y`~zx~a#Gnh?vHZ&OP~Gb z)cxdl!W-+C&I?N@tWIVqB|=Hg|DAn%-sc@gr_&_`(aD~%3xXq*oe2ntD|1)Ist$=_ zgXP%3IMOxAFUxN;a=uQ>J`5uzlxaoppxdaZf#Ld@Jei?XqG);VDCb`431`Tp&u!qC2KWU;8s){S!Xf z1TdkKl9MxyJ$+9@`m+ze>8nk)${j%4j6gZOabQiG=F{fHGzvP-YNtsf+iPayhl@Bs zE@+8u+6W3KDi}@}3M*?2!FbeL4ZkxFx{Oa{vx5;oj3&&!t^}j%MI|ez8;x9F8UxoL zVQ;>%fJx@4sAHf~Q~9%5zz;Ih*|Zhr0Xf0DjW8HEI_@{k=lkd#cvmkTJXxxo8*c3> zOC>YK?%ds;#h;|5EB=B1aS{yM0H7od4hN`?jj=a-_^CW%gWmMRCggu!Lgz&gvo{BS65Fk&Wru| zK{Y`5Lzxt~c`74xTG?9kX$jEG#P^Hox0BN4_VS8AEhBPp3BH+stSsICRa5t9vB?!Gdm9yW-Z)t+{zX_3gPyXn3wE!}APQQGmKYeKf zRwjk6BdQ%ssu#TsG_yg`XE^ygQT-=#14igO#(_jeEKjj-QP1F^0=Ti^be0n(p3Se4 zlkIlPw{5ApGYLs)E0nZOVom^@u`7Eu8jh!TQVL=Ge7YNUQzSMwb+XQz2 ztNSR}LVY$|wk`1`{DAi(J65y}^w>;yTJCf3vcrUJ{BCZ>qOCUDreLm&-0D=nY11c5 zUT9d=fpw@BjXE=3=%^KH)kA>anB?;xef8%_{uLjUprUVXp^1Y-y$nSFp!dwYd}5Q{x(V!l{+nH7qU7{;BLu z@kNnq+?jK0+3R3c7Mx?dq6d{usy zK<2!BNCyP67kfFi?dOAC5sNclg{bX$VQ*!a_frfGm8Hg=bF{T4ZE`^?nA?grjTYhm z1<^ZLYL{0OxZkL?)}QeHC)u{O(aoV#(apQ`@zfvFbX!eQ=Z08;;NevWI|t=2n$-XAmy8g^5)2=vz6Q1+$@t z6|tdW?C8@HUq0Ob=2~m<;Ha|rh~~y%U@Xk(;rh!G2R>-ou=; zw1|n4!5iXHfK+>tKW=+oXusrh=Q^qunm(FL8O}s*B0sQnZpJt8f`ueFkFV{a&y-$Y zRIzgVH@7JnD;j+D>6OLj5OI*MQ*T2AZdlr&zc9uvPrq;#mpJ`V-nl9k(qK+C6L0jR zU_$`u`6O=Ja=YG3xo4f>?u6lEXeee1M9tFO9@4DL4Hzrihc|ipLJxE0vpr`T?E37j z2xO=MnO4D`hyITVx05*?3qFsy$ z?Ic(ML8sd?OSq||Rkj!`$bm|*!N9My?7TO01}`1K?}Jg_GP|!JsVCxZ-+9kvSrE6m z9@&#P&qTsNWC?61t#_0<*adsGPiK}|Z7=D%E{PIK$<*-Z$s8QlJPfIY^N z>MEyL_%%QMgKF+V^Xs3m8hrn;vlY;cPYU)WJ`gp%>%Ohv*qT-}?GHG1^gb<@-Yl=a zRZ)hwgML}sgts5qgK&xY+(9STuL@16VGF)@o~^RkAg7P^xm~e8F~JRXudlmZ9BxO{ zYTass?>2P%MtzS_I$NG!J8m>4Lc6O?4}tf{4y?F0TY3;Py5hfr;ZktCT&)hK+7pJ8 z3-=rmlnL2z37XOwT=$)vB$g<*6zjJa!=$J)p+vil7yHao{T_bX1WDHB5dKDLS@%pz z%(@`?&Jw;_g!1rC4!yx8Sb9 z9WH&}z4!UWMn04&S(DYSpmbrk8Vm3@}WcU*WGRtgPd?D*AB!br&qi@Cjl!_%MSUCme?#W(Wt9GuzPTv}_u-QG+PX5zTlJ$u zP(ELx!lNC(!5hbB!SBjFh%PMdE%=OZ13f;N!mlOK5=gB9_6f9IpjOkiyxX{R`iMQC zD@m(PPC~{>j032M_RJ*`N1;9v;I|{HOEx>m+$@3xjKy?mc|>RU!K5#Fc^=3P-)}PZ zE$SBTBs@4W6Em5pQf#Gi#q#I!E^g>Zi>R@C#;1JY_`PQ& z<7S+{bT8;7XG2~)c*JPgs7`oBdk->+2XbkvVx}Zwi?3VmXU1)|b^Qt&&=QZEmQ6=- z#Jvv4cg^`A3xy85&@c8SCY+;VDU zae|AWtKY#YuGJ>6Sa*S5&m31H6do^bwkuC0aadb_u$ypAI>xz|wTD}7 zr^Z5f>&YcJtshw&e)Eq{>u4QnNcjQD()fk{=(r7rf?ImkX1Q#Ww^CG3q>@~}9M5Ti zH2>IO#pma19cgtWT+g)W$J_>KLH;Mo1V1T;<2CXQa#K~7%I_HASUz49HBZp5lQQtot5bv>QgEHSpCjaTo?6r z4Wuns10HwinXW!2B%#aed{>0Au?}8pJjdf9D|3LQ$=OpWiFwF%p^A34mHx^u1qqtX zvO=pkN4WB|c^9QyZZWbv99}0wgbnxC#_4m`p?M&f3z~P$6`+m6!pG4^$n1n6;vvT> zcfA7dj6c-eL1H+RX&F^7G3Mwf{%J`h97_p?sD+L#mii4=;}CQ+Ksv+_B@N~}4#22X zhB*Pp7;C#A4YiL7ArUJA~XKpjUZ&NmsQ(GynMLFoG%Q@`9G(u z10Y}Pw;`NKQsqwyz8dHXWYwmj_7|D{H2tv^k^CBze*;Hf!JNm(9pFvsi!Oh7S1`sz zCJQz0ylbOTPTv7Lwcp7@y03Tl^{a`~QY}q*9d3q8wm`3Qwt9D8&`Cws!1T4F;PsAG zQDWlECnigLtU?#W#R_<1%1 zvbWq&zm5ff=AFy2Yrc*k8BQc4Q*4)k?mz{R51~D!PhC#Pwa#7Gu&1sDnwZ?CKn7Fk zWn}Gasx{dAEj2o4(f`ubJlG9_0i6WLQlj8v(S#QHZ24cGT>8%s$W5q zkETLUjpEKxMfZQgQZ>2&r$`C=Yh<16dxVy?efP+yX zGZ22whIFlg@nMQ1oLNQG6+yY}m3p3pO^2p7#{u?Bl0^nck*o0sMOE7~jr6!{{tsE> zskqW!~RIS?_~l{^S;}{GjI!YCHL%$2(+8zTC2_;g)R` zI`~)B*H-r+#y3G()HyD(CtPX_4Sajswv#LCn<>eE#ar=dnagl-laBxM>$^_`poQ@M z$#Cs38;-$a{R8$0!M&R@Y~eAU&u27A(JmLqy2BH&S~HprEFBAaKtB&-+kudMWEuxV zvGEfE#zuM)Vrq%e=fJ#~0SN;fY&tAkD`XWm{7X)9|MEq1A;>B}M#%3owMLeJZ+&9& z$LNo92&4%?70QEg$*4;t%I8))OV{LF%j7%=NlI{PeD&%*b(IKg-adwGP?Z|QtAYlR zo6;RL>W>{%blg zd=KCMWoIJZ$r^&RQ1pH05BH?j3w48-LqG2fwwj)V1_nm!l!e7{iXWQ%*FVh`Tu^Oo z$n)bAkPX)2pF^q{kaUzf)vWd!c)PDe;NCIelW_F0kvNg0boaxjUpL#D_|c;* z;mKX9NJc@$>v(<;jycYyp%?<^3n^Ecfm4xA>nL zQbyViPuPp-Vl0f@^Xs~6uY|*!#r1uYR@P3ZA?v5Ofev{Cq~>*k<{k5Y%n-laHa%;L zDXOiHEpG53N1OO-x!yey&n6y)lyL&~84``AkPk^R2f||_w@;s0xCsv{?(?uZ1c;hfrJ4|E?ULY04 z>3{RmRhY6T&V!Ms`1ySBlSOc-T1K9YlLvBqPS>|}=W&E@(a=9tKb!IgKM93*4o@eF zsv`ann4OSZHI-8~xF*dNtnN9e>AuNMcfOz#y6!-%F!)IVCVD86P^`7s6}3k8 zMB28Wm|I8@BkX{?^wlr6i%(eL5%e7}NkxJAT5Y%gP+NvRi5NU<0E`=OeHDTL_4|iA zQRCep&O+V21@10EnIDW#OqfTSKgN<${-=F{S5%A=CjuZ;^TN;XUu|(C3f=n&AVLmP z+74sIg`NyuW1NGMAj&N_>Y+567^n32ScLKB5Y^v1(;)5+E%l$dH(eFiA~6kR_lSVl z0&dC8%8lTLw6h2b9R9KVhGo2H{{2A8 zK|0Nxuk=}okbLw{E7=e69Ao#DwU};+iO6&ho#9WvEv*Q=GI9>{_rSR2{#VDZUOeTV zv4Z-P(&LAz?A$QKMgsnE3$N9g`lTcAN&hFmc)pKQ;FG94Y%&*^*90Z zV}DvcdvvDE<}CKd3GT@?s7H3Jhkfb2U=`RTChzau@=okhw^Q1>VGT$Mhn$PmXEbO( z`s)sx-W0^VAY0COtV)k9+zDjT)80F(t_6XnqI#w%!|(WO_=)&zg!oQ`f*$uJBP1p(B2T!2{bG_t7Rdm)zz4_Mx|+qLW?uI56z_Enjo6ZB2x z2j2_cEd(V^i3b7{WW_y8t)X@C3U)gmQ*(cOH0MY`rs%Sc`oM(|D?~hRhE{W~!!{tA zmyA@^h~AB`pmg>Dal^6qY!?dCiIIwzUQ*rQIyc% ze{Z5Kmud=BZATemQe0y^Jl~n{K zQh&U-BGGYSIxV&SIVDn`TQrX1*h4I!$?G59 z?@AtiggHU`n!nZ3n}0Ec-5z%)Aeu>fhuX*>Lg_Lm2&hLZ!&At=RRU3tGA{hw=GRKbuEdm-{t zuO=l%r!0Dfrr~qC;?j^mn9D}S0KD$^UWiGCqFOzRdq=2?a1rGlOsSXeq}Zl?t5{8* zDh)WVq=GKi%&Vqm#_PVRVxTVSH3ipm+ar9h(=l3e(NK=U@s27R?Xggxg4@RMA9`k1#6zLPg>him*GdaHnnzuKR<9%G(nN z-Mj{AKiAWZur>MFv~4a@`FFTv?O#m+zwa*!hOa%V*>vv?Y*exV7S&mIo<*P0?p(cvv#z%BUdJD2J#``2a*Mzb_v>e5k4D zML5$@;IBhLY!7XiIN05@Ou3@Fw2*H1&-HvHa_fIrY|PkqPt;t~G{OPpm_m5q3$Aa% zj|gnJD7y_d%l3K7uGdm$KAghM^4E++VST&6$6J!iZH@Yhl(~#?Bm2#VO^$1!g|9S- z&5LHczp5@Y<-Z`f?28#gJ|Dr}M{$sA-#A3AutT*&{elA1|X)5tgQH8 z+@1x4#C8m8;PrzeX?p>QE5Tk#V#=Hu?wsq3`E>{4Z2Ed!QJSSE49~ zs**Y)x5MZ*0a)h-zBw7`tlWY$p5uXqUSF_!aQ3J0QLkqk{4zB+8W&iO}U99 z6-OvWF#B*>U*M#V(NuMGB^|9G?}Q)8lBUmP)4zzu!Dj3aFO@b|_@Lz7b>x_`kbJYh z5lkwI+0Lca;;bmo;Q1;$k|Nr#P28IJLuh@`5lBeOOyj1?uDhU3Co~nvPZ{>?0_Xoc z_I8fCY$rVa`>e0Gf2Y<|5!;-V?@-wN`@V1qG@0!*5lKp_OqCE~E>`Mq_deAYZVZ?C z#EU<-QF`kDL8vjvkkc~pG8iK8zUsXz`3`I7wyTQQ|5ahm)l|ff$trIlWf~w8z*PvB zlD38LjL0)J!|5ERJBSW}NqvROl`G-1g)LXc?3iN}4&i{?p~GpiYgg&~FMBk5d$%36 z=5aiOb_VpLLnmyu*C_1DhyOZpzkjv~fGm~w*t%hjOAu@OZ!bX2EpUqCCrk+EV6Ei# ziCtceBDUx5E-$}RC844MVnos?HKjpB{tcBbkAI%}R_EEa+2V2UHcd$p@?Y0;t1`F5 zx4!~16GK~cWDTrM#my|^<>WK>p9c}cucx7lvwGpl*gvyVf%y$z+CmnT|IwnEK}rfG z_&cV`J1w$y*0YPVOqX@e^n(-Vuo#M5YL``%{zu=;_Nilx-qBM89&%5`L7sF?w{}eD zxEC4nS+m&5$}@|4V}LL!4t8hYP;5b163ru=j3Pe7W2YH#3zGe*X$+AyG*xjD>~6JZ+zJxJazePaR?=Hc6h^akWy3XeK-; z7DcfYhbca-NT|s}JsrbMTxR@#LY3zMq_H%vEJ0 zQ_9yR>W_83NIo%+>j8`_9oD50t;@7S)%tH}j33zIDcl;wm(U~~opQ~5{%(r5lBZ6) z<7J+6#R?4GeQd-8)oFZ53l=f-xIF>ma-qcyzlO686R?x?%!1&0eJoSpA9v| z&*1Oxs`KBmpEBZ-3@ZOVde@ara+tn6j|A%V6Syq4vP`PD$N4@n`1@3y8oF&6ThdGd z1lo#yzK12wbmaiNk=nc_-9PL}vLBi#3!J?AS)69Sk;n<{nWSaH$troAYk$AdM~DR9 zPlzr+D4!x5_)x8Y{*{%<6`uK-wl){sA&NH-;}~a)-oJ>R(5D7SZtG2b8*L6pQG>n!xD9GQA?${DK#eMj7~WQr=i*%nx``_dtw29+A&-z z1OLm3EX1Gxpwrw6QH$AYZfcS2f*w7=->m5Dp)mt(%=>epwy~n{KQQu=kA6$uJm{PxovJAWV4zAy2Q!+R*)$NT@ zB2|59x2@FOU{i~YR2R}pd!~@`gmmZ74VgodELQSGN=NHi_72Xgx8o7iWf(4J2u)zC zUJ@e(L<@@-=?lJqVlh-o- ze}(i|O8$oQyqk+L%`T^pC?W|e262-=CNGdMLuBIUj*-l_vFK_1fB1qiDn&JJBrjR5 zNyrTid*uB+vR@#2FBg~LQu9hSAI8oZ?fPU$v@baAMisk$%>nDe#-p8mUgy^rbxs|7 zB8QDE-{UvOZJQtmvR9dpA$wd=UH0(0kPPEfrNjJ+X(8Wg-7x1ypGD z^ScQ_AUHe3T)r~{ZT6QKA;T3DcdVk=`&JD$Bj*9&jNUOr)io#MIdB!vp(SBa_^0=T zCe*~4V=|)wd;~4se(OK3cMkS&u%Y@cWg5c|JezvV=}N;ar) zsJdvVtt*%8uKli51Jc_ER{2GZ09|dWq4>Spi}yZ8vsj8ws$Bhx78Fm`^FNKE`z^wI z3Qp)-9_*6#i;aFX%^8GT2nE|I;K)TC5QvhSt{V?hv>!t6kH`6Mi$D zPCir^e|(7hSfOk@a0fI#aQY>V^aEB#4tH2CUxN;F&qX_VpM~cifKX%qKLCLd2AORf zqNcygHC@lH#vs?@_jpO2vdxND*O_V5bUM^X-H{z#HLxFb9@QaK!jJr!!rDma$AuBs zJNWKao1Z5CmYu>^P4o}QK*Ke#kI}VTk(wk7rm&25PX6Ku$211no`>fO`44PyPyIL0 z2;e4;HN!}fAss4w-@xq@55A{H=16xA9z3xle-wdl{r65yh3cEK_O-ttuqM#)@1>#D zyoN}ibB8TtX-Dqa&|5e92>mL3$v(}=+eB|o)A#PLdvL$|>0`?yMf5FZ*vsn!uFPGI z@A#`P7Sjbp!plvJpg#F+;g>l46}S1aMzCKH@Dpe6jG!^i&VcAPIo&Bxpe?#J_=pef zo2Vn^J3r^i`AvUJzU*Hyu`?FsPc~YKCGhKegHq@thFlR)4h#=-&@}?^EC1zgv=c?S z1jM|YM=2(<=ey1Q*9$6-_m@cZp?HAWHiSUiJ%Ku)5gD}Lb-600zeuSg?m2cabJlML6%h`GbdFymnb61 z7^}Xpb!=lOPE6bQJs#74-j~g7hrpw}26) zBAkB-@2;W1>7N3HK!IXOdgn4C-G!G1x<}Jxqw%FT^WGDnf!sohCmuJfHWjx_OXC96 zJsvamQ;^?b%FW4nq3UUo!*ynkW+W>E;J+!+AGZq%qfIOeMWFpf?0`gv#X+ z2^R3Dy0#fXm7mg4CZl6xCElfyAL8fDeBfqKGAk2ubCwZ@i!+x%&v|w)t7A zJGa1Mq)GZ!KU{C4Qq$^4{dJ^16`l7&JVa-lz^Gzpl~&PqarYlC#X!n)NKl0sHb=1k_}DTaYX0KPk~>^H=c0IpHol1sa9z6QoP^6Yo%rvg!4!M7XR zD7d{JT?1pz8SGYzP-{py$9-)wmh9vI9=6)I_slgD)i1F887Y0 zP#5L07XzjjJYz@H1MiI)jy~#L;CWgu8{ppx|h@n=xnit;YS_@$>54)|+8D>o z51za5J*~Fh3Ro)(sr8gYHZ-&?xA6(zXL!mR$xDb>Ks_ENXCbjd?Gk8kxPx>R__ z{oEi^VZN~&B{AH( z*XQ(RZWZPRqSna(UiPTAyay)MbY&$kinZt~8}CE^MGi7Y#;QLz?27sZCrh5A%xOc< zU#yr__YHXbRf3WwFXfU{KWlz3%rE@&6*hkaVBlv;Yc6D@G-3R38Nvs`b@T*0XHMy+ zuaF5xEm235X#Y+Ll-1P372faLca2g0Y~4zx9dBH)HMb$QF!i{rmD_?cYN?``lhGV= z8iX5djrk>UWQWr?d6-tT2r2^=UR@10mhjaCuKpG%gp`CE#0gj?+~8l|mJRCBOFS9MR!uOL%5O@@4dl*yv#3 z4qx*kwDgL!oBk3$8$AXKSJxqVkzMPGSceAP!nZ9G*P*dnE$8sNyP(AbBvl_;>O+2)Xw`bP91yQG~xEk}{BV z|GWY(3qk$<93F!lA?NQsIRzK{xnvesVpY;aurr)ThZDFx2`8D!_yU`;2#*!lIxN+U z!>92|!tE27sin^ur^X{KYMktWutS{$1fCe>&E6YOwl|xAFE>6=_4IgY*RvEJDIjZtm5bW8Xg}SIgeBUAe*(6BXE;Lx@zH4POKF0OKLRXrN!yO$jtLK&LA`j-> zS#4K;!v?rh*&qa#P|%5z%DsESfYfLIKD^AR2+K=P#SqS(2)S)E_YBDzR!@NVNV&^y zti4$-+^7ZNwPk(dZm>v@xKj^q9fTvONVUS!YijouR>hL@Ve7Img@p?2v#T3qmdx}5 z$yoRGfI4Z>xHzDBf&w8&_4no;q8Tk@R*AYs2Uk5=cTMm#k@*2 zjj}y;^W%1CzzzrpDkehhFBSKc!Z?Hm0A_~^W1)P$ask7&NNsFUGy5kSk=WT4Mj=WY zLpiewcM6n>h!**cisJFzuqMTWXrqRDlx7A?lHf0sxEJ2Yw(f_R#zKT>Dev22M((QE zz}q5TZ9rLHj)6jS8WBJ9hePM8>dE8N)4u48<#lu z=lxA{d+|%W<_KS|lQopqfW(C^#U;vC7E0x^C67!@LGH}peRt7#d`&$Vc_ zm@0_%ITmitN9luW57=T9>6dJDo+xz4lwSbsQy1?5kKNQ(XE{xW6+K$!0XJ~G{?Q+L zWdY)~`djtuX5&_F$U&O%QUU$pTo_(QMahx3pBjM@-3 zgMh7}oEqj(vmJ`NQ*iSfA`1cdV6TsS&KA5PFE3%U5W8Acn~k-C8T7I#iZpFmEJrc^ z-Bo_=L8ad>vFuhfWcviKZmbmY&xY7Y%x2dGanqcE z>TjK)A7ZP7|4g0+LS=U&JyEVyw%P%I)7&3hHoK85ZgsApod1EU`h})fsSPMI15)E0 zgqVaG&9J<2AltSw2+KfM+rX5M0jgw&BqW4lD+QHn4)J_=!^cvVsNZ#^H6+S=bb5SP^gxHHKHeaDHj2#v3GO#8^cs z=EF|p3J3%mVSeG`glZlPv-gw4+8E82P($1I=8c}d{OBIY$4~F!ZM_8to8l5;U8uxHl^wXV(&vBFJbWEZn8JM*I-&dT=Z# zY``vLWfqPltSlszSHn|C&4kUl>sBfTlj*UeY|X%Qb&m7CYnmRlnE@^71Km1#8Bc6| zH#TFzGHfMh5273BbrOiZ+SI@ zZ#4!pQ2JUEPT6WtKegX*cvJ?h)EOV28?PYWA9559DH}yn%1E=CTEn8S=G_h zwO|+8y!hILj`SPfVWX|ambU;d8nSLqhGGp_Q?axDu#enUM@6w>*!q^j!y~}|v2mr>MsJR; z_nzAr>X(q~J~&Q7wf~#y1$Zcna`X#-b{i8egklu#(hPnkm#i#}!o@`joDj(W0#H|XPuYjmh-$Hk?`8G zH2JH3-$j<%SR*R=R@e_k!qNgo1A*!3(X&9GUOo%m()!WC1a*Z~lQqw_IB~&Ea+5*W zUclyNj^!le={)c^eKj9(qg$uRF_{|Zi3Jzx+&gFa5n+@mOr2JpFBj5*x0}^a0}@Wc zCblwx6J(4qmaV-8U2xZ-%(MzvLo)3Pi*x`r?_S+P^cb@)Xx|E&azYn`VIrHBgV z%?9LYLj35vG~xhJoKu3saH^6~X7HO0QVX6Zd&i16#}8CV=ggnY^n%K+kT1H8`+oLtJJh?fXkFaB~nX%yqWT;+1c6$22Kc=(X8_8 z#~Ow4{BO1X(Vk8$O%PR^MLj6mV^%1#@JDFYRqhsAsi*v2sCUCeZM1LWEjfxnrEMf4 zGryd~Wlc2dLvkgNFA>d7PJ;EmyU?Xj2h`S|^+V^zw6BLc;(5O9TB z#gG*lR!5LCRF_0YaKsPaU|Qhh-O=nizfQ2}P(Wqccfn{Ejhj^nS4FEU4!8v&?+<9T zzF$Wr!lOk+p^nyqy@4QIo_8k*a zi^k@m(vdSQebr5xw~-#-HYqC$%**e^QUePA4ZgM-C_l_n*(rB%WON0Wci8XHUK!sw z!^3y#FsrX_P-l*uRcxr$Y0(-pN5}iu2VF z!lfi&hDv(l!MLF(#Ez}-$^VM47>2$FdT?gdikvzihx@y@f&*3)EFv$+j+H9SLa6H5 zM9{$dXRWN|hU*N$9M@)IGTj^axU}ro(Mg~ZHG}*|pXkIT{%^QrA^PW2C9oKbXHOhS zrAVWCwJL`kTXUe1$_w=U7R{e&9AWz;a$6@-tor-67dwWDeoO&w&p^veZ_o3cx$>dR zZr^pkSVl&)NpS{#PtL(~o4ri)?5+I<*d!A+5&pU)aH16cwF@mhAZB4mzo{a3Bti5k zRnD*W82ZoBBgVqGj?_^(VwOK$1Sl-sVef-l-0@!V`h&e&qsu0Y&F@`7*Yv1-eYd2f z4-ESVFTd&4{gCYhCJp01SbV@>SN>di3n}9aRJ48ksDh+;q~Y>VSj~daqH65>Pwr0PxrZs;CQ~i@598q8t(EX0qfU)QYheMa}{-1sSzU+SoMbP(bU-UfT$`o zb4Iu$KKKC~@eZu4HmF-aRH~j)qQS_p;%u$7*hrh!iO<}?;VFp(JNbD zbKEx0=dnPYdvBrg;oy~XU^nHYX^7rPrv||iE(8i~rv_{ZO!X9`t-&t=WL;(ai8xle z*JYjidi*;!pT*b2;MQ{oeo9a7`s{Ixh8{}|xxg*uYV+I!gXeFW)1 zz;vs@|?&zSQ3ufbhn%-U3u*r zW96QXm2M;}txsH!E8%~80sM@d+yK;4&UDN}YLFyq9Ch-0Y8+LuWqYL!2vMY$nQxxi zp)4|ESrUCmPI8yT&FO@RW#Er@wGTlAZB%huwF%+1;!MPHw$nzrS6F^48di!p$i<$R zWT-{_iCwT6?mJH!-S zh{B^W8bwVy=HNJ=$CW6;+a9FsU&%GNooT9cGC@V;v*HJ=O$#g6AJvkXOJW|!CFVQ`FJ#x}l88(9xp-hIfwxHx`C`vcVIo?-je*u)npB{%%l{kd62nR9+d>m!CmV`305WMgn zQjq|s_6poxKbkc%i5MEi7&9+>;KdrcM7CXPUvHWfyJK;h;srAjN zq@aRWECkW~mq?d{?9CLywrm`9$h)AUZovC;V;s}QigvMR?me1gV-&Jsu1K9$foC)x zVt3CR)*s6U!|2^i_4mg+8O5^tV5{wzM;#$(95MsW?XD)$f5I`E(TyD11rd{WO&Q(E z%Y|`2h!WaVkO;C`WZ8ljD~u`$o6n2_&m!QH-!V5zA^w@0REoKIs1uf)GGkkQyV@Ok zqYy#fZ&q={t4uU+AADJ?A$GiBx|bMCieVZT2o0w>IZZP-zs{mvBVx~mDvE2YhH+<$ zQ5cmAHfoqr&{3WKR+ll1e8$-q)~UQKcnZyXK7iYeQ~_@RR|J@zm6gWLII$Y1bHzKeNntl|i|H& z`bTe{#UmpTh($fy49JpRR+_4tG@hzPC0tLx#QD9z&cs2)gw=OD%_n?Qd0Se)-wueN z8i2~eaf{a6lfa*sSfX$_*V(0-(n0#O1_QdNHloQ0-$?>7t9T+4C^4c1*+zvCCim#U zt?Hq|xpg1*fLm$C%)Q9!@H9;&tfSsY?}A1Wi9JuS7O(Nk|ETeo*fk^i)$7V`9|22) zz?-rb4V}chDzT7;27q-CJDasLXM*d?y%cDOoLJMG@v5-{Va3XL7qPhnB8eG~NHj5_ ztP2a-tG4~8p!a7xB*O5YzQ*79jhjG5X%@E0xwch6%bJZNSb4~1Z@A(g-&VpHm!BvS zs&{QR?!))kEqV)|NvV6`Qzrol-905jaEq7+KK?tRZ*?bo3Jj(wlS>|vry5YlDI-+| zJ+`Kvd}?uQ=?We~`m>~O!G^y)$s)hhDeN{fT%IanrKw&+|YP#vi-_3R}P2*iQc7N*Rx?|Na5V__4vn!?) z7?-W+4d5*J#T}W-Zv;Xi9s`4txsWVFaZx+bMmm%7l+@C(r@wX;&65dUe<0Je%zF$- z(_-DQ)eNKsy5Dw-U_Se1pQQuxm`H?5?#XW+aC{CQ- zi||jbsb!WROQj58PYKeBnUs5(CimVEKtQB>+b%LvwQt*&?BP%U39*E~5Kl31aV z_;XgfQIekE?@-CZr-^2Olz@F7&qNR1s^RHjtq7HZnPUMcXI0%Z7f8UGOTBVYrJnMS86ZAEQ^uGO*DB-$W#_Vn?P}-#B8CrnMGYQ4GOI9-_ZMEyxnNv)`C* ztO(Hd$}J*U4tW0RadI>`^5sizz_vBsK+Y6L0s);Pe#!>7iUHZrCB_9d@6PM1Suz>p&684tq$MM^R z4F`(p9aqoxAA4BwgVT%U+A6@jlsofd-9~CdtN;|>!Nh$% zWJ>5|r+OXCuqKcakOi{0;TH~i#OCfU0tN8arbx3cyySqOEfT|DCh7TUAM8%i{U*PnM@7?bE;J^;}t9}Bj(`B=tCZXOQaQ$oX zBXX!NBPtU5`CZVS`xvQk?;)}@}7FZ zW6C5C?5d%#Z_)_t{fb}+#Lkh6VGxlm zT;Y}gYReJD5ne~J6{&TVeh;UVnhZxO*h`U55jarx%sN(W4A3hs^H6+I(AcG4u41Lq z_*4BKY(wa8Tk?N7gU}y#i$%Xbme&%@C-ex?rYLMgX}lVv9vMy}t-PYyRD_)TmQ(r6 zhL-V^7#}&c%f%%off@Tt4?&Wld{8w>0EmxM26}S$ggrE<6hFgweKKo@cW(77PIWi#jDLjug9RUw^Cj6@r9lZg znta4YeEzHGuu7Ibl(lYJ3;8;vY}zIAZ&nIzrFvxVRzcWlNs3t~mR(0pjR!>GcV+l&nqTEodi?w(%fkD(Zyl+p5LB1> z_Vxv$DABh>6@Bea1O`n-%jEPCvOkbp$dHWwhYyfpG2<*JP7~^Sf(CrUWu*Nv9}gy8 z_q7^@5;%BNf_@Yh0kvPdS8>*6h@xgd;sEJkYVkcnCb&6gxya81wrzoir46F-Sa{d# z&;1Q5M=Fpx=Wq0qp8~7P4AVjh-Vmy{`7+$Z{2+HyUufOU0Y0)TZ`3%N%t7}^;5+zB z1xUV&s)=Mc!T#HjpSzL4n>JdK|4tzfJ-nfbpRm6M15H|u)ndmN#`WGj7MUa691J$Pmy+Z10m%Grncb^$3)WxB$FDFc7@XLPorkfXUiiD3j zyj%*kbe?wat})A4O6h=vLjxeS8RRwkz4s%I}_A=|)y@W?G%R27QeE zr6$gx8&%Z040&I@;9+Hul&Q{bWEbhx?tscar@jkv-~|Wv*NpVP%Wmf|Zikx)5_iKS z4JVP`Rnv0;LuVA!jZO;~vT@ZZt7WWzibX(v1TpcgxZ`az)BB;ojheBp=wg!he81G> z6nlI`O~?8AZJ)crn9?hE*gBhj?)86z!;Fdu5dVX%J6KG{ROTQHEy1U{n;-(Zw2J2| zyDBw%8%rbpr4TR}(!whE@e_DCN2VR}*XDgEO?0Ajf?0JD7Qm02x2HHtWe;dt*5yP} zsc!A(^CuzG`Ndt0r>|$hP9qvJ9^vCLl-@K+@1e8YEAtY#;y9-kus5cec4DDnKj?|5 zbbJ=tUW&&=;?b%KVsU@Z9Yut&f)G+QVhszpa_h4{k92i*u+?W+uvfEE3@fK_jYE2X zQIN$kCXqaIgm5 zBDvNVDU;8ABUq%)YlY+ODBJW7ZMPNUJ_*Cc+!%+6RfFK~IJA5^Xu0oNKaXknfAB{yklo(Z z>T<-zE)YxgLQ6Aw+JJds-8Cq*{F-JKCm`xw!mCn;B+C4}APr6o*%%E)ycwp}LVA9k z2)O#x_6RfW%EJ?9&TDiC(1I*y&?x5aX63p&Lug`+WT8E2BvinvIORw%XXKmVI>(xA z1-d__&qgxss}kdWx~e;L)%I^!4ITM^di(0AIG%RR!2<+HkPtiscXyjWg3I8+A-F^E z;7JJX?t=~P1b31U+#$HT26wiH-}mj^vwQEkyZ#Z3e-JYhif%+uwDGJ= zV;1tuUA^Tds=*Q8IP27iA{d{FP0N zFm=ho^YXN7q^*qI)WluD=veoWftl%yOWn+hfV2O?H>sdlwkchgYf^t_w{>7v@wX%yzWGn#s%xW4lQp@$1b@g(Nik_Jz%erocZajh5s`tN9o>SR5nt@$%O)yyXg*(b-t)e% zLskNcf7DYUjMJ!mx8|zTfT?5{(fxd(q%+3gI!U~h%L?aMa7ZB*$Q4${r_vx502YC(=%n(c3ZyoV|j&a=A=X< zvFon(Zew^yHEEsk^sl~O(09bv1-R*ZMCefXeluu37Bx>zwZ!`S>V(pXfp1;?fPl9% zyMi@x3d#Mo&%#|0Mzx;EPPJ#Iy& ziN^@t%WJ+2S7Gm7Et>9;Xj_~jpIoVBR7DTQY6V4CE?Rv}uE{2FHR*_>L zKE`a6ZsZTOzEh{3UFWGjAM|t=-fHyw-`%~=QoC=5t=vaPIGZb62nU;@1p0Tt*zS0$lBd z1x_^n-X?AqGxW>l~!zUAt+>{{$1(4wzv$7h#_=2q9{ zV}3Ss<8E0Q65(T7 zI%7A*PV#M68pSN`AB`YsIXbGJAp=%FGcriiJAbPq(bj$XGA@JOYh70+IEESJ*JuQY z|F0}yuqJZSy2so637ixvk+xRSH#3$u>HJGfo9kQC#uY?o^0o!|aWN zAXZ!W*0hxGKQq%6(jMvaLy?t0-w*#P+Y&KVm&nUXc>E><>3Ow2lyJ^GrY%=Z+q<-x zdu4={(1rSB7(qSE4Tqu$N%Fnu3;#-A{uLSUa^FpHI%5%T6eKM7bU3o$Om>`T?n7$h zedhd*X^4oI*>BgGpuDiKm{DoO$2+Uh%XoI(9O`AoG~L{SW=>i&NrB#0y8JJjAIrW# zlY%=9S(71mql*gcLdeXlLGC#JKq?2!2CE}Ku%NgraUr0{P$(a>g=IHN(hQob+O`@} zBm$OH2BsR%j;KAS(fCSs;T@rK-pm+}Q**tr-Hfi?L#|O76FMI3(p?_;Qr<>blF1}H ze)HcZ{CB5E6JBjK)zm`Ir?k12N>)?6tcd`lWT`0d@L;&#;@iXR6LRJN%PV#)D9IeU zVMcxFruY*_fuwo_HCwKIKbn!A66!yATby?_Z)w2nILt8j`C=n0^~5QmON=TJsi9^4 zZmF4j9iF;z)%Prk4sJgwA=PKjNo zM&GirgjyBUS=KwU#0j>~A}&6REnP`5Ek`3kII;RgDw@z+FKE~=J`2lf0|Hu#e#>mSrN2)Rx!GCrQ}LGr@;Ses8655lS1)w^ zOm}Q1cg)uLReFLQ)G4P3D3#=*h(>yy9zJ5c-@ox%;Lf9guxZb(zyFo9OR+=({QmV! zz_KMGAOLoum zG+72rvv#fLY+t_E;rt9ub23sW@YSG?3?lZW}xZ7-G&yzP^ z-^p9c>t40HPut|ZQ`ZYhJph?6k+UHT_Lnx_Pj+*=cvPBia@1MSo|s=*t7P~dpezVX zJ_*K_?d{dl;>~RC(a;_EK3@CQP48PlpL}}Un+=nPrL;K7b9_&=liL$>U#ay5>&a~@b}!fufqIRnFu$~OGGt3qF-$??BwLdI!oYApP0sgT1)2-N%4js2 zec@j2{c;yy{0Ya*hwJNWak`-3;E`6WW8z|uaGa#=T@n@0(0!70NE?%G0;U+rd!1U)`KyO<3t z`-NJ|7g3GP+0}otQfzPDMQEeu{V^z3!SS~In9~M)w;9bX5TQ)A?*O(+`}%C<<7d_CG z+wRUDjuy-Ja$y5VTA|Z5=OH75k5=q2f8aBY;u(6EkQ(sZ)dE;DE6N|cI9a- zsK|g&$F+rTCK-PB5B^sQ?r?Dbm$cP?J?ae@_Wc$A3Bfq<+sNReMN{0mv5B5p0sS}k zfo@^4ieh5HZ%y~kmy-kSj+Y$~%dC62L`)vF9aMZ0;w-mI`@hBX9mz_1P~C8n{P+w4 zZ3m(^-$a;FvU=iz!-@XM5=9lXy1nnf&2P=zVl};bsg+33`o1X5mj(nUs@n~uSJ=mxMjotcC11(duySa7b4m;-(!wpN(l!+rrRz73ZY(AwWbs7p zd%ore?B9Z9q7^PP6OJq83* zv^YdDr{(v|DkRyvf<%|)Htn0eR|UN|`!R{VM%ZPnd6Vd}N|?osDL*fpqJi^=D~q3{ zidzn&!!F>Qx4;sliipqRclPd{o5W5-aq9rP!1Al*bd+U4n6oc2l?U&2vFLPY*9L9R z3N1_C)KZ{xSXo~jGR@d>5n{b>IPP2b+2tC+MT;wZjB}g>5QxNB=ItA`T>mC4tC?4H znElV!vJ74byTqzY{?ClZQ~88{sG(p>M{6t9V;(MvWP1~Xmpx8@)_+KRBj9w3Un*>U zgYJ{oP+?S-0+T{_o+Do`t-15FTpT=kZSF*DQW3=TVCPf6zpN`lv0AUH+K9F*%f&Zr=oe7X{45K5 zPam$skI7#NA*FD)&4lNA{KJ+E`xjes>DBwtSBr=XlJ0BjG(El6OE9kiRH7ayivR6Q`FJyanyQxELE=XW;@!CEXu-POG`B1*f*=e4vN zyZ+v#%EmN%v)1C@$2!-_&ba6JyvI%b35UK6i09z6UD>eq)3+eLFFYM$LbGKNf0nHI zBy?>abb0?Qy9P@ZwU&~!g0A>T z5%ATXU=A`>bk(dM`JZN0t`V%+BBXrZ3q1v~QZt&Dzt8s*pWS2+fHSc6RljQl+xa@_ zNRibWLI@ONuFDx&=h~R9kF=K01C%8rFe!hSDj^p9Ex_bg!?CU!M^Ax;c_iOE2G$aF z6?1z#7txiLX14c#ly(shz+(it0lTTH(}20+em#vW{UU#64IH?2)aYZFkkXB;5Va{J zb8UqlwlQ7t^8UDorg5%k7F)-g=e6hZeUqUb2D4&dDcN$Ld4{&=e2QPz>UjGx#}Cx) zzkXCgPuI4J*vBm?#&3D;}j9& zBjNlFauJR1mb>ka?#5`hYrmIHB}YO3u+!8PbH5xr1^8h^p)SeqIEOs9U~^PbNbI5SjqA z_PuBFP!(fIjc~86YCq%a7kFp6ye-8|<#9O@&gl+#wo*mQ14%>~u-p4Ds8nUoJdf;> zMzL-b!Ca7-eBk6TReV;3*y|JnjNKS06G1|;w}sbcdBhh7Gj#dBuXJ_+Lqb{9o(}K{ zOLlDE@(0^DP9^07FRZ8yQ0k1ZEA&OmcyX0@yi(V5i$;vShNC|`N6Bc67=a0iQ=(t8 zIq9`gNw}az1ZIO@y>M*2=KpX$-N!`oh&UIuGhy#Q8Tls=2wL*kVBOe0okgotT!#&*&Dm&)I*XD#@D-)pISJc`|ztcvJVtK<%JfK z`{bVoaHxsexnJA&(g5)~*;gwXN9QCF`Jb&N>uk{ zsK!8}J|GI+{>7u8I{&16kiLS&d1^6wY5}`IeR+t*ak~BMhI{PV8R>L!DDR=={$K0X zKCG3N_*s`$Y|?Z8>foUH4qHvsG5Fd8tF;HKe!EP=BS=Ublt zIF_g-#6+NJjTh+JHZa6=hO_p_fO=^ojt1G_=Q68~AK&BVtfm|D*vS`O?@3Y>fb#a$}xf&hn7cW4Akm32bmM)7c3yD6nS9R3+(SKP5Ed3bvaMu@bLzyE& z8ibOPVffKW3T`BSr9;4XC~HMwi>lsxL9Wk{sUutV%DjdPUQZAQ&^0K`iiu6L7To-$ zYQp;R*w*bNQY$B&3I1%DI^H!es;GdI-BMW$_fgGJ$9Y@zp*ZHmaheXi9GMaUpIv~9 z2+zUwkVLp;chACH3XXtr8uv27X#tzwXs|B)dRYd9;(Q*NEXDCp)S8Xf9Z&zYfDHEJ zpz5bEx272>0Wmm)FL3}W)Y+1RLH=tYeUH^rOTpKrwn^Tv$GC|7b+}2n6Wh?3p|IT zo%fmt0&fA_uEzi|UCdWUpb_SVyGjDRe8PbZAPUClVL+$WV#!JW$M-0a1;xarFp8AyF>bP2j1lFQxMRMck0FvR<7!UDO~`QFCSbZF9w zLQXml9K$dpyn0l|a2rp=;r7hB7O9^E4cz2qD`z6dU_yBLS6+W>sJ4aGAwt^istc1$ zB;Rv$@_pe)_e2=*wD6m6I(!5{=04;aD@krsVkZMlWnDCtYxPK4B!H@|Mw-Mx37*?g+F0yBmtB(CcE5MY_> zNJlEYx*F8c+LA}o=C3I?$~|TV`lEZ$nI0&Smf0OxsfJ`)<9Fj+KI8m+FA7z3-s$VN zT76PgIy^LLp|PWyiQ|r9U>}ZypyS8v$I|EYe5CX-^eDwlpYiYjVtND0pIa~#IYJ(x zi{|b@5s>9=dHKBT-h$?IO+HOZF?;~Na!7uGaVUH8jPgLTc-i0Yj~3v|+At@{|IMki z`Ul;(B%`;h!OdPJNfsPCel|`HhAamSVVR z+-8Bs*O9>Y;mx=-@C{IF%BxLRYvU4sm!;?I=0$3^9H=)YebCI%_fg1H$9OZ&E11m_k0%Uf=h+r)DsX+s zzZQjNwUSxTtb{fpqH0L=zKt4^Ls_H*JcYl>s47Jp zHsD^HVR4niyT3)~^z|S@sR1%I_%p#6+{Ef1ed6+pYUGqK9&A;j7hs;tl@$GX3bu_p z=vbMT8p;yuPaFr6i@n|<`7mzD(P%ld-GO?<7ijgR)#CgNjsbAa&*j!cGY+pi&uYsK zG<~6%s5#}Y6Bx6%fp7HWyJ%ZSt*N|j0AC71T(maKLBU<}wYI^t2@p32y9EZf#TQxw zNNzegv)^c2=by$QAZ!y9oUh4MhNB{m0%=JZLc@T4#%eXRD%iC4o`Fd6L=oG8c;aA9 z(unznntxH4Dj-7LzX>I04f-zL1!GmVI(+J)gDbG4e8ma$kY~K1V#;vFkVjfFb?=)X zTMT!HD4$7UBdQg>ziL5I3#22)C&*~2s>>U}t0VSM9S*VmH)8PFj(!)4;&Osql!yN@ zu}wxacqfL)3S?Td!2nspWlkTl^#7bLjmSWiIU%{&Rp<`~LUIfOn9?1p)E)8BCk_R- zfhjL6T1T8Nq6Yuw%m)jrg{wff{jDNT55uuJ-oSQGCPJN2f!U8k6pP1?lUO)FCt_qM zD;2i*&2UU=KpF)yW7z%M%iAwE-K+*mHD5V1Lvv?-I^Zhl8pBI}65TEbOi~sY1kNw9 zT*XmTvo=t4&>9`R8^MQX+v2u43qi=*(WsDR#GEXz1?dXY+^Dk?@%=r+JE+$QP|1uT zlO$hR%e7toIu)RTZ)5Lo3w%C7PvB~xr z_N+ATasVdzX-ABx!zilgvwCp&-dAu(Tr_R7ArHhmWqZb}o6|j&$^%pdH0ZhQH3<2$ zSnoR_mKbfAK2j!TEi0lt7p^o4F;3l`GC?@NOoFcA6$vPj@CT&eWMTfPL!xwO&!xBs zo?u~9!-^BNpV^O-YJiIwQ>RGp&kN!*L~#;l02vG(yHm5YEUToj{waGo`Y!B}PE?3D z@B?fc5X~)tmA4`DkPJp4vG|l}N7Ui!Rk6eXc}39G4q_fwckB4f@L3)n!IYFJm`QX;@Cq>8C@gem(S?WW z?`4I&H;=&naXzArmOx!UES_k@u6km<_=CK2lIx4bYex;m&}7OR%J6@5VR9P{D#b8~My`NjZkWe7nk72Qw3SH>X z;V`t~01SL;lvIj6T{3#M<>P|ITIp^H1um0Zdt+!OIWv%(t%owIby$6&wFTp|LPr(H zre6KD5G_6wW`*;{gDU$iKzY99Vs+PpvHqW_s1V|#4R;>w59eH|x{c`FId2{^n^V1C zT1Xnj;?wjcDi-;*S5Ys<1mZ{hIoNt=ts@h$=C;?-b~)E<=%-fVv?b}A_OYKXOC+g{4jvy*>5D5f2!k0u>TRi_ElcJQ-{MFLsYS1%6zM{F*md#21c>@hD%!hgBWGAgz z+;N-7C8jlGF#kRzA-=_6e$GdcTIKw<7C3~`fhUKiR2rQ9`Xif2FY=DqW_O0>acqJ7 zUbcC2Sha!i@Qg}^Y`960FTtBkcJCC9Lv`d@^4{1?{Uk{__wzsW9^x4w&=R@{y5ejE zEezxIBkfbq>Emxl5mgZ=C7aE1pYzFO0n)U>;r6F7zopOtieP zjPthjSAg2+guG+i0lLJGsYIN;&a5O{^5dD6 z5UqUltG88a1J)*eZs#~xk+%jmH8xYe3=X?>xa$Prp51?HTM}%6>U0$ne!M+aQ-JQZ z#?dK^JnZgyLzE59O9-?+`m#+NcEpxxbyj2quFC$Os3obidNX{BrS<+Y z2rGpVYZ*11UN4pM-)c@JtPq;tkJ`W42`Fq!pi>!%OslQie**=uR@6W)vNxAeN_g$T zqpDTuuEw7c9G89=p84y!e-X93YuWsafU9s!-d3!e>w~J}U-ufDi)k{kCg;Qn2?PL= zZ~}C;=)xyzRK=FPqj|laIh=)67n>quA;K)7lSFKzdpB#Rvwy!S zPRgZoTJCh`POWz)&(Kk0fIt~wTBW;t3lC=5Aj!<^zR`j$(mP?4)#y1b$xfFbu7sm( zlcKg|eU0XIk*2sQip41j9_8a!*v|tgF^z)kYr5@SCv_B{o+b1!#8N7+4zhkbqsMdJBj)~ zdzkJc^h1bRq{nWqrsjq$7}#b2;c!RPmo=V^hN^v)Ii@K%tUH5HdGzKgC<=X=?7hS{ zr-f*w%>#Oh-F7bWG=r-y=I~_j5rL^dDYqsrPm{7RNRFC6zTCR7 zzpytpzHMx@z|#NY4m4s|PHnavBVHj>yGbn4?I4<&Vf&;OuDwUj*{2LMWwPq0wI2a~ zezWHStyJ}y(&$xYCrKV;!I2A>rloZdnwYt@o`f+IP3lpl_MH9)0Q&*;wLuEHnzfXZ zSxiBJFO6+TMt+Q_ty1>jC!9Ds=@AZ%68yc$LF2J}eJ`8L_SOL$QSWI3t=8Cc)@4(MINLs=RE2EO(?*lTJf)A<>-~`` z`6HYed^muZFoeaxEc6q28McaPRTt9w*0!JYp~tPkASxMyd$QS8l~&i>je$11{`|mj z3Ps(mM#dCG*Z0F9(>|vCO=v1lvDqdqi*`OH>HrCC7gE8{Fh_`8e4N*3GW`jw`msytyO?QB%+JiYTCa}t|iajPUGs-=4x(N zZ-yLDHnsJNf z(GZ(7upY0K^IZ@Dfk49H%Cf2o&XO@)xTVSf|24za(e-(QDYbHVfmu9)1~V3Xbj@{?FSoAEdt;sb!7_o=jKo4I>|`vsQb2NNNhrFf-6qAbcpnvG>5yOg0Ur4Pyno?6T$vdFmhVc`KU>*fc=I;RWE5MqvJhLS7gxQ1zNP|5<0h!tSw3Gk5WW+TY|#eztq zkf%J#Q|0{25s-(&--B-G0Y9=Ya1T{99i02-&;95mhqNAa@O(SPbUF?B7S6 zNWy2>ZoS~3)B$QFn`S^3S`b@T@(HRJmV|y%Oeo}v0H(o98PfQ`x;R*d6o%T+XZbq; z=iP8!Umw6eV&d09P8fW6Yq{gm3_c@`Doj+h6$F$TWD`@7FQ+=BgRV9tnM|y|lf4TU z(_lH|<@DUbO Date: Sun, 4 Mar 2012 16:26:43 +0100 Subject: [PATCH 02/40] Include README.md in the source tarball This should fix the IOError that occured in setup.py. --- MANIFEST.in | 1 + setup.py | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000000..bb3ec5f0d4 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include README.md diff --git a/setup.py b/setup.py index 75e232550d..88eba45745 100644 --- a/setup.py +++ b/setup.py @@ -14,16 +14,10 @@ requirements.append('argparse>=1.2.1') -try: - long_description = open('README.md').read() -except IOError: - long_description = '' - - setup( name='httpie',version=httpie.__version__, description=httpie.__doc__.strip(), - long_description=long_description, + long_description=open('README.md').read(), url='http://httpie.org/', download_url='https://github.com/jkbr/httpie', author=httpie.__author__, From 71771dc4a6864ce1e6f3c88cb45dd581913beeb5 Mon Sep 17 00:00:00 2001 From: Laurent Bachelier Date: Sun, 4 Mar 2012 16:28:03 +0100 Subject: [PATCH 03/40] One argument per line --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 88eba45745..03bb0b3c20 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,8 @@ setup( - name='httpie',version=httpie.__version__, + name='httpie', + version=httpie.__version__, description=httpie.__doc__.strip(), long_description=open('README.md').read(), url='http://httpie.org/', From e83e601f7c7dc780e6e6ada865f0c4ad304a5204 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Sun, 4 Mar 2012 16:39:57 +0100 Subject: [PATCH 04/40] Added a link to contributors on GitHub to README. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index fc9523f80c..0dad5a0747 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,12 @@ Most of the flags mirror the arguments you would use with `requests.request`. Se --timeout TIMEOUT Float describes the timeout of the request (Use socket.setdefaulttimeout() as fallback). + +### Contributors + +[View contributors on GitHub](https://github.com/jkbr/httpie/contributors). + + ### Changelog * [0.1.6](https://github.com/jkbr/httpie/compare/0.1.4...0.1.6) (2012-03-04) From ce952c9e902504267317a4a2fc27088d29e416a1 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Sun, 4 Mar 2012 16:40:02 +0100 Subject: [PATCH 05/40] Added support for more 256 color terminals. Closes #20. Thanks, @laurentb. --- httpie/pretty.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpie/pretty.py b/httpie/pretty.py index 49870449d6..774839d132 100644 --- a/httpie/pretty.py +++ b/httpie/pretty.py @@ -15,7 +15,7 @@ AVAILABLE_STYLES = [DEFAULT_STYLE] + STYLE_MAP.keys() TYPE_JS = 'application/javascript' FORMATTER = (Terminal256Formatter - if os.environ.get('TERM') == 'xterm-256color' + if '256color' in os.environ.get('TERM', '') else TerminalFormatter) From 8cff0a3e67295280cf430d727568207ce1989582 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Mon, 5 Mar 2012 00:48:06 +0100 Subject: [PATCH 06/40] Updated README. --- README.md => README.rst | 90 +++++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 26 deletions(-) rename README.md => README.rst (53%) diff --git a/README.md b/README.rst similarity index 53% rename from README.md rename to README.rst index 0dad5a0747..b573fad655 100644 --- a/README.md +++ b/README.rst @@ -1,56 +1,92 @@ -## HTTPie: cURL for humans +HTTPie: cURL for humans +======================= -[![Build Status](https://secure.travis-ci.org/jkbr/httpie.png)](http://travis-ci.org/jkbr/httpie) +**HTTPie is a CLI HTTP utility** built out of frustration with existing tools. The goal is to make CLI interaction with HTTP-based services as human-friendly as possible. +HTTPie does so by providing an ``http`` command that allows for issuing arbitrary HTTP requests using a **simple and natural syntax** and displaying **colorized responses**: -HTTPie is a CLI frontend for [python-requests](http://python-requests.org) built out of frustration. It provides an `http` command that can be used to easily issue HTTP requests. It is meant to be used by humans to interact with HTTP-based APIs and web servers. The response headers are colorized and the body is syntax-highlighted if its `Content-Type` is known to [Pygments](http://pygments.org/) (unless the output is redirected). +.. image:: https://github.com/jkbr/httpie/raw/master/httpie.png + :alt: HTTPie compared to cURL -![httpie](https://github.com/jkbr/httpie/raw/master/httpie.png) +Under the hood, HTTPie uses the excellent `Requests `_ and `Pygments `_ Python libraries. -### Installation +Installation +------------ -Latest stable version using [pip](http://www.pip-installer.org/en/latest/index.html): +The latest **stable version** of HTTPie can always be installed (or updated to) via `pip `_:: pip install -U httpie - # easy_install httpie -Master: + +Or, you can install the **development version** directly from GitHub: + +.. image:: https://secure.travis-ci.org/jkbr/httpie.png + :target: http://travis-ci.org/jkbr/httpie + :alt: Build Status of the master branch + +:: pip install -U https://github.com/jkbr/httpie/tarball/master -### Usage +Usage +----- + +Hello world:: + + http GET httpie.org + +Synopsis:: + + http [flags] METHOD URL [items] - http [flags] METHOD URL [header:value | data-field-name=value]* +There are three types of key-value pair items available: -The default request `Content-Type` is `application/json` and data fields are automatically serialized as a JSON `Object`, so this: +Headers + Arbitrary HTTP headers. The ``:`` character is used to separate a header's name from its value, e.g., ``X-API-Token:123``. - http PATCH api.example.com/person/1 X-API-Token:123 name=John email=john@example.org +Simple data items + Data items are included in the request body. Depending on the ``Content-Type``, they are automatically serialized as a JSON ``Object`` (default) or ``application/x-www-form-urlencoded`` (the ``-f`` flag). Data items use ``=`` as the separator, e.g., ``hello=world``. -Will issue the following request: +Raw JSON items + This item type is needed when ``Content-Type`` is JSON and a field's value is a ``Boolean``, ``Number``, nested ``Object`` or an ``Array``, because simple data items are always serialized as ``String``. E.g. ``pies=[1,2,3]``. + +Examples +^^^^^^^^ +:: + + http PATCH api.example.com/person/1 X-API-Token:123 name=John email=john@example.org age:=29 + + +The following request is issued:: PATCH /person/1 HTTP/1.1 User-Agent: HTTPie/0.1 X-API-Token: 123 Content-Type: application/json; charset=utf-8 - {"name": "John", "email": "john@example.org"} + {"name": "John", "email": "john@example.org", "age": 29} -You can pass other types than just strings using the `field:=value` notation. It allows you to set arbitrary JSON to the data fields: - http PUT httpie.org/pies bool:=true list:=[1,2,3] 'object:={"a": "b", "c": "d"}' +It can easily be changed to a 'form' request using the ``-f`` (or ``--form``) flag, which produces:: -Produces the following JSON request: + PATCH /person/1 HTTP/1.1 + User-Agent: HTTPie/0.1 + X-API-Token: 123 + Content-Type: application/x-www-form-urlencoded; charset=utf-8 - {"bool": true, "list": [1, 2, 3], "object": {"a": "b", "c": "d"}} + age=29&name=John&email=john%40example.org -You can use the `--form` flag to set `Content-Type` and serialize the data as `application/x-www-form-urlencoded`. +A whole request body can be passed in via ``stdin`` instead:: -The data to be sent can also be passed via `stdin`: + echo '{"name": "John"}' | http PATCH example.com/person/1 X-API-Token:123 + # Or: + http POST example.com/person/1 X-API-Token:123 < person.json - http PUT api.example.com/person/1 X-API-Token:123 < person.json -Most of the flags mirror the arguments you would use with `requests.request`. See `http -h`: +Flags +^^^^^ +Most of the flags mirror the arguments understood by ``requests.request``. See ``http -h`` for more details:: usage: http [-h] [--version] [--json | --form] [--traceback] [--pretty | --ugly] [--headers | --body] [--style STYLE] @@ -103,11 +139,13 @@ Most of the flags mirror the arguments you would use with `requests.request`. Se socket.setdefaulttimeout() as fallback). -### Contributors +Contributors +------------ -[View contributors on GitHub](https://github.com/jkbr/httpie/contributors). +`View contributors on GitHub `_. -### Changelog +Changelog +--------- -* [0.1.6](https://github.com/jkbr/httpie/compare/0.1.4...0.1.6) (2012-03-04) +* `0.1.6 `_ (2012-03-04) From ccb2aaf94fc7e948c6ad91b789ad5f4b26d7961d Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Mon, 5 Mar 2012 02:54:34 +0100 Subject: [PATCH 07/40] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index b573fad655..40ebc1dc93 100644 --- a/README.rst +++ b/README.rst @@ -49,7 +49,7 @@ Simple data items Data items are included in the request body. Depending on the ``Content-Type``, they are automatically serialized as a JSON ``Object`` (default) or ``application/x-www-form-urlencoded`` (the ``-f`` flag). Data items use ``=`` as the separator, e.g., ``hello=world``. Raw JSON items - This item type is needed when ``Content-Type`` is JSON and a field's value is a ``Boolean``, ``Number``, nested ``Object`` or an ``Array``, because simple data items are always serialized as ``String``. E.g. ``pies=[1,2,3]``. + This item type is needed when ``Content-Type`` is JSON and a field's value is a ``Boolean``, ``Number``, nested ``Object`` or an ``Array``, because simple data items are always serialized as ``String``. E.g. ``pies:=[1,2,3]``. Examples ^^^^^^^^ From f5d4addab224c6bc3ea6e9220ff6727ae3d8c713 Mon Sep 17 00:00:00 2001 From: Chris Faulkner Date: Sun, 4 Mar 2012 22:26:23 -0800 Subject: [PATCH 08/40] Update references to moved README. --- MANIFEST.in | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index bb3ec5f0d4..9561fb1061 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -include README.md +include README.rst diff --git a/setup.py b/setup.py index 03bb0b3c20..e1ef6381bd 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ name='httpie', version=httpie.__version__, description=httpie.__doc__.strip(), - long_description=open('README.md').read(), + long_description=open('README.rst').read(), url='http://httpie.org/', download_url='https://github.com/jkbr/httpie', author=httpie.__author__, From c9eb2255f6355fa2cf8fa7b9f509bddfd5cc6056 Mon Sep 17 00:00:00 2001 From: Praful Mathur Date: Mon, 5 Mar 2012 12:58:21 -0500 Subject: [PATCH 09/40] Added proper JSON highlighting --- httpie/pretty.py | 75 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/httpie/pretty.py b/httpie/pretty.py index 774839d132..1a108d395c 100644 --- a/httpie/pretty.py +++ b/httpie/pretty.py @@ -1,12 +1,13 @@ import os import json import pygments +import re from pygments import token from pygments.util import ClassNotFound from pygments.lexers import get_lexer_for_mimetype from pygments.formatters.terminal256 import Terminal256Formatter from pygments.formatters.terminal import TerminalFormatter -from pygments.lexer import RegexLexer, bygroups +from pygments.lexer import include, RegexLexer, bygroups from pygments.styles import get_style_by_name, STYLE_MAP from . import solarized @@ -31,6 +32,68 @@ class HTTPLexer(RegexLexer): (r'(.*?:)(.+)', bygroups(token.Name, token.String)) ]} +# Stolen from https://github.com/orb/pygments-json +class JSONLexer(RegexLexer): + name = 'JSON Lexer' + aliases = ['json'] + filenames = ['*.json'] + mimetypes = [] + + + flags = re.DOTALL + tokens = { + 'whitespace': [ + (r'\s+', token.Text), + ], + + # represents a simple terminal value + 'simplevalue':[ + (r'(true|false|null)\b', token.Keyword.Constant), + (r'-?[0-9]+', token.Number.Integer), + (r'"(\\\\|\\"|[^"])*"', token.String.Double), + ], + + + # the right hand side of an object, after the attribute name + 'objectattribute': [ + include('value'), + (r':', token.Punctuation), + # comma terminates the attribute but expects more + (r',', token.Punctuation, '#pop'), + # a closing bracket terminates the entire object, so pop twice + (r'}', token.Punctuation, ('#pop', '#pop')), + ], + + # a json object - { attr, attr, ... } + 'objectvalue': [ + include('whitespace'), + (r'"(\\\\|\\"|[^"])*"', token.Name.Tag, 'objectattribute'), + (r'}', token.Punctuation, '#pop'), + ], + + # json array - [ value, value, ... } + 'arrayvalue': [ + include('whitespace'), + include('value'), + (r',', token.Punctuation), + (r']', token.Punctuation, '#pop'), + ], + + # a json value - either a simple value or a complex value (object or array) + 'value': [ + include('whitespace'), + include('simplevalue'), + (r'{', token.Punctuation, 'objectvalue'), + (r'\[', token.Punctuation, 'arrayvalue'), + ], + + + # the root of a json document would be a value + 'root': [ + include('value'), + ], + + } class PrettyHttp(object): @@ -52,11 +115,13 @@ def body(self, content, content_type): # Indent JSON content = json.dumps(json.loads(content), sort_keys=True, indent=4) + lexer = JSONLexer() except Exception: pass - try: - lexer = get_lexer_for_mimetype(content_type) - except ClassNotFound: - return content + else: + try: + lexer = get_lexer_for_mimetype(content_type) + except ClassNotFound: + return content content = pygments.highlight(content, lexer, self.formatter) return content From 3c8af4c1700ae8a7768820ad064ed207e122930f Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Fri, 9 Mar 2012 14:18:00 +0100 Subject: [PATCH 10/40] Added BSD license text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HTTPie is going to be packaged for Debian and this will make it easier. The license and © is still the same as before. --- LICENSE | 26 ++++++++++++++++++++++++++ MANIFEST.in | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..3384890165 --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +Copyright © 2012 Jakub Roztocil + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of The author nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in index 9561fb1061..0c738421d6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -include README.rst +include README.rst LICENSE From 20408e12e9115bd9e825bbcbad37f73e2e519d60 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Fri, 9 Mar 2012 14:18:00 +0100 Subject: [PATCH 11/40] Added BSD license text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HTTPie is going to be packaged for Debian and this will make it easier. The license and © is still the same as before. --- LICENSE | 26 ++++++++++++++++++++++++++ MANIFEST.in | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..3384890165 --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +Copyright © 2012 Jakub Roztocil + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of The author nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in index 9561fb1061..0c738421d6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -include README.rst +include README.rst LICENSE From 31c28807c932cb3de2923bd45d5e6b13732b4e94 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Tue, 13 Mar 2012 21:42:18 +0100 Subject: [PATCH 12/40] Added better JSON highlighting A JSON-specific lexer for Pygments by Norman Richards (@orb) has been added. It attempts to provide more interesting syntax highlighting which correctly distinguishes between attribute names and values. Closes #25. --- httpie/pretty.py | 78 +++++------------------------------------------- httpie/pygson.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 71 deletions(-) create mode 100644 httpie/pygson.py diff --git a/httpie/pretty.py b/httpie/pretty.py index 1a108d395c..68e846e01a 100644 --- a/httpie/pretty.py +++ b/httpie/pretty.py @@ -1,20 +1,19 @@ import os import json import pygments -import re from pygments import token from pygments.util import ClassNotFound from pygments.lexers import get_lexer_for_mimetype from pygments.formatters.terminal256 import Terminal256Formatter from pygments.formatters.terminal import TerminalFormatter -from pygments.lexer import include, RegexLexer, bygroups +from pygments.lexer import RegexLexer, bygroups from pygments.styles import get_style_by_name, STYLE_MAP from . import solarized +from .pygson import JSONLexer DEFAULT_STYLE = 'solarized' AVAILABLE_STYLES = [DEFAULT_STYLE] + STYLE_MAP.keys() -TYPE_JS = 'application/javascript' FORMATTER = (Terminal256Formatter if '256color' in os.environ.get('TERM', '') else TerminalFormatter) @@ -32,68 +31,6 @@ class HTTPLexer(RegexLexer): (r'(.*?:)(.+)', bygroups(token.Name, token.String)) ]} -# Stolen from https://github.com/orb/pygments-json -class JSONLexer(RegexLexer): - name = 'JSON Lexer' - aliases = ['json'] - filenames = ['*.json'] - mimetypes = [] - - - flags = re.DOTALL - tokens = { - 'whitespace': [ - (r'\s+', token.Text), - ], - - # represents a simple terminal value - 'simplevalue':[ - (r'(true|false|null)\b', token.Keyword.Constant), - (r'-?[0-9]+', token.Number.Integer), - (r'"(\\\\|\\"|[^"])*"', token.String.Double), - ], - - - # the right hand side of an object, after the attribute name - 'objectattribute': [ - include('value'), - (r':', token.Punctuation), - # comma terminates the attribute but expects more - (r',', token.Punctuation, '#pop'), - # a closing bracket terminates the entire object, so pop twice - (r'}', token.Punctuation, ('#pop', '#pop')), - ], - - # a json object - { attr, attr, ... } - 'objectvalue': [ - include('whitespace'), - (r'"(\\\\|\\"|[^"])*"', token.Name.Tag, 'objectattribute'), - (r'}', token.Punctuation, '#pop'), - ], - - # json array - [ value, value, ... } - 'arrayvalue': [ - include('whitespace'), - include('value'), - (r',', token.Punctuation), - (r']', token.Punctuation, '#pop'), - ], - - # a json value - either a simple value or a complex value (object or array) - 'value': [ - include('whitespace'), - include('simplevalue'), - (r'{', token.Punctuation, 'objectvalue'), - (r'\[', token.Punctuation, 'arrayvalue'), - ], - - - # the root of a json document would be a value - 'root': [ - include('value'), - ], - - } class PrettyHttp(object): @@ -108,20 +45,19 @@ def headers(self, content): return pygments.highlight(content, HTTPLexer(), self.formatter) def body(self, content, content_type): + lexer = None content_type = content_type.split(';')[0] if 'json' in content_type: - content_type = TYPE_JS + lexer = JSONLexer() try: - # Indent JSON + # Indent the JSON data. content = json.dumps(json.loads(content), sort_keys=True, indent=4) - lexer = JSONLexer() except Exception: pass - else: + if not lexer: try: lexer = get_lexer_for_mimetype(content_type) except ClassNotFound: return content - content = pygments.highlight(content, lexer, self.formatter) - return content + return pygments.highlight(content, lexer, self.formatter) diff --git a/httpie/pygson.py b/httpie/pygson.py new file mode 100644 index 0000000000..be0492b3a8 --- /dev/null +++ b/httpie/pygson.py @@ -0,0 +1,77 @@ +""" +JSON lexer by Norman Richards + +It's already been merged into Pygments but not released yet, +so we are temporarily bundling it with HTTPie. + +It can be removed once Pygments > 1.4 has been released. + +See for more details. + +""" +import re +from pygments import token +from pygments.lexer import RegexLexer, include + + +class JSONLexer(RegexLexer): + name = 'JSON Lexer' + aliases = ['json'] + filenames = ['*.json'] + mimetypes = [] + + + flags = re.DOTALL + tokens = { + 'whitespace': [ + (r'\s+', token.Text), + ], + + # represents a simple terminal value + 'simplevalue':[ + (r'(true|false|null)\b', token.Keyword.Constant), + (r'-?[0-9]+', token.Number.Integer), + (r'"(\\\\|\\"|[^"])*"', token.String.Double), + ], + + + # the right hand side of an object, after the attribute name + 'objectattribute': [ + include('value'), + (r':', token.Punctuation), + # comma terminates the attribute but expects more + (r',', token.Punctuation, '#pop'), + # a closing bracket terminates the entire object, so pop twice + (r'}', token.Punctuation, ('#pop', '#pop')), + ], + + # a json object - { attr, attr, ... } + 'objectvalue': [ + include('whitespace'), + (r'"(\\\\|\\"|[^"])*"', token.Name.Tag, 'objectattribute'), + (r'}', token.Punctuation, '#pop'), + ], + + # json array - [ value, value, ... } + 'arrayvalue': [ + include('whitespace'), + include('value'), + (r',', token.Punctuation), + (r']', token.Punctuation, '#pop'), + ], + + # a json value - either a simple value or a complex value (object or array) + 'value': [ + include('whitespace'), + include('simplevalue'), + (r'{', token.Punctuation, 'objectvalue'), + (r'\[', token.Punctuation, 'arrayvalue'), + ], + + + # the root of a json document would be a value + 'root': [ + include('value'), + ], + + } From 02622a4135077b2635428fbf6885927b80b55b68 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 00:05:44 +0100 Subject: [PATCH 13/40] Added the option to print the request It is now possible to print any combination of the following request-response bits: - Request headers (H) - Request body (B) - Response headers (h) - Response body (b) The output is controlled by the --print / -p option which defaults to "hb" (i.e., response headers and response body). Note that -p was previously shortcut for --prety. Closes #29. --- LICENSE | 2 +- README.rst | 24 ++++++--- httpie/__init__.py | 2 +- httpie/__main__.py | 120 +++++++++++++++++++++++++++++++++------------ httpie/cli.py | 77 ++++++++++++++++++++++------- httpie/pretty.py | 2 +- 6 files changed, 169 insertions(+), 58 deletions(-) diff --git a/LICENSE b/LICENSE index 3384890165..027da677e9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright © 2012 Jakub Roztocil +Copyright © 2012 Jakub Roztocil Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.rst b/README.rst index 40ebc1dc93..562d02b5be 100644 --- a/README.rst +++ b/README.rst @@ -89,10 +89,12 @@ Flags Most of the flags mirror the arguments understood by ``requests.request``. See ``http -h`` for more details:: usage: http [-h] [--version] [--json | --form] [--traceback] - [--pretty | --ugly] [--headers | --body] [--style STYLE] - [--auth AUTH] [--verify VERIFY] [--proxy PROXY] - [--allow-redirects] [--file PATH] [--timeout TIMEOUT] - METHOD URL [items [items ...]] + [--pretty | --ugly] + [--print OUTPUT_OPTIONS | --headers | --body] + [--style STYLE] [--auth AUTH] [--verify VERIFY] + [--proxy PROXY] [--allow-redirects] [--file PATH] + [--timeout TIMEOUT] + METHOD URL [items [items ...]] HTTPie - cURL for humans. @@ -113,13 +115,21 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` Type to application/x-www-form-urlencoded, if not specified. --traceback Print exception traceback should one occur. - --pretty, -p If stdout is a terminal, the response is prettified by + --pretty If stdout is a terminal, the response is prettified by default (colorized and indented if it is JSON). This flag ensures prettifying even when stdout is redirected. --ugly, -u Do not prettify the response. - --headers, -t Print only the response headers. - --body, -b Print only the response body. + --print OUTPUT_OPTIONS, -p OUTPUT_OPTIONS + String specifying what should the output contain. "H" + stands for request headers and "B" for request body. + "h" stands for response headers and "b" for response + body. Defaults to "hb" which means that the whole + response (headers and body) is printed. + --headers, -t Print only the response headers. It's a shortcut for + --print=h. + --body, -b Print only the response body. It's a shortcut for + --print=b. --style STYLE, -s STYLE Output coloring style, one of autumn, borland, bw, colorful, default, emacs, friendly, fruity, manni, diff --git a/httpie/__init__.py b/httpie/__init__.py index 1bf9b61bc3..861218351d 100644 --- a/httpie/__init__.py +++ b/httpie/__init__.py @@ -3,5 +3,5 @@ """ __author__ = 'Jakub Roztocil' -__version__ = '0.1.6' +__version__ = '0.1.7-dev' __licence__ = 'BSD' diff --git a/httpie/__main__.py b/httpie/__main__.py index 713bda134d..3b5dda13ff 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -2,6 +2,7 @@ import os import sys import json +from urlparse import urlparse import requests try: from collections import OrderedDict @@ -18,6 +19,69 @@ TYPE_JSON = 'application/json; charset=utf-8' +class HTTPMessage(object): + + def __init__(self, line, headers, body, content_type=None): + # {Request,Status}-Line + self.line = line + self.headers = headers + self.body = body + self.content_type = content_type + + +def format_http_message(message, prettifier=None, + with_headers=True, with_body=True): + bits = [] + if with_headers: + if prettifier: + bits.append(prettifier.headers(message.line)) + bits.append(prettifier.headers(message.headers)) + else: + bits.append(message.line) + bits.append(message.headers) + if with_body: + bits.append('\n') + if with_body: + if prettifier and message.content_type: + bits.append(prettifier.body(message.body, message.content_type)) + else: + bits.append(message.body) + bits = [bit.strip() for bit in bits] + bits.append('') + return '\n'.join(bits) + + +def make_request_message(request): + """Make an `HTTPMessage` from `requests.models.Request`.""" + url = urlparse(request.url) + request_headers = dict(request.headers) + request_headers['Host'] = url.netloc + return HTTPMessage( + line='{method} {path} HTTP/1.1'.format( + method=request.method, + path=url.path), + headers='\n'.join('%s: %s' % (name, value) + for name, value + in request_headers.iteritems()), + body=request._enc_data, + content_type=request_headers.get('Content-Type') + ) + + +def make_response_message(response): + """Make an `HTTPMessage` from `requests.models.Response`.""" + encoding = response.encoding or 'ISO-8859-1' + original = response.raw._original_response + response_headers = response.headers + return HTTPMessage( + line='HTTP/{version} {status} {reason}'.format( + version='.'.join(str(original.version)), + status=original.status, reason=original.reason,), + headers=str(original.msg).decode(encoding), + body=response.content.decode(encoding) if response.content else u'', + content_type=response_headers.get('Content-Type')) + + def main(args=None, stdin=sys.stdin, stdin_isatty=sys.stdin.isatty(), @@ -28,7 +92,8 @@ def main(args=None, args = parser.parse_args(args if args is not None else sys.argv[1:]) do_prettify = (args.prettify is True or - (args.prettify == cli.PRETTIFY_STDOUT_TTY_ONLY and stdout_isatty)) + (args.prettify == cli.PRETTIFY_STDOUT_TTY_ONLY + and stdout_isatty)) # Parse request headers and data from the command line. headers = CaseInsensitiveDict() @@ -79,36 +144,31 @@ def main(args=None, sys.stderr.write(str(e.message) + '\n') sys.exit(1) - # Reconstruct the raw response. - encoding = response.encoding or 'ISO-8859-1' - original = response.raw._original_response - status_line, headers, body = ( - 'HTTP/{version} {status} {reason}'.format( - version='.'.join(str(original.version)), - status=original.status, reason=original.reason, - ), - str(original.msg).decode(encoding), - response.content.decode(encoding) if response.content else u'' - ) + prettifier = pretty.PrettyHttp(args.style) if do_prettify else None - if do_prettify: - prettify = pretty.PrettyHttp(args.style) - if args.print_headers: - status_line = prettify.headers(status_line) - headers = prettify.headers(headers) - if args.print_body and 'Content-Type' in response.headers: - body = prettify.body(body, response.headers['Content-Type']) - - # Output. - # TODO: preserve leading/trailing whitespaces in the body. - # Some of the Pygments styles add superfluous line breaks. - if args.print_headers: - stdout.write(status_line.strip()) - stdout.write('\n') - stdout.write(headers.strip().encode('utf-8')) - stdout.write('\n\n') - if args.print_body: - stdout.write(body.strip().encode('utf-8')) + output_request = (cli.OUT_REQUEST_HEADERS in args.output_options + or cli.OUT_REQUEST_BODY in args.output_options) + + output_response = (cli.OUT_RESPONSE_HEADERS in args.output_options + or cli.OUT_RESPONSE_BODY in args.output_options) + + if output_request: + stdout.write(format_http_message( + message=make_request_message(response.request), + prettifier=prettifier, + with_headers=cli.OUT_REQUEST_HEADERS in args.output_options, + with_body=cli.OUT_REQUEST_BODY in args.output_options + ).encode('utf-8')) + if output_response: + stdout.write('\n') + + if output_response: + stdout.write(format_http_message( + message=make_response_message(response), + prettifier=prettifier, + with_headers=cli.OUT_RESPONSE_HEADERS in args.output_options, + with_body=cli.OUT_RESPONSE_BODY in args.output_options + ).encode('utf-8')) stdout.write('\n') diff --git a/httpie/cli.py b/httpie/cli.py index 36c864078f..584cb7c724 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -12,6 +12,16 @@ SEP_DATA_RAW_JSON = ':=' PRETTIFY_STDOUT_TTY_ONLY = object() +OUT_REQUEST_HEADERS = 'H' +OUT_REQUEST_BODY = 'B' +OUT_RESPONSE_HEADERS = 'h' +OUT_RESPONSE_BODY = 'b' + +OUTPUT_OPTIONS = [OUT_REQUEST_HEADERS, + OUT_REQUEST_BODY, + OUT_RESPONSE_HEADERS, + OUT_RESPONSE_BODY] + class ParseError(Exception): pass @@ -72,7 +82,19 @@ def _(text): return ' '.join(text.strip().split()) -parser = argparse.ArgumentParser(description=doc.strip(),) +class HTTPieArgumentParser(argparse.ArgumentParser): + def parse_args(self, args=None, namespace=None): + args = super(HTTPieArgumentParser, self).parse_args(args, namespace) + self._validate_output_options(args) + return args + + def _validate_output_options(self, args): + unknown_output_options = set(args.output_options) - set(OUTPUT_OPTIONS) + if unknown_output_options: + self.error('Unknown output options: %s' % ','.join(unknown_output_options)) + + +parser = HTTPieArgumentParser(description=doc.strip(),) parser.add_argument('--version', action='version', version=version) # Content type. @@ -96,7 +118,7 @@ def _(text): ) -# Output options. +# output_options options. ############################################# parser.add_argument( @@ -108,13 +130,12 @@ def _(text): prettify = parser.add_mutually_exclusive_group(required=False) prettify.add_argument( - '--pretty', '-p', dest='prettify', action='store_true', + '--pretty', dest='prettify', action='store_true', default=PRETTIFY_STDOUT_TTY_ONLY, help=_(''' - If stdout is a terminal, - the response is prettified by default (colorized and - indented if it is JSON). This flag ensures - prettifying even when stdout is redirected. + If stdout is a terminal, the response is prettified + by default (colorized and indented if it is JSON). + This flag ensures prettifying even when stdout is redirected. ''') ) prettify.add_argument( @@ -124,21 +145,41 @@ def _(text): ''') ) -only = parser.add_mutually_exclusive_group(required=False) -only.add_argument( - '--headers', '-t', dest='print_body', - action='store_false', default=True, - help=(''' +output_options = parser.add_mutually_exclusive_group(required=False) +output_options.add_argument('--print', '-p', dest='output_options', + default=OUT_RESPONSE_HEADERS + OUT_RESPONSE_BODY, + help=_(''' + String specifying what should the output contain. + "{request_headers}" stands for request headers and + "{request_body}" for request body. + "{response_headers}" stands for response headers and + "{response_body}" for response body. + Defaults to "hb" which means that the whole response + (headers and body) is printed. + '''.format( + request_headers=OUT_REQUEST_HEADERS, + request_body=OUT_REQUEST_BODY, + response_headers=OUT_RESPONSE_HEADERS, + response_body=OUT_RESPONSE_BODY, + )) +) +output_options.add_argument( + '--headers', '-t', dest='output_options', + action='store_const', const=OUT_RESPONSE_HEADERS, + help=_(''' Print only the response headers. - ''') + It's a shortcut for --print={0}. + '''.format(OUT_RESPONSE_HEADERS)) ) -only.add_argument( - '--body', '-b', dest='print_headers', - action='store_false', default=True, - help=(''' +output_options.add_argument( + '--body', '-b', dest='output_options', + action='store_const', const=OUT_RESPONSE_BODY, + help=_(''' Print only the response body. - ''') + It's a shortcut for --print={0}. + '''.format(OUT_RESPONSE_BODY)) ) + parser.add_argument( '--style', '-s', dest='style', default='solarized', metavar='STYLE', choices=pretty.AVAILABLE_STYLES, diff --git a/httpie/pretty.py b/httpie/pretty.py index 68e846e01a..f63eaff12d 100644 --- a/httpie/pretty.py +++ b/httpie/pretty.py @@ -8,8 +8,8 @@ from pygments.formatters.terminal import TerminalFormatter from pygments.lexer import RegexLexer, bygroups from pygments.styles import get_style_by_name, STYLE_MAP -from . import solarized from .pygson import JSONLexer +from . import solarized DEFAULT_STYLE = 'solarized' From 5e19e1b95d601ea004388e4cc79937cbb78673b4 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 00:58:05 +0100 Subject: [PATCH 14/40] Added a "New in development version" link. --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 562d02b5be..3331adea5e 100644 --- a/README.rst +++ b/README.rst @@ -158,4 +158,5 @@ Contributors Changelog --------- +* `New in development version `_ * `0.1.6 `_ (2012-03-04) From ed888a2657baa311ec8a60aaca00f388056eb955 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 01:10:28 +0100 Subject: [PATCH 15/40] Made sure request Host is correct when printing. --- httpie/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/httpie/__main__.py b/httpie/__main__.py index 3b5dda13ff..44f3c11771 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -55,7 +55,8 @@ def make_request_message(request): """Make an `HTTPMessage` from `requests.models.Request`.""" url = urlparse(request.url) request_headers = dict(request.headers) - request_headers['Host'] = url.netloc + if 'Host' not in request_headers: + request_headers['Host'] = url.netloc return HTTPMessage( line='{method} {path} HTTP/1.1'.format( method=request.method, From 578acacdf3b15fddcae4306fbd752a9e3238a6ee Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 11:14:28 +0100 Subject: [PATCH 16/40] Added a --verbose / -v flag When set, the whole request as well as the response is printed. Shortcut for --print=HBhb. --- httpie/cli.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/httpie/cli.py b/httpie/cli.py index 584cb7c724..c06d350058 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -163,12 +163,20 @@ def _validate_output_options(self, args): response_body=OUT_RESPONSE_BODY, )) ) +output_options.add_argument( + '--verbose', '-v', dest='output_options', + action='store_const', const=''.join(OUTPUT_OPTIONS), + help=_(''' + Print the whole request as well as response. + Shortcut for --print={0}. + '''.format(''.join(OUTPUT_OPTIONS))) +) output_options.add_argument( '--headers', '-t', dest='output_options', action='store_const', const=OUT_RESPONSE_HEADERS, help=_(''' Print only the response headers. - It's a shortcut for --print={0}. + Shortcut for --print={0}. '''.format(OUT_RESPONSE_HEADERS)) ) output_options.add_argument( @@ -176,7 +184,7 @@ def _validate_output_options(self, args): action='store_const', const=OUT_RESPONSE_BODY, help=_(''' Print only the response body. - It's a shortcut for --print={0}. + Shortcut for --print={0}. '''.format(OUT_RESPONSE_BODY)) ) From b7e0473d6cb9155e6b54c5e0ba10a9a3544dd2af Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 12:17:39 +0100 Subject: [PATCH 17/40] Added file upload support It is now possible to send multipart/form-data requests. Note that the --file option used previously has been removed because it didn't allow you specify the field name. Example: http -f POST example.com field-name@/path/to/file --- .travis.yml | 2 +- README.rst | 50 ++++++++++++++++++++++---------------- httpie/__main__.py | 19 ++++++++++++--- httpie/cli.py | 42 ++++++++++++++++++++------------ tests/file.txt | 1 + tests.py => tests/tests.py | 26 +++++++++++++++++--- 6 files changed, 95 insertions(+), 45 deletions(-) create mode 100644 tests/file.txt rename tests.py => tests/tests.py (79%) diff --git a/.travis.yml b/.travis.yml index 36b8a13ed3..b5b2acae97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ python: - 2.7 # TODO: Python 3 #- 3.2 -script: python tests.py +script: python tests/tests.py install: - pip install requests pygments - "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install argparse; fi" diff --git a/README.rst b/README.rst index 3331adea5e..9768edaf5c 100644 --- a/README.rst +++ b/README.rst @@ -40,15 +40,18 @@ Synopsis:: http [flags] METHOD URL [items] -There are three types of key-value pair items available: +There are four types of key-value pair items available: Headers Arbitrary HTTP headers. The ``:`` character is used to separate a header's name from its value, e.g., ``X-API-Token:123``. -Simple data items +Simple data fields Data items are included in the request body. Depending on the ``Content-Type``, they are automatically serialized as a JSON ``Object`` (default) or ``application/x-www-form-urlencoded`` (the ``-f`` flag). Data items use ``=`` as the separator, e.g., ``hello=world``. -Raw JSON items +File fields + Only available with ``-f`` / ``--form``. Use ``@`` as the separator, e.g., ``screenshot@/path/to/file.png``. + +Raw JSON fields This item type is needed when ``Content-Type`` is JSON and a field's value is a ``Boolean``, ``Number``, nested ``Object`` or an ``Array``, because simple data items are always serialized as ``String``. E.g. ``pies:=[1,2,3]``. Examples @@ -77,6 +80,17 @@ It can easily be changed to a 'form' request using the ``-f`` (or ``--form``) fl age=29&name=John&email=john%40example.org +It is also possible to send ``multipart/form-data`` requests, i.e., to simulate a file upload form submission. It is done using the ``--form`` / ``-f`` flag and passing one or more file fields:: + + http -f POST example.com/job-application email=John cv@~/Documents/cv.pdf + +The above will send a request equivalent to submitting the following form:: + +
+ + +
+ A whole request body can be passed in via ``stdin`` instead:: echo '{"name": "John"}' | http PATCH example.com/person/1 X-API-Token:123 @@ -88,14 +102,6 @@ Flags ^^^^^ Most of the flags mirror the arguments understood by ``requests.request``. See ``http -h`` for more details:: - usage: http [-h] [--version] [--json | --form] [--traceback] - [--pretty | --ugly] - [--print OUTPUT_OPTIONS | --headers | --body] - [--style STYLE] [--auth AUTH] [--verify VERIFY] - [--proxy PROXY] [--allow-redirects] [--file PATH] - [--timeout TIMEOUT] - METHOD URL [items [items ...]] - HTTPie - cURL for humans. positional arguments: @@ -103,17 +109,20 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` PUT, DELETE, PATCH, ...). URL Protocol defaults to http:// if the URL does not include it. - items HTTP header (key:value), data field (key=value) or raw - JSON field (field:=value). + items HTTP header (header:value), data field (field=value), + raw JSON field (field:=value) or file field + (field@/path/to/file). optional arguments: -h, --help show this help message and exit --version show program's version number and exit --json, -j Serialize data items as a JSON object and set Content- Type to application/json, if not specified. - --form, -f Serialize data items as form values and set Content- - Type to application/x-www-form-urlencoded, if not - specified. + --form, -f Serialize fields as form values. The Content-Type is + set to application/x-www-form-urlencoded. The presence + of any file fields results into a multipart/form-data + request. Note that Content-Type is not automatically + set if explicitely specified. --traceback Print exception traceback should one occur. --pretty If stdout is a terminal, the response is prettified by default (colorized and indented if it is JSON). This @@ -126,10 +135,11 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` "h" stands for response headers and "b" for response body. Defaults to "hb" which means that the whole response (headers and body) is printed. - --headers, -t Print only the response headers. It's a shortcut for + --verbose, -v Print the whole request as well as response. Shortcut + for --print=HBhb. + --headers, -t Print only the response headers. Shortcut for --print=h. - --body, -b Print only the response body. It's a shortcut for - --print=b. + --body, -b Print only the response body. Shortcut for --print=b. --style STYLE, -s STYLE Output coloring style, one of autumn, borland, bw, colorful, default, emacs, friendly, fruity, manni, @@ -144,11 +154,9 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` http:foo.bar:3128). --allow-redirects Set this flag if full redirects are allowed (e.g. re- POST-ing of data at new ``Location``) - --file PATH File to multipart upload --timeout TIMEOUT Float describes the timeout of the request (Use socket.setdefaulttimeout() as fallback). - Contributors ------------ diff --git a/httpie/__main__.py b/httpie/__main__.py index 44f3c11771..e06c47b14f 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -100,26 +100,37 @@ def main(args=None, headers = CaseInsensitiveDict() headers['User-Agent'] = DEFAULT_UA data = OrderedDict() + files = OrderedDict() try: - cli.parse_items(items=args.items, headers=headers, data=data) + cli.parse_items(items=args.items, headers=headers, + data=data, files=files) except cli.ParseError as e: if args.traceback: raise parser.error(e.message) + if files and not args.form: + # We could just switch to --form automatically here, + # but I think it's better to make it explicit. + parser.error( + ' You need to set the --form / -f flag to' + ' to issue a multipart request. File fields: %s' + % ','.join(files.keys())) + if not stdin_isatty: if data: parser.error('Request body (stdin) and request ' 'data (key=value) cannot be mixed.') data = stdin.read() + # JSON/Form content type. if args.json or (not args.form and data): if stdin_isatty: data = json.dumps(data) - if 'Content-Type' not in headers and (data or args.json): + if not files and ('Content-Type' not in headers and (data or args.json)): headers['Content-Type'] = TYPE_JSON - elif 'Content-Type' not in headers: + elif not files and 'Content-Type' not in headers: headers['Content-Type'] = TYPE_FORM # Fire the request. @@ -133,7 +144,7 @@ def main(args=None, timeout=args.timeout, auth=(args.auth.key, args.auth.value) if args.auth else None, proxies=dict((p.key, p.value) for p in args.proxy), - files=dict((os.path.basename(f.name), f) for f in args.file), + files=files, allow_redirects=args.allow_redirects, ) except (KeyboardInterrupt, SystemExit): diff --git a/httpie/cli.py b/httpie/cli.py index c06d350058..70830f890b 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -1,3 +1,4 @@ +import os import json import argparse from collections import namedtuple @@ -10,6 +11,7 @@ SEP_HEADERS = SEP_COMMON SEP_DATA = '=' SEP_DATA_RAW_JSON = ':=' +SEP_FILES = '@' PRETTIFY_STDOUT_TTY_ONLY = object() OUT_REQUEST_HEADERS = 'H' @@ -49,16 +51,28 @@ def __call__(self, string): return KeyValue(key=key, value=value, sep=sep, orig=string) -def parse_items(items, data=None, headers=None): - """Parse `KeyValueType` `items` into `data` and `headers`.""" +def parse_items(items, data=None, headers=None, files=None): + """Parse `KeyValueType` `items` into `data`, `headers` and `files`.""" if headers is None: headers = {} if data is None: data = {} + if files is None: + files = {} for item in items: value = item.value + key = item.key if item.sep == SEP_HEADERS: target = headers + elif item.sep == SEP_FILES: + try: + value = open(os.path.expanduser(item.value), 'r') + except IOError as e: + raise ParseError( + 'Invalid argument %r. %s' % (item.orig, e)) + if not key: + key = os.path.basename(value.name) + target = files elif item.sep in [SEP_DATA, SEP_DATA_RAW_JSON]: if item.sep == SEP_DATA_RAW_JSON: try: @@ -69,12 +83,12 @@ def parse_items(items, data=None, headers=None): else: raise ParseError('%s is not valid item' % item.orig) - if item.key in target: + if key in target: ParseError('duplicate item %s (%s)' % (item.key, item.orig)) - target[item.key] = value + target[key] = value - return headers, data + return headers, data, files def _(text): @@ -111,9 +125,9 @@ def _validate_output_options(self, args): group_type.add_argument( '--form', '-f', action='store_true', help=_(''' - Serialize data items as form values and set - Content-Type to application/x-www-form-urlencoded, - if not specified. + Serialize fields as form values. The Content-Type is set to application/x-www-form-urlencoded. + The presence of any file fields results into a multipart/form-data request. + Note that Content-Type is not automatically set if explicitely specified. ''') ) @@ -225,11 +239,6 @@ def _validate_output_options(self, args): (e.g. re-POST-ing of data at new ``Location``) ''') ) -parser.add_argument( - '--file', metavar='PATH', type=argparse.FileType(), - default=[], action='append', - help='File to multipart upload' -) parser.add_argument( '--timeout', type=float, help=_(''' @@ -258,9 +267,10 @@ def _validate_output_options(self, args): ) parser.add_argument( 'items', nargs='*', - type=KeyValueType(SEP_COMMON, SEP_DATA, SEP_DATA_RAW_JSON), + type=KeyValueType(SEP_COMMON, SEP_DATA, SEP_DATA_RAW_JSON, SEP_FILES), help=_(''' - HTTP header (key:value), data field (key=value) - or raw JSON field (field:=value). + HTTP header (header:value), data field (field=value), + raw JSON field (field:=value) + or file field (field@/path/to/file). ''') ) diff --git a/tests/file.txt b/tests/file.txt new file mode 100644 index 0000000000..fba7ccb994 --- /dev/null +++ b/tests/file.txt @@ -0,0 +1 @@ +__test_file_content__ diff --git a/tests.py b/tests/tests.py similarity index 79% rename from tests.py rename to tests/tests.py index 0cb2911abe..f099aa8b97 100644 --- a/tests.py +++ b/tests/tests.py @@ -1,7 +1,13 @@ +# coding:utf8 +import os import sys import unittest import argparse from StringIO import StringIO + + +TESTS_ROOT = os.path.dirname(__file__) +sys.path.insert(0, os.path.abspath(os.path.join(TESTS_ROOT, '..'))) from httpie import __main__ from httpie import cli @@ -82,7 +88,7 @@ def test_json(self): self.assertIn('"foo": "bar"', response) def test_form(self): - response = http('POST', '--form', 'http://httpbin.org/post', 'foo=bar') + response = http('--form', 'POST', 'http://httpbin.org/post', 'foo=bar') self.assertIn('"foo": "bar"', response) def test_headers(self): @@ -103,13 +109,27 @@ def test_pretty_enabled_by_default_unless_stdin_redirected(self): self.assertNotIn(TERMINAL_COLOR_CHECK, r) def test_force_pretty(self): - r = http('GET', '--pretty', 'http://httpbin.org/get', stdout_isatty=False) + r = http('--pretty', 'GET', 'http://httpbin.org/get', stdout_isatty=False) self.assertIn(TERMINAL_COLOR_CHECK, r) def test_force_ugly(self): - r = http('GET', '--ugly', 'http://httpbin.org/get', stdout_isatty=True) + r = http('--ugly', 'GET', 'http://httpbin.org/get', stdout_isatty=True) self.assertNotIn(TERMINAL_COLOR_CHECK, r) +class TestFileUpload(BaseTest): + + def test_non_existent_file_raises_parse_error(self): + self.assertRaises(cli.ParseError, http, + '--form', '--traceback', + 'POST', 'http://httpbin.org/post', + 'foo@/__does_not_exist__') + + def test_upload_ok(self): + r = http('--form', 'POST', 'http://httpbin.org/post', + 'test-file@%s' % os.path.join(TESTS_ROOT, 'file.txt')) + self.assertIn('"test-file": "__test_file_content__', r) + + if __name__ == '__main__': unittest.main() From 6a1f0248e186c4c012cfcdb5e8b49976e3946b74 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 19:21:47 +0100 Subject: [PATCH 18/40] Fixed tests. --- tests/tests.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index f099aa8b97..98c290e81a 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -5,13 +5,15 @@ import argparse from StringIO import StringIO - TESTS_ROOT = os.path.dirname(__file__) -sys.path.insert(0, os.path.abspath(os.path.join(TESTS_ROOT, '..'))) +sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) from httpie import __main__ from httpie import cli +TEST_FILE = os.path.join(TESTS_ROOT, 'file.txt') + + TERMINAL_COLOR_CHECK = '\x1b[' @@ -46,7 +48,8 @@ def setUp(self): self.kv = cli.KeyValueType( cli.SEP_HEADERS, cli.SEP_DATA, - cli.SEP_DATA_RAW_JSON + cli.SEP_DATA_RAW_JSON, + cli.SEP_FILES, ) def test_invalid_items(self): @@ -56,7 +59,7 @@ def test_invalid_items(self): lambda: self.kv(item)) def test_valid_items(self): - headers, data = cli.parse_items([ + headers, data, files = cli.parse_items([ self.kv('string=value'), self.kv('header:value'), self.kv('list:=["a", 1, {}, false]'), @@ -64,6 +67,7 @@ def test_valid_items(self): self.kv('eh:'), self.kv('ed='), self.kv('bool:=true'), + self.kv('test-file@%s' % TEST_FILE), ]) self.assertDictEqual(headers, { 'header': 'value', @@ -76,6 +80,7 @@ def test_valid_items(self): "list": ["a", 1, {}, False], "obj": {"a": "b"} }) + self.assertIn('test-file', files) class TestHTTPie(BaseTest): @@ -127,7 +132,7 @@ def test_non_existent_file_raises_parse_error(self): def test_upload_ok(self): r = http('--form', 'POST', 'http://httpbin.org/post', - 'test-file@%s' % os.path.join(TESTS_ROOT, 'file.txt')) + 'test-file@%s' % TEST_FILE) self.assertIn('"test-file": "__test_file_content__', r) From ccbea8c96ef9136f233f3704544f3d646b0f5313 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 19:30:12 +0100 Subject: [PATCH 19/40] Assume "/" as the Request-URI for printing when none present. --- httpie/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpie/__main__.py b/httpie/__main__.py index e06c47b14f..6df1f332e3 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -60,7 +60,7 @@ def make_request_message(request): return HTTPMessage( line='{method} {path} HTTP/1.1'.format( method=request.method, - path=url.path), + path=url.path or '/'), headers='\n'.join('%s: %s' % (name, value) for name, value in request_headers.iteritems()), From e2e749b2a6c8315be7d6364017e85f1302902423 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 19:30:58 +0100 Subject: [PATCH 20/40] Improved request formatting. --- httpie/__main__.py | 4 ++-- httpie/pretty.py | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/httpie/__main__.py b/httpie/__main__.py index 6df1f332e3..7a8a994a79 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -39,9 +39,9 @@ def format_http_message(message, prettifier=None, else: bits.append(message.line) bits.append(message.headers) - if with_body: + if with_body and message.body: bits.append('\n') - if with_body: + if with_body and message.body: if prettifier and message.content_type: bits.append(prettifier.body(message.body, message.content_type)) else: diff --git a/httpie/pretty.py b/httpie/pretty.py index f63eaff12d..2b11181023 100644 --- a/httpie/pretty.py +++ b/httpie/pretty.py @@ -26,9 +26,14 @@ class HTTPLexer(RegexLexer): tokens = { 'root': [ (r'\s+', token.Text), + # Request-Line + (r'([A-Z]+\s+)(/.*?)(\s+HTTP/[\d.]+)', bygroups( + token.Keyword, token.String, token.Keyword)), + # Status-Line (r'(HTTP/[\d.]+\s+)(\d+)(\s+.+)', bygroups( - token.Operator, token.Number, token.String)), - (r'(.*?:)(.+)', bygroups(token.Name, token.String)) + token.Keyword, token.Number, token.String)), + # Header + (r'(.*?:)(.+)', bygroups(token.Name, token.Keyword)) ]} From 1f49900db6416690a95829e25bce4b224cab9f73 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 14 Mar 2012 22:55:09 +0100 Subject: [PATCH 21/40] Improved README. --- README.rst | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index 9768edaf5c..0e814b65ed 100644 --- a/README.rst +++ b/README.rst @@ -42,18 +42,19 @@ Synopsis:: There are four types of key-value pair items available: -Headers +Headers (``Name:Value``) Arbitrary HTTP headers. The ``:`` character is used to separate a header's name from its value, e.g., ``X-API-Token:123``. -Simple data fields +Simple data fields (``field=value``) Data items are included in the request body. Depending on the ``Content-Type``, they are automatically serialized as a JSON ``Object`` (default) or ``application/x-www-form-urlencoded`` (the ``-f`` flag). Data items use ``=`` as the separator, e.g., ``hello=world``. -File fields - Only available with ``-f`` / ``--form``. Use ``@`` as the separator, e.g., ``screenshot@/path/to/file.png``. - -Raw JSON fields +Raw JSON fields (``field:=value``) This item type is needed when ``Content-Type`` is JSON and a field's value is a ``Boolean``, ``Number``, nested ``Object`` or an ``Array``, because simple data items are always serialized as ``String``. E.g. ``pies:=[1,2,3]``. +File fields (``field@/path/to/file``) + Only available with ``-f`` / ``--form``. Use ``@`` as the separator, e.g., ``screenshot@/path/to/file.png``. The presence of a file field results into a ``multipart/form-data`` request. + + Examples ^^^^^^^^ :: @@ -82,12 +83,12 @@ It can easily be changed to a 'form' request using the ``-f`` (or ``--form``) fl It is also possible to send ``multipart/form-data`` requests, i.e., to simulate a file upload form submission. It is done using the ``--form`` / ``-f`` flag and passing one or more file fields:: - http -f POST example.com/job-application email=John cv@~/Documents/cv.pdf + http -f POST example.com/jobs name=John cv@~/Documents/cv.pdf -The above will send a request equivalent to submitting the following form:: +The above will send the same request as if the following HTML form were submitted:: -
- + +
From 51aa0409e6cf82a96a0b4f616c6b41e1c5549fee Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Thu, 15 Mar 2012 00:11:49 +0100 Subject: [PATCH 22/40] Added Python 3 support Closes #11. --- .travis.yml | 5 +++-- README.rst | 2 +- httpie/__main__.py | 34 ++++++++++++++++------------------ httpie/pretty.py | 2 +- setup.py | 7 +++---- tests/tests.py | 23 +++++++++++++---------- 6 files changed, 37 insertions(+), 36 deletions(-) diff --git a/.travis.yml b/.travis.yml index b5b2acae97..8d447e03be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,9 @@ language: python python: - 2.6 - 2.7 - # TODO: Python 3 - #- 3.2 + - 3.1 + - 3.2 + - 3.3 script: python tests/tests.py install: - pip install requests pygments diff --git a/README.rst b/README.rst index 0e814b65ed..d3b6835138 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ HTTPie does so by providing an ``http`` command that allows for issuing arbitrar .. image:: https://github.com/jkbr/httpie/raw/master/httpie.png :alt: HTTPie compared to cURL -Under the hood, HTTPie uses the excellent `Requests `_ and `Pygments `_ Python libraries. +Under the hood, HTTPie uses the excellent `Requests `_ and `Pygments `_ Python libraries. Python >= 2.6 is supported (including Python 3.x). Installation ------------ diff --git a/httpie/__main__.py b/httpie/__main__.py index 7a8a994a79..cd9e2de639 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -1,19 +1,19 @@ #!/usr/bin/env python -import os import sys import json -from urlparse import urlparse -import requests try: from collections import OrderedDict except ImportError: OrderedDict = dict +import requests +from requests.compat import urlparse, str from requests.structures import CaseInsensitiveDict from . import cli from . import pretty from . import __version__ as version +NEW_LINE = str('\n') DEFAULT_UA = 'HTTPie/%s' % version TYPE_FORM = 'application/x-www-form-urlencoded; charset=utf-8' TYPE_JSON = 'application/json; charset=utf-8' @@ -40,15 +40,14 @@ def format_http_message(message, prettifier=None, bits.append(message.line) bits.append(message.headers) if with_body and message.body: - bits.append('\n') + bits.append(NEW_LINE) if with_body and message.body: if prettifier and message.content_type: bits.append(prettifier.body(message.body, message.content_type)) else: bits.append(message.body) - bits = [bit.strip() for bit in bits] - bits.append('') - return '\n'.join(bits) + bits.append(NEW_LINE) + return NEW_LINE.join(bit.strip() for bit in bits) def make_request_message(request): @@ -61,9 +60,9 @@ def make_request_message(request): line='{method} {path} HTTP/1.1'.format( method=request.method, path=url.path or '/'), - headers='\n'.join('%s: %s' % (name, value) + headers=NEW_LINE.join(str('%s: %s') % (name, value) for name, value - in request_headers.iteritems()), + in request_headers.items()), body=request._enc_data, content_type=request_headers.get('Content-Type') ) @@ -78,8 +77,8 @@ def make_response_message(response): line='HTTP/{version} {status} {reason}'.format( version='.'.join(str(original.version)), status=original.status, reason=original.reason,), - headers=str(original.msg).decode(encoding), - body=response.content.decode(encoding) if response.content else u'', + headers=str(original.msg), + body=response.content.decode(encoding) if response.content else '', content_type=response_headers.get('Content-Type')) @@ -123,7 +122,6 @@ def main(args=None, 'data (key=value) cannot be mixed.') data = stdin.read() - # JSON/Form content type. if args.json or (not args.form and data): if stdin_isatty: @@ -148,12 +146,12 @@ def main(args=None, allow_redirects=args.allow_redirects, ) except (KeyboardInterrupt, SystemExit): - sys.stderr.write('\n') + sys.stderr.write(NEW_LINE) sys.exit(1) except Exception as e: if args.traceback: raise - sys.stderr.write(str(e.message) + '\n') + sys.stderr.write(str(e.message) + NEW_LINE) sys.exit(1) prettifier = pretty.PrettyHttp(args.style) if do_prettify else None @@ -170,9 +168,9 @@ def main(args=None, prettifier=prettifier, with_headers=cli.OUT_REQUEST_HEADERS in args.output_options, with_body=cli.OUT_REQUEST_BODY in args.output_options - ).encode('utf-8')) + )) if output_response: - stdout.write('\n') + stdout.write(NEW_LINE) if output_response: stdout.write(format_http_message( @@ -180,8 +178,8 @@ def main(args=None, prettifier=prettifier, with_headers=cli.OUT_RESPONSE_HEADERS in args.output_options, with_body=cli.OUT_RESPONSE_BODY in args.output_options - ).encode('utf-8')) - stdout.write('\n') + )) + stdout.write(NEW_LINE) if __name__ == '__main__': diff --git a/httpie/pretty.py b/httpie/pretty.py index 2b11181023..7fea796955 100644 --- a/httpie/pretty.py +++ b/httpie/pretty.py @@ -13,7 +13,7 @@ DEFAULT_STYLE = 'solarized' -AVAILABLE_STYLES = [DEFAULT_STYLE] + STYLE_MAP.keys() +AVAILABLE_STYLES = [DEFAULT_STYLE] + list(STYLE_MAP.keys()) FORMATTER = (Terminal256Formatter if '256color' in os.environ.get('TERM', '') else TerminalFormatter) diff --git a/setup.py b/setup.py index e1ef6381bd..b7d0337cad 100644 --- a/setup.py +++ b/setup.py @@ -36,10 +36,9 @@ 'Programming Language :: Python', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', - # TODO: Python 3 - # 'Programming Language :: Python :: 3.1' - # 'Programming Language :: Python :: 3.2' - # 'Programming Language :: Python :: 3.3' + 'Programming Language :: Python :: 3.1' + 'Programming Language :: Python :: 3.2' + 'Programming Language :: Python :: 3.3' 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', diff --git a/tests/tests.py b/tests/tests.py index 98c290e81a..a8504760b2 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,9 +1,10 @@ -# coding:utf8 +# coding:utf-8 import os import sys import unittest import argparse -from StringIO import StringIO +from requests.compat import StringIO, is_py26, str + TESTS_ROOT = os.path.dirname(__file__) sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) @@ -12,9 +13,7 @@ TEST_FILE = os.path.join(TESTS_ROOT, 'file.txt') - - -TERMINAL_COLOR_CHECK = '\x1b[' +TERMINAL_COLOR_PRESENCE_CHECK = '\x1b[' def http(*args, **kwargs): @@ -30,7 +29,7 @@ def http(*args, **kwargs): class BaseTest(unittest.TestCase): - if sys.version < (2, 7): + if is_py26: def assertIn(self, member, container, msg=None): self.assert_(member in container, msg) @@ -88,6 +87,10 @@ class TestHTTPie(BaseTest): def test_get(self): http('GET', 'http://httpbin.org/get') + def test_verbose(self): + r = http('--verbose', 'GET', 'http://httpbin.org/get', 'test-header:__test__') + self.assertEqual(r.count('__test__'), 2) + def test_json(self): response = http('POST', 'http://httpbin.org/post', 'foo=bar') self.assertIn('"foo": "bar"', response) @@ -107,19 +110,19 @@ class TestPrettyFlag(BaseTest): def test_pretty_enabled_by_default(self): r = http('GET', 'http://httpbin.org/get', stdout_isatty=True) - self.assertIn(TERMINAL_COLOR_CHECK, r) + self.assertIn(TERMINAL_COLOR_PRESENCE_CHECK, r) def test_pretty_enabled_by_default_unless_stdin_redirected(self): r = http('GET', 'http://httpbin.org/get', stdout_isatty=False) - self.assertNotIn(TERMINAL_COLOR_CHECK, r) + self.assertNotIn(TERMINAL_COLOR_PRESENCE_CHECK, r) def test_force_pretty(self): r = http('--pretty', 'GET', 'http://httpbin.org/get', stdout_isatty=False) - self.assertIn(TERMINAL_COLOR_CHECK, r) + self.assertIn(TERMINAL_COLOR_PRESENCE_CHECK, r) def test_force_ugly(self): r = http('--ugly', 'GET', 'http://httpbin.org/get', stdout_isatty=True) - self.assertNotIn(TERMINAL_COLOR_CHECK, r) + self.assertNotIn(TERMINAL_COLOR_PRESENCE_CHECK, r) class TestFileUpload(BaseTest): From 3dbb61a8cacb683a97ee48b0d6a553f52ad7a391 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Thu, 15 Mar 2012 00:22:29 +0100 Subject: [PATCH 23/40] Added `argparse` for Python 3.1. --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b7d0337cad..7156958ebc 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,8 @@ requirements = ['requests>=0.10.4', 'Pygments>=1.4'] -if sys.version_info < (2, 7): +if sys.version_info[:2] in ((2, 6), (3, 1)): + # argparse has been added in Python 3.2 / 2.7 requirements.append('argparse>=1.2.1') From ab23037582205ec50904389989e51913257f86a3 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Thu, 15 Mar 2012 00:28:15 +0100 Subject: [PATCH 24/40] Python 3 fixes. --- .travis.yml | 3 +-- README.rst | 2 +- setup.py | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8d447e03be..7effe4ccb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,8 @@ python: - 2.7 - 3.1 - 3.2 - - 3.3 script: python tests/tests.py install: - pip install requests pygments - - "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install argparse; fi" + - "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]] || [[ $TRAVIS_PYTHON_VERSION == '3.1' ]]; then echo pip install argparse; fi" diff --git a/README.rst b/README.rst index d3b6835138..13ef9eefd2 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ HTTPie does so by providing an ``http`` command that allows for issuing arbitrar .. image:: https://github.com/jkbr/httpie/raw/master/httpie.png :alt: HTTPie compared to cURL -Under the hood, HTTPie uses the excellent `Requests `_ and `Pygments `_ Python libraries. Python >= 2.6 is supported (including Python 3.x). +Under the hood, HTTPie uses the excellent `Requests `_ and `Pygments `_ Python libraries. Python 2.6+ is supported (including 3.x). Installation ------------ diff --git a/setup.py b/setup.py index 7156958ebc..b18c76de9a 100644 --- a/setup.py +++ b/setup.py @@ -39,7 +39,6 @@ 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.1' 'Programming Language :: Python :: 3.2' - 'Programming Language :: Python :: 3.3' 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', From 1c5fd184655a1a3225a01b06675f8ae60ea3dc1a Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Thu, 15 Mar 2012 00:31:12 +0100 Subject: [PATCH 25/40] Python 3 fixes (travis config). --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7effe4ccb1..470a635ddc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,5 +7,5 @@ python: script: python tests/tests.py install: - pip install requests pygments - - "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]] || [[ $TRAVIS_PYTHON_VERSION == '3.1' ]]; then echo pip install argparse; fi" + - "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]] || [[ $TRAVIS_PYTHON_VERSION == '3.1' ]]; then pip install argparse; fi" From 153663cb92bd7f4072fcdc1119fe1a2d17f53bce Mon Sep 17 00:00:00 2001 From: Davey Shafik Date: Thu, 22 Mar 2012 10:40:03 -0400 Subject: [PATCH 26/40] Add support for Digest authentication --- httpie/__main__.py | 8 +++++++- httpie/cli.py | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/httpie/__main__.py b/httpie/__main__.py index cd9e2de639..342527b01b 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -133,6 +133,12 @@ def main(args=None, # Fire the request. try: + credentials = None + if args.auth and args.digest: + credentials = requests.auth.HTTPDigestAuth(args.auth.key, args.auth.value) + elif args.auth: + credentials = requests.auth.HTTPBasicAuth(args.auth.key, args.auth.value) + response = requests.request( method=args.method.lower(), url=args.url if '://' in args.url else 'http://%s' % args.url, @@ -140,7 +146,7 @@ def main(args=None, data=data, verify=True if args.verify == 'yes' else args.verify, timeout=args.timeout, - auth=(args.auth.key, args.auth.value) if args.auth else None, + auth=credentials, proxies=dict((p.key, p.value) for p in args.proxy), files=files, allow_redirects=args.allow_redirects, diff --git a/httpie/cli.py b/httpie/cli.py index 70830f890b..dd9c290fd1 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -215,6 +215,11 @@ def _validate_output_options(self, args): '--auth', '-a', help='username:password', type=KeyValueType(SEP_COMMON) ) + +parser.add_argument( + '--digest', '-d', action='store_true', help=_('Use Digest authentication') +) + parser.add_argument( '--verify', help=_(''' From 71d21d1feb831e58080947e570b417fde08e0267 Mon Sep 17 00:00:00 2001 From: "Matthew M. Boedicker" Date: Thu, 5 Apr 2012 12:55:05 -0400 Subject: [PATCH 27/40] make --verify no command line argument work --- httpie/__main__.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/httpie/__main__.py b/httpie/__main__.py index cd9e2de639..ec3c5cd085 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -131,6 +131,13 @@ def main(args=None, elif not files and 'Content-Type' not in headers: headers['Content-Type'] = TYPE_FORM + if args.verify == 'yes': + verify = True + elif args.verify == 'no': + verify = False + else: + verify = args.verify + # Fire the request. try: response = requests.request( @@ -138,7 +145,7 @@ def main(args=None, url=args.url if '://' in args.url else 'http://%s' % args.url, headers=headers, data=data, - verify=True if args.verify == 'yes' else args.verify, + verify=verify, timeout=args.timeout, auth=(args.auth.key, args.auth.value) if args.auth else None, proxies=dict((p.key, p.value) for p in args.proxy), From c6c1489212ccfc00c955507779ad87ca9b7c46ef Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 11 Apr 2012 12:44:02 +0200 Subject: [PATCH 28/40] Refactored @mmb's fix to --verify; updated docs. Closes #32. --- README.rst | 16 ++++++++++++---- httpie/__main__.py | 9 +-------- httpie/cli.py | 5 +++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index 13ef9eefd2..9c2ae2c64c 100644 --- a/README.rst +++ b/README.rst @@ -103,6 +103,13 @@ Flags ^^^^^ Most of the flags mirror the arguments understood by ``requests.request``. See ``http -h`` for more details:: + usage: http [-h] [--version] [--json | --form] [--traceback] + [--pretty | --ugly] + [--print OUTPUT_OPTIONS | --verbose | --headers | --body] + [--style STYLE] [--auth AUTH] [--verify VERIFY] + [--proxy PROXY] [--allow-redirects] [--timeout TIMEOUT] + METHOD URL [items [items ...]] + HTTPie - cURL for humans. positional arguments: @@ -147,10 +154,11 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` monokai, murphy, native, pastie, perldoc, solarized, tango, trac, vim, vs. Defaults to solarized. --auth AUTH, -a AUTH username:password - --verify VERIFY Set to "yes" to check the host's SSL certificate. You - can also pass the path to a CA_BUNDLE file for private - certs. You can also set the REQUESTS_CA_BUNDLE - environment variable. + --verify VERIFY Set to "no" to skip checking the host's SSL + certificate. You can also pass the path to a CA_BUNDLE + file for private certs. You can also set the + REQUESTS_CA_BUNDLE environment variable. Defaults to + "yes". --proxy PROXY String mapping protocol to the URL of the proxy (e.g. http:foo.bar:3128). --allow-redirects Set this flag if full redirects are allowed (e.g. re- diff --git a/httpie/__main__.py b/httpie/__main__.py index ec3c5cd085..1064f46af1 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -131,13 +131,6 @@ def main(args=None, elif not files and 'Content-Type' not in headers: headers['Content-Type'] = TYPE_FORM - if args.verify == 'yes': - verify = True - elif args.verify == 'no': - verify = False - else: - verify = args.verify - # Fire the request. try: response = requests.request( @@ -145,7 +138,7 @@ def main(args=None, url=args.url if '://' in args.url else 'http://%s' % args.url, headers=headers, data=data, - verify=verify, + verify={'yes': True, 'no': False}.get(args.verify, args.verify), timeout=args.timeout, auth=(args.auth.key, args.auth.value) if args.auth else None, proxies=dict((p.key, p.value) for p in args.proxy), diff --git a/httpie/cli.py b/httpie/cli.py index 70830f890b..e907b21292 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -216,12 +216,13 @@ def _validate_output_options(self, args): type=KeyValueType(SEP_COMMON) ) parser.add_argument( - '--verify', + '--verify', default='yes', help=_(''' - Set to "yes" to check the host\'s SSL certificate. + Set to "no" to skip checking the host\'s SSL certificate. You can also pass the path to a CA_BUNDLE file for private certs. You can also set the REQUESTS_CA_BUNDLE environment variable. + Defaults to "yes". ''') ) parser.add_argument( From 0c4c6c47536a853cf1ac0bb3ff69261a380173e3 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 11 Apr 2012 13:47:47 +0200 Subject: [PATCH 29/40] Added --auth-type and tests for basic/digest auth. Closes #38. --- httpie/__main__.py | 9 +++++---- httpie/cli.py | 9 ++++++++- tests/tests.py | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/httpie/__main__.py b/httpie/__main__.py index 7854faa195..d7b12067bc 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -134,10 +134,11 @@ def main(args=None, # Fire the request. try: credentials = None - if args.auth and args.digest: - credentials = requests.auth.HTTPDigestAuth(args.auth.key, args.auth.value) - elif args.auth: - credentials = requests.auth.HTTPBasicAuth(args.auth.key, args.auth.value) + if args.auth: + auth_type = (requests.auth.HTTPDigestAuth + if args.auth_type == 'digest' + else requests.auth.HTTPBasicAuth) + credentials = auth_type(args.auth.key, args.auth.value) response = requests.request( method=args.method.lower(), diff --git a/httpie/cli.py b/httpie/cli.py index 48f512ea92..3287454697 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -100,6 +100,7 @@ class HTTPieArgumentParser(argparse.ArgumentParser): def parse_args(self, args=None, namespace=None): args = super(HTTPieArgumentParser, self).parse_args(args, namespace) self._validate_output_options(args) + self._validate_auth_options(args) return args def _validate_output_options(self, args): @@ -107,6 +108,11 @@ def _validate_output_options(self, args): if unknown_output_options: self.error('Unknown output options: %s' % ','.join(unknown_output_options)) + def _validate_auth_options(self, args): + if args.auth_type and not args.auth: + self.error('--auth-type can only be used with --auth') + + parser = HTTPieArgumentParser(description=doc.strip(),) parser.add_argument('--version', action='version', version=version) @@ -217,7 +223,8 @@ def _validate_output_options(self, args): ) parser.add_argument( - '--digest', '-d', action='store_true', help=_('Use Digest authentication') + '--auth-type', choices=['basic', 'digest'], + help=_('The type of authentication ("basic" or "digest"). Defaults to "basic".') ) parser.add_argument( diff --git a/tests/tests.py b/tests/tests.py index a8504760b2..0570d4465a 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -139,5 +139,20 @@ def test_upload_ok(self): self.assertIn('"test-file": "__test_file_content__', r) +class TestAuth(BaseTest): + + def test_basic_auth(self): + r = http('--auth', 'user:password', + 'GET', 'httpbin.org/basic-auth/user/password') + self.assertIn('"authenticated": true', r) + self.assertIn('"user": "user"', r) + + def test_digest_auth(self): + r = http('--auth-type=digest', '--auth', 'user:password', + 'GET', 'httpbin.org/digest-auth/auth/user/password') + self.assertIn('"authenticated": true', r) + self.assertIn('"user": "user"', r) + + if __name__ == '__main__': unittest.main() From 4da3821bc49113357af5bf683ab9cfddd693916a Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 11 Apr 2012 22:21:11 +0200 Subject: [PATCH 30/40] Lowered the minimum version of requests required So that the Debian package works out of the box: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=663506 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b18c76de9a..9401a0ff92 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ sys.exit() -requirements = ['requests>=0.10.4', 'Pygments>=1.4'] +requirements = ['requests>=0.10.1', 'Pygments>=1.4'] if sys.version_info[:2] in ((2, 6), (3, 1)): # argparse has been added in Python 3.2 / 2.7 requirements.append('argparse>=1.2.1') From 45ce446017f355981de72dbcd10feb32e1aaf711 Mon Sep 17 00:00:00 2001 From: Jake Basile Date: Sat, 14 Apr 2012 14:13:53 -0500 Subject: [PATCH 31/40] -j/--json now adds "Accept": "application/json" to GET requests if no previous Accept header exists. --- httpie/__main__.py | 2 ++ tests/tests.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/httpie/__main__.py b/httpie/__main__.py index d7b12067bc..1759d1a020 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -124,6 +124,8 @@ def main(args=None, # JSON/Form content type. if args.json or (not args.form and data): + if args.method.lower() == 'get' and 'Accept' not in headers: + headers['Accept'] = 'application/json' if stdin_isatty: data = json.dumps(data) if not files and ('Content-Type' not in headers and (data or args.json)): diff --git a/tests/tests.py b/tests/tests.py index 0570d4465a..cf5a0959b0 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -94,6 +94,10 @@ def test_verbose(self): def test_json(self): response = http('POST', 'http://httpbin.org/post', 'foo=bar') self.assertIn('"foo": "bar"', response) + response2 = http('-j', 'GET', 'http://httpbin.org/headers') + self.assertIn('"Accept": "application/json"', response2) + response3 = http('-j', 'GET', 'http://httpbin.org/headers', 'Accept:application/xml') + self.assertIn('"Accept": "application/xml"', response3) def test_form(self): response = http('--form', 'POST', 'http://httpbin.org/post', 'foo=bar') From c29981c6330531c4bea19dad9b83038e2cfd3df4 Mon Sep 17 00:00:00 2001 From: Jake Basile Date: Mon, 16 Apr 2012 20:28:08 -0500 Subject: [PATCH 32/40] Added ability to escape parameters... except for the := ones. --- httpie/cli.py | 36 +++++++++++++++++++++++++++++++----- tests/tests.py | 20 ++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/httpie/cli.py b/httpie/cli.py index 3287454697..2f8c8453d5 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -1,6 +1,7 @@ import os import json import argparse +import re from collections import namedtuple from . import pretty from . import __doc__ as doc @@ -31,6 +32,19 @@ class ParseError(Exception): KeyValue = namedtuple('KeyValue', ['key', 'value', 'sep', 'orig']) +def find_separator(string, sep, depth = 1): + for i in range(depth): + loc = string.find(sep) + if loc != -1: + # check if previous char is escape char + possible_escape = loc - 1 + if possible_escape <= 0 or string[possible_escape] != '\\': + return loc + else: + # remove the escape char + string = string.replace('\\' + sep, sep, 1) + return find_separator(string, sep, depth + 1) + class KeyValueType(object): """A type used with `argparse`.""" @@ -38,16 +52,28 @@ def __init__(self, *separators): self.separators = separators def __call__(self, string): - found = dict((string.find(sep), sep) - for sep in self.separators - if string.find(sep) != -1) + found = {} + for sep in self.separators: + regex = '[^\\\\]' + sep + match = re.search(regex, string) + if match: + found[match.start() + 1] = sep if not found: #noinspection PyExceptionInherit raise argparse.ArgumentTypeError( '"%s" is not a valid value' % string) - sep = found[min(found.keys())] - key, value = string.split(sep, 1) + + # split the string at the earliest non-escaped separator. + seploc = min(found.keys()) + sep = found[seploc] + key = string[:seploc] + value = string[seploc + len(sep):] + + # remove escape chars + for sepstr in self.separators: + key = key.replace('\\' + sepstr, sepstr) + value = value.replace('\\' + sepstr, sepstr) return KeyValue(key=key, value=value, sep=sep, orig=string) diff --git a/tests/tests.py b/tests/tests.py index cf5a0959b0..3302672054 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -57,6 +57,26 @@ def test_invalid_items(self): self.assertRaises(argparse.ArgumentTypeError, lambda: self.kv(item)) + def test_escape(self): + headers, data, files = cli.parse_items([ + # headers + self.kv('foo\\:bar:baz'), + self.kv('jack\\@jill:hill'), + # data + self.kv('baz\\=bar=foo'), + # files + self.kv('bar\\@baz@%s' % TEST_FILE) + ]) + self.assertDictEqual(headers, { + 'foo:bar': 'baz', + 'jack@jill': 'hill', + }) + self.assertDictEqual(data, { + 'baz=bar': 'foo', + }) + self.assertIn('bar@baz', files) + + def test_valid_items(self): headers, data, files = cli.parse_items([ self.kv('string=value'), From 16df8848e81eefac830f407e4b985f42b52970da Mon Sep 17 00:00:00 2001 From: Jake Basile Date: Mon, 16 Apr 2012 20:47:13 -0500 Subject: [PATCH 33/40] Removed accidentally included old funky code. --- httpie/cli.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/httpie/cli.py b/httpie/cli.py index 2f8c8453d5..22797a53c5 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -32,20 +32,6 @@ class ParseError(Exception): KeyValue = namedtuple('KeyValue', ['key', 'value', 'sep', 'orig']) -def find_separator(string, sep, depth = 1): - for i in range(depth): - loc = string.find(sep) - if loc != -1: - # check if previous char is escape char - possible_escape = loc - 1 - if possible_escape <= 0 or string[possible_escape] != '\\': - return loc - else: - # remove the escape char - string = string.replace('\\' + sep, sep, 1) - return find_separator(string, sep, depth + 1) - - class KeyValueType(object): """A type used with `argparse`.""" def __init__(self, *separators): From 90af1f742230831792d74d303d1e7ce56c96d4bd Mon Sep 17 00:00:00 2001 From: Jake Basile Date: Wed, 18 Apr 2012 18:18:00 -0500 Subject: [PATCH 34/40] Fixed escaping for long separators. --- httpie/cli.py | 18 ++++++++++++++---- tests/tests.py | 7 +++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/httpie/cli.py b/httpie/cli.py index 22797a53c5..29a55f6d88 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -36,14 +36,24 @@ class KeyValueType(object): """A type used with `argparse`.""" def __init__(self, *separators): self.separators = separators + self.escapes = ['\\\\' + sep for sep in separators] def __call__(self, string): found = {} + found_escapes = [] + for esc in self.escapes: + found_escapes += [m.span() for m in re.finditer(esc, string)] for sep in self.separators: - regex = '[^\\\\]' + sep - match = re.search(regex, string) - if match: - found[match.start() + 1] = sep + matches = re.finditer(sep, string) + for match in matches: + start, end = match.span() + inside_escape = False + for estart, eend in found_escapes: + if start >= estart and end <= eend: + inside_escape = True + break + if not inside_escape: + found[start] = sep if not found: #noinspection PyExceptionInherit diff --git a/tests/tests.py b/tests/tests.py index 3302672054..ea77d6aee1 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -76,6 +76,13 @@ def test_escape(self): }) self.assertIn('bar@baz', files) + def test_escape_longsep(self): + headers, data, files = cli.parse_items([ + self.kv('bob\\:==foo'), + ]) + self.assertDictEqual(data, { + 'bob:=': 'foo', + }) def test_valid_items(self): headers, data, files = cli.parse_items([ From 67d6426360930b77158cb1fd544e1f1bd4af83c3 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 25 Apr 2012 00:08:40 +0200 Subject: [PATCH 35/40] Fixed several unicode-related issues Closes #31 Python 3 & non-ascii arguments => UnicodeEncodeError Closes #41 Unicode response error. Closes #42 UnicodeEncodeError when piping Unicode output --- httpie/__main__.py | 37 +++++++++++++++++++++---------------- httpie/cli.py | 42 ++++++++++++++++++++++-------------------- tests/tests.py | 12 ++++++++---- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/httpie/__main__.py b/httpie/__main__.py index 1759d1a020..3d27b2990b 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -6,7 +6,7 @@ except ImportError: OrderedDict = dict import requests -from requests.compat import urlparse, str +from requests.compat import urlparse, str, is_py3 from requests.structures import CaseInsensitiveDict from . import cli from . import pretty @@ -165,30 +165,35 @@ def main(args=None, prettifier = pretty.PrettyHttp(args.style) if do_prettify else None - output_request = (cli.OUT_REQUEST_HEADERS in args.output_options - or cli.OUT_REQUEST_BODY in args.output_options) + do_output_request = (cli.OUT_REQ_HEADERS in args.output_options + or cli.OUT_REQ_BODY in args.output_options) - output_response = (cli.OUT_RESPONSE_HEADERS in args.output_options - or cli.OUT_RESPONSE_BODY in args.output_options) + do_output_response = (cli.OUT_RESP_HEADERS in args.output_options + or cli.OUT_RESP_BODY in args.output_options) - if output_request: - stdout.write(format_http_message( + output = [] + if do_output_request: + output.append(format_http_message( message=make_request_message(response.request), prettifier=prettifier, - with_headers=cli.OUT_REQUEST_HEADERS in args.output_options, - with_body=cli.OUT_REQUEST_BODY in args.output_options + with_headers=cli.OUT_REQ_HEADERS in args.output_options, + with_body=cli.OUT_REQ_BODY in args.output_options )) - if output_response: - stdout.write(NEW_LINE) + if do_output_response: + output.append(NEW_LINE) - if output_response: - stdout.write(format_http_message( + if do_output_response: + output.append(format_http_message( message=make_response_message(response), prettifier=prettifier, - with_headers=cli.OUT_RESPONSE_HEADERS in args.output_options, - with_body=cli.OUT_RESPONSE_BODY in args.output_options + with_headers=cli.OUT_RESP_HEADERS in args.output_options, + with_body=cli.OUT_RESP_BODY in args.output_options )) - stdout.write(NEW_LINE) + output.append(NEW_LINE) + + output_bytes = ''.join(output).encode('utf8') + f = (stdout.buffer if is_py3 and hasattr(stdout, 'buffer') else stdout) + f.write(output_bytes) if __name__ == '__main__': diff --git a/httpie/cli.py b/httpie/cli.py index 29a55f6d88..98338dc67f 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -13,17 +13,19 @@ SEP_DATA = '=' SEP_DATA_RAW_JSON = ':=' SEP_FILES = '@' -PRETTIFY_STDOUT_TTY_ONLY = object() -OUT_REQUEST_HEADERS = 'H' -OUT_REQUEST_BODY = 'B' -OUT_RESPONSE_HEADERS = 'h' -OUT_RESPONSE_BODY = 'b' -OUTPUT_OPTIONS = [OUT_REQUEST_HEADERS, - OUT_REQUEST_BODY, - OUT_RESPONSE_HEADERS, - OUT_RESPONSE_BODY] +OUT_REQ_HEADERS = 'H' +OUT_REQ_BODY = 'B' +OUT_RESP_HEADERS = 'h' +OUT_RESP_BODY = 'b' +OUTPUT_OPTIONS = [OUT_REQ_HEADERS, + OUT_REQ_BODY, + OUT_RESP_HEADERS, + OUT_RESP_BODY] + + +PRETTIFY_STDOUT_TTY_ONLY = object() class ParseError(Exception): @@ -34,6 +36,7 @@ class ParseError(Exception): class KeyValueType(object): """A type used with `argparse`.""" + def __init__(self, *separators): self.separators = separators self.escapes = ['\\\\' + sep for sep in separators] @@ -56,7 +59,6 @@ def __call__(self, string): found[start] = sep if not found: - #noinspection PyExceptionInherit raise argparse.ArgumentTypeError( '"%s" is not a valid value' % string) @@ -160,7 +162,7 @@ def _validate_auth_options(self, args): ) -# output_options options. +# Output options. ############################################# parser.add_argument( @@ -189,7 +191,7 @@ def _validate_auth_options(self, args): output_options = parser.add_mutually_exclusive_group(required=False) output_options.add_argument('--print', '-p', dest='output_options', - default=OUT_RESPONSE_HEADERS + OUT_RESPONSE_BODY, + default=OUT_RESP_HEADERS + OUT_RESP_BODY, help=_(''' String specifying what should the output contain. "{request_headers}" stands for request headers and @@ -199,10 +201,10 @@ def _validate_auth_options(self, args): Defaults to "hb" which means that the whole response (headers and body) is printed. '''.format( - request_headers=OUT_REQUEST_HEADERS, - request_body=OUT_REQUEST_BODY, - response_headers=OUT_RESPONSE_HEADERS, - response_body=OUT_RESPONSE_BODY, + request_headers=OUT_REQ_HEADERS, + request_body=OUT_REQ_BODY, + response_headers=OUT_RESP_HEADERS, + response_body=OUT_RESP_BODY, )) ) output_options.add_argument( @@ -215,19 +217,19 @@ def _validate_auth_options(self, args): ) output_options.add_argument( '--headers', '-t', dest='output_options', - action='store_const', const=OUT_RESPONSE_HEADERS, + action='store_const', const=OUT_RESP_HEADERS, help=_(''' Print only the response headers. Shortcut for --print={0}. - '''.format(OUT_RESPONSE_HEADERS)) + '''.format(OUT_RESP_HEADERS)) ) output_options.add_argument( '--body', '-b', dest='output_options', - action='store_const', const=OUT_RESPONSE_BODY, + action='store_const', const=OUT_RESP_BODY, help=_(''' Print only the response body. Shortcut for --print={0}. - '''.format(OUT_RESPONSE_BODY)) + '''.format(OUT_RESP_BODY)) ) parser.add_argument( diff --git a/tests/tests.py b/tests/tests.py index ea77d6aee1..be39fb039d 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -3,7 +3,8 @@ import sys import unittest import argparse -from requests.compat import StringIO, is_py26, str +from requests.compat import is_py26 +import tempfile TESTS_ROOT = os.path.dirname(__file__) @@ -22,9 +23,12 @@ def http(*args, **kwargs): 'stdout_isatty': False } http_kwargs.update(kwargs) - stdout = http_kwargs.setdefault('stdout', StringIO()) + stdout = http_kwargs.setdefault('stdout', tempfile.TemporaryFile()) __main__.main(args=args, **http_kwargs) - return stdout.getvalue() + stdout.seek(0) + response = stdout.read().decode('utf8') + stdout.close() + return response class BaseTest(unittest.TestCase): @@ -83,7 +87,7 @@ def test_escape_longsep(self): self.assertDictEqual(data, { 'bob:=': 'foo', }) - + def test_valid_items(self): headers, data, files = cli.parse_items([ self.kv('string=value'), From c5b1aaaa28022bb4160b94b0a214e1b8e39059bd Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 25 Apr 2012 01:32:53 +0200 Subject: [PATCH 36/40] Major clean-up and refactoring. --- httpie/__main__.py | 202 +++++++++++++----------------------------- httpie/cli.py | 173 ++++++------------------------------ httpie/cliparse.py | 165 ++++++++++++++++++++++++++++++++++ httpie/httpmessage.py | 66 ++++++++++++++ tests/tests.py | 48 +++++----- 5 files changed, 344 insertions(+), 310 deletions(-) create mode 100644 httpie/cliparse.py create mode 100644 httpie/httpmessage.py diff --git a/httpie/__main__.py b/httpie/__main__.py index 3d27b2990b..5022a7bc1f 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -1,137 +1,41 @@ #!/usr/bin/env python import sys import json -try: - from collections import OrderedDict -except ImportError: - OrderedDict = dict import requests -from requests.compat import urlparse, str, is_py3 -from requests.structures import CaseInsensitiveDict +from requests.compat import str +from . import httpmessage +from . import cliparse from . import cli from . import pretty -from . import __version__ as version -NEW_LINE = str('\n') -DEFAULT_UA = 'HTTPie/%s' % version TYPE_FORM = 'application/x-www-form-urlencoded; charset=utf-8' TYPE_JSON = 'application/json; charset=utf-8' -class HTTPMessage(object): - - def __init__(self, line, headers, body, content_type=None): - # {Request,Status}-Line - self.line = line - self.headers = headers - self.body = body - self.content_type = content_type - - -def format_http_message(message, prettifier=None, - with_headers=True, with_body=True): - bits = [] - if with_headers: - if prettifier: - bits.append(prettifier.headers(message.line)) - bits.append(prettifier.headers(message.headers)) - else: - bits.append(message.line) - bits.append(message.headers) - if with_body and message.body: - bits.append(NEW_LINE) - if with_body and message.body: - if prettifier and message.content_type: - bits.append(prettifier.body(message.body, message.content_type)) - else: - bits.append(message.body) - bits.append(NEW_LINE) - return NEW_LINE.join(bit.strip() for bit in bits) - - -def make_request_message(request): - """Make an `HTTPMessage` from `requests.models.Request`.""" - url = urlparse(request.url) - request_headers = dict(request.headers) - if 'Host' not in request_headers: - request_headers['Host'] = url.netloc - return HTTPMessage( - line='{method} {path} HTTP/1.1'.format( - method=request.method, - path=url.path or '/'), - headers=NEW_LINE.join(str('%s: %s') % (name, value) - for name, value - in request_headers.items()), - body=request._enc_data, - content_type=request_headers.get('Content-Type') - ) - - -def make_response_message(response): - """Make an `HTTPMessage` from `requests.models.Response`.""" - encoding = response.encoding or 'ISO-8859-1' - original = response.raw._original_response - response_headers = response.headers - return HTTPMessage( - line='HTTP/{version} {status} {reason}'.format( - version='.'.join(str(original.version)), - status=original.status, reason=original.reason,), - headers=str(original.msg), - body=response.content.decode(encoding) if response.content else '', - content_type=response_headers.get('Content-Type')) - - -def main(args=None, - stdin=sys.stdin, - stdin_isatty=sys.stdin.isatty(), - stdout=sys.stdout, - stdout_isatty=sys.stdout.isatty()): - - parser = cli.parser - - args = parser.parse_args(args if args is not None else sys.argv[1:]) - do_prettify = (args.prettify is True or - (args.prettify == cli.PRETTIFY_STDOUT_TTY_ONLY - and stdout_isatty)) - - # Parse request headers and data from the command line. - headers = CaseInsensitiveDict() - headers['User-Agent'] = DEFAULT_UA - data = OrderedDict() - files = OrderedDict() - try: - cli.parse_items(items=args.items, headers=headers, - data=data, files=files) - except cli.ParseError as e: - if args.traceback: - raise - parser.error(e.message) - - if files and not args.form: - # We could just switch to --form automatically here, - # but I think it's better to make it explicit. - parser.error( - ' You need to set the --form / -f flag to' - ' to issue a multipart request. File fields: %s' - % ','.join(files.keys())) +def _get_response(parser, args, stdin, stdin_isatty): if not stdin_isatty: - if data: + if args.data: parser.error('Request body (stdin) and request ' 'data (key=value) cannot be mixed.') - data = stdin.read() - - # JSON/Form content type. - if args.json or (not args.form and data): - if args.method.lower() == 'get' and 'Accept' not in headers: - headers['Accept'] = 'application/json' + args.data = stdin.read() + + if args.json or (not args.form and args.data): + # JSON + if not args.files and ( + 'Content-Type' not in args.headers + and (args.data or args.json)): + args.headers['Content-Type'] = TYPE_JSON if stdin_isatty: - data = json.dumps(data) - if not files and ('Content-Type' not in headers and (data or args.json)): - headers['Content-Type'] = TYPE_JSON - elif not files and 'Content-Type' not in headers: - headers['Content-Type'] = TYPE_FORM + # Serialize the parsed data. + args.data = json.dumps(args.data) + if args.method.lower() == 'get' and 'Accept' not in args.headers: + # Default Accept to JSON as well. + args.headers['Accept'] = 'application/json' + elif not args.files and 'Content-Type' not in args.headers: + # Form + args.headers['Content-Type'] = TYPE_FORM # Fire the request. try: @@ -142,57 +46,75 @@ def main(args=None, else requests.auth.HTTPBasicAuth) credentials = auth_type(args.auth.key, args.auth.value) - response = requests.request( + return requests.request( method=args.method.lower(), url=args.url if '://' in args.url else 'http://%s' % args.url, - headers=headers, - data=data, + headers=args.headers, + data=args.data, verify={'yes': True, 'no': False}.get(args.verify, args.verify), timeout=args.timeout, auth=credentials, proxies=dict((p.key, p.value) for p in args.proxy), - files=files, + files=args.files, allow_redirects=args.allow_redirects, ) + except (KeyboardInterrupt, SystemExit): - sys.stderr.write(NEW_LINE) + sys.stderr.write('\n') sys.exit(1) except Exception as e: if args.traceback: raise - sys.stderr.write(str(e.message) + NEW_LINE) + sys.stderr.write(str(e.message) + '\n') sys.exit(1) - prettifier = pretty.PrettyHttp(args.style) if do_prettify else None - do_output_request = (cli.OUT_REQ_HEADERS in args.output_options - or cli.OUT_REQ_BODY in args.output_options) +def _get_output(args, stdout_isatty, response): + + do_prettify = (args.prettify is True or + (args.prettify == cliparse.PRETTIFY_STDOUT_TTY_ONLY + and stdout_isatty)) + + do_output_request = (cliparse.OUT_REQ_HEADERS in args.output_options + or cliparse.OUT_REQ_BODY in args.output_options) - do_output_response = (cli.OUT_RESP_HEADERS in args.output_options - or cli.OUT_RESP_BODY in args.output_options) + do_output_response = (cliparse.OUT_RESP_HEADERS in args.output_options + or cliparse.OUT_RESP_BODY in args.output_options) + prettifier = pretty.PrettyHttp(args.style) if do_prettify else None output = [] + if do_output_request: - output.append(format_http_message( - message=make_request_message(response.request), + output.append(httpmessage.format( + message=httpmessage.from_request(response.request), prettifier=prettifier, - with_headers=cli.OUT_REQ_HEADERS in args.output_options, - with_body=cli.OUT_REQ_BODY in args.output_options + with_headers=cliparse.OUT_REQ_HEADERS in args.output_options, + with_body=cliparse.OUT_REQ_BODY in args.output_options )) if do_output_response: - output.append(NEW_LINE) + output.append('\n') if do_output_response: - output.append(format_http_message( - message=make_response_message(response), + output.append(httpmessage.format( + message=httpmessage.from_response(response), prettifier=prettifier, - with_headers=cli.OUT_RESP_HEADERS in args.output_options, - with_body=cli.OUT_RESP_BODY in args.output_options + with_headers=cliparse.OUT_RESP_HEADERS in args.output_options, + with_body=cliparse.OUT_RESP_BODY in args.output_options )) - output.append(NEW_LINE) + output.append('\n') + + return ''.join(output) + - output_bytes = ''.join(output).encode('utf8') - f = (stdout.buffer if is_py3 and hasattr(stdout, 'buffer') else stdout) +def main(args=None, + stdin=sys.stdin, stdin_isatty=sys.stdin.isatty(), + stdout=sys.stdout, stdout_isatty=sys.stdout.isatty()): + parser = cli.parser + args = parser.parse_args(args if args is not None else sys.argv[1:]) + response = _get_response(parser, args, stdin, stdin_isatty) + output = _get_output(args, stdout_isatty, response) + output_bytes = output.encode('utf8') + f = (stdout.buffer if hasattr(stdout, 'buffer') else stdout) f.write(output_bytes) diff --git a/httpie/cli.py b/httpie/cli.py index 98338dc67f..57433ed5bd 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -1,118 +1,11 @@ -import os -import json -import argparse -import re -from collections import namedtuple +""" +CLI definition. + +""" from . import pretty from . import __doc__ as doc from . import __version__ as version - - -SEP_COMMON = ':' -SEP_HEADERS = SEP_COMMON -SEP_DATA = '=' -SEP_DATA_RAW_JSON = ':=' -SEP_FILES = '@' - - -OUT_REQ_HEADERS = 'H' -OUT_REQ_BODY = 'B' -OUT_RESP_HEADERS = 'h' -OUT_RESP_BODY = 'b' -OUTPUT_OPTIONS = [OUT_REQ_HEADERS, - OUT_REQ_BODY, - OUT_RESP_HEADERS, - OUT_RESP_BODY] - - -PRETTIFY_STDOUT_TTY_ONLY = object() - - -class ParseError(Exception): - pass - - -KeyValue = namedtuple('KeyValue', ['key', 'value', 'sep', 'orig']) - -class KeyValueType(object): - """A type used with `argparse`.""" - - def __init__(self, *separators): - self.separators = separators - self.escapes = ['\\\\' + sep for sep in separators] - - def __call__(self, string): - found = {} - found_escapes = [] - for esc in self.escapes: - found_escapes += [m.span() for m in re.finditer(esc, string)] - for sep in self.separators: - matches = re.finditer(sep, string) - for match in matches: - start, end = match.span() - inside_escape = False - for estart, eend in found_escapes: - if start >= estart and end <= eend: - inside_escape = True - break - if not inside_escape: - found[start] = sep - - if not found: - raise argparse.ArgumentTypeError( - '"%s" is not a valid value' % string) - - # split the string at the earliest non-escaped separator. - seploc = min(found.keys()) - sep = found[seploc] - key = string[:seploc] - value = string[seploc + len(sep):] - - # remove escape chars - for sepstr in self.separators: - key = key.replace('\\' + sepstr, sepstr) - value = value.replace('\\' + sepstr, sepstr) - return KeyValue(key=key, value=value, sep=sep, orig=string) - - -def parse_items(items, data=None, headers=None, files=None): - """Parse `KeyValueType` `items` into `data`, `headers` and `files`.""" - if headers is None: - headers = {} - if data is None: - data = {} - if files is None: - files = {} - for item in items: - value = item.value - key = item.key - if item.sep == SEP_HEADERS: - target = headers - elif item.sep == SEP_FILES: - try: - value = open(os.path.expanduser(item.value), 'r') - except IOError as e: - raise ParseError( - 'Invalid argument %r. %s' % (item.orig, e)) - if not key: - key = os.path.basename(value.name) - target = files - elif item.sep in [SEP_DATA, SEP_DATA_RAW_JSON]: - if item.sep == SEP_DATA_RAW_JSON: - try: - value = json.loads(item.value) - except ValueError: - raise ParseError('%s is not valid JSON' % item.orig) - target = data - else: - raise ParseError('%s is not valid item' % item.orig) - - if key in target: - ParseError('duplicate item %s (%s)' % (item.key, item.orig)) - - target[key] = value - - return headers, data, files +from . import cliparse def _(text): @@ -120,27 +13,10 @@ def _(text): return ' '.join(text.strip().split()) -class HTTPieArgumentParser(argparse.ArgumentParser): - def parse_args(self, args=None, namespace=None): - args = super(HTTPieArgumentParser, self).parse_args(args, namespace) - self._validate_output_options(args) - self._validate_auth_options(args) - return args - - def _validate_output_options(self, args): - unknown_output_options = set(args.output_options) - set(OUTPUT_OPTIONS) - if unknown_output_options: - self.error('Unknown output options: %s' % ','.join(unknown_output_options)) - - def _validate_auth_options(self, args): - if args.auth_type and not args.auth: - self.error('--auth-type can only be used with --auth') - - - -parser = HTTPieArgumentParser(description=doc.strip(),) +parser = cliparse.HTTPieArgumentParser(description=doc.strip(),) parser.add_argument('--version', action='version', version=version) + # Content type. ############################################# @@ -175,7 +51,7 @@ def _validate_auth_options(self, args): prettify = parser.add_mutually_exclusive_group(required=False) prettify.add_argument( '--pretty', dest='prettify', action='store_true', - default=PRETTIFY_STDOUT_TTY_ONLY, + default=cliparse.PRETTIFY_STDOUT_TTY_ONLY, help=_(''' If stdout is a terminal, the response is prettified by default (colorized and indented if it is JSON). @@ -191,7 +67,7 @@ def _validate_auth_options(self, args): output_options = parser.add_mutually_exclusive_group(required=False) output_options.add_argument('--print', '-p', dest='output_options', - default=OUT_RESP_HEADERS + OUT_RESP_BODY, + default=cliparse.OUT_RESP_HEADERS + cliparse.OUT_RESP_BODY, help=_(''' String specifying what should the output contain. "{request_headers}" stands for request headers and @@ -201,35 +77,35 @@ def _validate_auth_options(self, args): Defaults to "hb" which means that the whole response (headers and body) is printed. '''.format( - request_headers=OUT_REQ_HEADERS, - request_body=OUT_REQ_BODY, - response_headers=OUT_RESP_HEADERS, - response_body=OUT_RESP_BODY, + request_headers=cliparse.OUT_REQ_HEADERS, + request_body=cliparse.OUT_REQ_BODY, + response_headers=cliparse.OUT_RESP_HEADERS, + response_body=cliparse.OUT_RESP_BODY, )) ) output_options.add_argument( '--verbose', '-v', dest='output_options', - action='store_const', const=''.join(OUTPUT_OPTIONS), + action='store_const', const=''.join(cliparse.OUTPUT_OPTIONS), help=_(''' Print the whole request as well as response. Shortcut for --print={0}. - '''.format(''.join(OUTPUT_OPTIONS))) + '''.format(''.join(cliparse.OUTPUT_OPTIONS))) ) output_options.add_argument( '--headers', '-t', dest='output_options', - action='store_const', const=OUT_RESP_HEADERS, + action='store_const', const=cliparse.OUT_RESP_HEADERS, help=_(''' Print only the response headers. Shortcut for --print={0}. - '''.format(OUT_RESP_HEADERS)) + '''.format(cliparse.OUT_RESP_HEADERS)) ) output_options.add_argument( '--body', '-b', dest='output_options', - action='store_const', const=OUT_RESP_BODY, + action='store_const', const=cliparse.OUT_RESP_BODY, help=_(''' Print only the response body. Shortcut for --print={0}. - '''.format(OUT_RESP_BODY)) + '''.format(cliparse.OUT_RESP_BODY)) ) parser.add_argument( @@ -243,7 +119,7 @@ def _validate_auth_options(self, args): # ``requests.request`` keyword arguments. parser.add_argument( '--auth', '-a', help='username:password', - type=KeyValueType(SEP_COMMON) + type=cliparse.KeyValueType(cliparse.SEP_COMMON) ) parser.add_argument( @@ -263,7 +139,7 @@ def _validate_auth_options(self, args): ) parser.add_argument( '--proxy', default=[], action='append', - type=KeyValueType(SEP_COMMON), + type=cliparse.KeyValueType(cliparse.SEP_COMMON), help=_(''' String mapping protocol to the URL of the proxy (e.g. http:foo.bar:3128). @@ -304,7 +180,12 @@ def _validate_auth_options(self, args): ) parser.add_argument( 'items', nargs='*', - type=KeyValueType(SEP_COMMON, SEP_DATA, SEP_DATA_RAW_JSON, SEP_FILES), + type=cliparse.KeyValueType( + cliparse.SEP_COMMON, + cliparse.SEP_DATA, + cliparse.SEP_DATA_RAW_JSON, + cliparse.SEP_FILES + ), help=_(''' HTTP header (header:value), data field (field=value), raw JSON field (field:=value) diff --git a/httpie/cliparse.py b/httpie/cliparse.py new file mode 100644 index 0000000000..8664edb4c8 --- /dev/null +++ b/httpie/cliparse.py @@ -0,0 +1,165 @@ +""" +CLI argument parsing logic. + +""" +import os +import json +import re +from collections import namedtuple +try: + from collections import OrderedDict +except ImportError: + OrderedDict = dict +import argparse +from requests.structures import CaseInsensitiveDict +from . import __version__ + + +SEP_COMMON = ':' +SEP_HEADERS = SEP_COMMON +SEP_DATA = '=' +SEP_DATA_RAW_JSON = ':=' +SEP_FILES = '@' + + +OUT_REQ_HEADERS = 'H' +OUT_REQ_BODY = 'B' +OUT_RESP_HEADERS = 'h' +OUT_RESP_BODY = 'b' +OUTPUT_OPTIONS = [OUT_REQ_HEADERS, + OUT_REQ_BODY, + OUT_RESP_HEADERS, + OUT_RESP_BODY] + + +PRETTIFY_STDOUT_TTY_ONLY = object() + +DEFAULT_UA = 'HTTPie/%s' % __version__ + + +class HTTPieArgumentParser(argparse.ArgumentParser): + + def parse_args(self, args=None, namespace=None): + args = super(HTTPieArgumentParser, self).parse_args(args, namespace) + self._validate_output_options(args) + self._validate_auth_options(args) + self._parse_items(args) + return args + + def _parse_items(self, args): + args.headers = CaseInsensitiveDict() + args.headers['User-Agent'] = DEFAULT_UA + args.data = OrderedDict() + args.files = OrderedDict() + try: + parse_items(items=args.items, headers=args.headers, + data=args.data, files=args.files) + except ParseError as e: + if args.traceback: + raise + self.error(e.message) + + if args.files and not args.form: + # We could just switch to --form automatically here, + # but I think it's better to make it explicit. + self.error( + ' You need to set the --form / -f flag to' + ' to issue a multipart request. File fields: %s' + % ','.join(args.files.keys())) + + def _validate_output_options(self, args): + unknown_output_options = set(args.output_options) - set(OUTPUT_OPTIONS) + if unknown_output_options: + self.error('Unknown output options: %s' % ','.join(unknown_output_options)) + + def _validate_auth_options(self, args): + if args.auth_type and not args.auth: + self.error('--auth-type can only be used with --auth') + + +class ParseError(Exception): + pass + + +KeyValue = namedtuple('KeyValue', ['key', 'value', 'sep', 'orig']) + + +class KeyValueType(object): + """A type used with `argparse`.""" + + def __init__(self, *separators): + self.separators = separators + self.escapes = ['\\\\' + sep for sep in separators] + + def __call__(self, string): + found = {} + found_escapes = [] + for esc in self.escapes: + found_escapes += [m.span() for m in re.finditer(esc, string)] + for sep in self.separators: + matches = re.finditer(sep, string) + for match in matches: + start, end = match.span() + inside_escape = False + for estart, eend in found_escapes: + if start >= estart and end <= eend: + inside_escape = True + break + if not inside_escape: + found[start] = sep + + if not found: + raise argparse.ArgumentTypeError( + '"%s" is not a valid value' % string) + + # split the string at the earliest non-escaped separator. + seploc = min(found.keys()) + sep = found[seploc] + key = string[:seploc] + value = string[seploc + len(sep):] + + # remove escape chars + for sepstr in self.separators: + key = key.replace('\\' + sepstr, sepstr) + value = value.replace('\\' + sepstr, sepstr) + return KeyValue(key=key, value=value, sep=sep, orig=string) + + +def parse_items(items, data=None, headers=None, files=None): + """Parse `KeyValueType` `items` into `data`, `headers` and `files`.""" + if headers is None: + headers = {} + if data is None: + data = {} + if files is None: + files = {} + for item in items: + value = item.value + key = item.key + if item.sep == SEP_HEADERS: + target = headers + elif item.sep == SEP_FILES: + try: + value = open(os.path.expanduser(item.value), 'r') + except IOError as e: + raise ParseError( + 'Invalid argument %r. %s' % (item.orig, e)) + if not key: + key = os.path.basename(value.name) + target = files + elif item.sep in [SEP_DATA, SEP_DATA_RAW_JSON]: + if item.sep == SEP_DATA_RAW_JSON: + try: + value = json.loads(item.value) + except ValueError: + raise ParseError('%s is not valid JSON' % item.orig) + target = data + else: + raise ParseError('%s is not valid item' % item.orig) + + if key in target: + ParseError('duplicate item %s (%s)' % (item.key, item.orig)) + + target[key] = value + + return headers, data, files diff --git a/httpie/httpmessage.py b/httpie/httpmessage.py new file mode 100644 index 0000000000..e96dd69175 --- /dev/null +++ b/httpie/httpmessage.py @@ -0,0 +1,66 @@ +from requests.compat import urlparse + + +class HTTPMessage(object): + """Model representing an HTTP message.""" + + def __init__(self, line, headers, body, content_type=None): + # {Request,Status}-Line + self.line = line + self.headers = headers + self.body = body + self.content_type = content_type + + +def from_request(request): + """Make an `HTTPMessage` from `requests.models.Request`.""" + url = urlparse(request.url) + request_headers = dict(request.headers) + if 'Host' not in request_headers: + request_headers['Host'] = url.netloc + return HTTPMessage( + line='{method} {path} HTTP/1.1'.format( + method=request.method, + path=url.path or '/'), + headers='\n'.join(str('%s: %s') % (name, value) + for name, value + in request_headers.items()), + body=request._enc_data, + content_type=request_headers.get('Content-Type') + ) + + +def from_response(response): + """Make an `HTTPMessage` from `requests.models.Response`.""" + encoding = response.encoding or 'ISO-8859-1' + original = response.raw._original_response + response_headers = response.headers + return HTTPMessage( + line='HTTP/{version} {status} {reason}'.format( + version='.'.join(str(original.version)), + status=original.status, reason=original.reason,), + headers=str(original.msg), + body=response.content.decode(encoding) if response.content else '', + content_type=response_headers.get('Content-Type')) + + +def format(message, prettifier=None, + with_headers=True, with_body=True): + """Return a `unicode` representation of `message`. """ + bits = [] + if with_headers: + if prettifier: + bits.append(prettifier.headers(message.line)) + bits.append(prettifier.headers(message.headers)) + else: + bits.append(message.line) + bits.append(message.headers) + if with_body and message.body: + bits.append('\n') + if with_body and message.body: + if prettifier and message.content_type: + bits.append(prettifier.body(message.body, message.content_type)) + else: + bits.append(message.body) + bits.append('\n') + return '\n'.join(bit.strip() for bit in bits) diff --git a/tests/tests.py b/tests/tests.py index be39fb039d..9ff5eea093 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -10,7 +10,7 @@ TESTS_ROOT = os.path.dirname(__file__) sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) from httpie import __main__ -from httpie import cli +from httpie import cliparse TEST_FILE = os.path.join(TESTS_ROOT, 'file.txt') @@ -48,28 +48,28 @@ def assertDictEqual(self, d1, d2, msg=None): class TestItemParsing(BaseTest): def setUp(self): - self.kv = cli.KeyValueType( - cli.SEP_HEADERS, - cli.SEP_DATA, - cli.SEP_DATA_RAW_JSON, - cli.SEP_FILES, + self.key_value_type = cliparse.KeyValueType( + cliparse.SEP_HEADERS, + cliparse.SEP_DATA, + cliparse.SEP_DATA_RAW_JSON, + cliparse.SEP_FILES, ) def test_invalid_items(self): items = ['no-separator'] for item in items: self.assertRaises(argparse.ArgumentTypeError, - lambda: self.kv(item)) + lambda: self.key_value_type(item)) def test_escape(self): - headers, data, files = cli.parse_items([ + headers, data, files = cliparse.parse_items([ # headers - self.kv('foo\\:bar:baz'), - self.kv('jack\\@jill:hill'), + self.key_value_type('foo\\:bar:baz'), + self.key_value_type('jack\\@jill:hill'), # data - self.kv('baz\\=bar=foo'), + self.key_value_type('baz\\=bar=foo'), # files - self.kv('bar\\@baz@%s' % TEST_FILE) + self.key_value_type('bar\\@baz@%s' % TEST_FILE) ]) self.assertDictEqual(headers, { 'foo:bar': 'baz', @@ -81,23 +81,23 @@ def test_escape(self): self.assertIn('bar@baz', files) def test_escape_longsep(self): - headers, data, files = cli.parse_items([ - self.kv('bob\\:==foo'), + headers, data, files = cliparse.parse_items([ + self.key_value_type('bob\\:==foo'), ]) self.assertDictEqual(data, { 'bob:=': 'foo', }) def test_valid_items(self): - headers, data, files = cli.parse_items([ - self.kv('string=value'), - self.kv('header:value'), - self.kv('list:=["a", 1, {}, false]'), - self.kv('obj:={"a": "b"}'), - self.kv('eh:'), - self.kv('ed='), - self.kv('bool:=true'), - self.kv('test-file@%s' % TEST_FILE), + headers, data, files = cliparse.parse_items([ + self.key_value_type('string=value'), + self.key_value_type('header:value'), + self.key_value_type('list:=["a", 1, {}, false]'), + self.key_value_type('obj:={"a": "b"}'), + self.key_value_type('eh:'), + self.key_value_type('ed='), + self.key_value_type('bool:=true'), + self.key_value_type('test-file@%s' % TEST_FILE), ]) self.assertDictEqual(headers, { 'header': 'value', @@ -163,7 +163,7 @@ def test_force_ugly(self): class TestFileUpload(BaseTest): def test_non_existent_file_raises_parse_error(self): - self.assertRaises(cli.ParseError, http, + self.assertRaises(cliparse.ParseError, http, '--form', '--traceback', 'POST', 'http://httpbin.org/post', 'foo@/__does_not_exist__') From 79102699961960026b56229c7a66ba0f0acdcd15 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 25 Apr 2012 02:10:58 +0200 Subject: [PATCH 37/40] Updated README and docs. --- README.rst | 73 ++++++++++++++++++++++++++++++---------------- httpie/__main__.py | 2 +- httpie/cli.py | 49 ++++++++++++++++++------------- 3 files changed, 78 insertions(+), 46 deletions(-) diff --git a/README.rst b/README.rst index 9c2ae2c64c..0cb0ebeecf 100644 --- a/README.rst +++ b/README.rst @@ -106,31 +106,36 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` usage: http [-h] [--version] [--json | --form] [--traceback] [--pretty | --ugly] [--print OUTPUT_OPTIONS | --verbose | --headers | --body] - [--style STYLE] [--auth AUTH] [--verify VERIFY] - [--proxy PROXY] [--allow-redirects] [--timeout TIMEOUT] - METHOD URL [items [items ...]] + [--style STYLE] [--auth AUTH] [--auth-type {basic,digest}] + [--verify VERIFY] [--proxy PROXY] [--allow-redirects] + [--timeout TIMEOUT] + METHOD URL [ITEM [ITEM ...]] - HTTPie - cURL for humans. + HTTPie - cURL for humans. positional arguments: - METHOD HTTP method to be used for the request (GET, POST, + METHOD The HTTP method to be used for the request (GET, POST, PUT, DELETE, PATCH, ...). - URL Protocol defaults to http:// if the URL does not - include it. - items HTTP header (header:value), data field (field=value), - raw JSON field (field:=value) or file field - (field@/path/to/file). + URL The protocol defaults to http:// if the URL does not + include one. + ITEM A key-value pair whose type is defined by the + separator used. It can be an HTTP header + (header:value), a data field to be used in the request + body (field_name=value), a raw JSON data field + (field_name:=value) or a file field + (field_name@/path/to/file). You can use a backslash to + escape a colliding separator in the field name. optional arguments: -h, --help show this help message and exit --version show program's version number and exit - --json, -j Serialize data items as a JSON object and set Content- - Type to application/json, if not specified. - --form, -f Serialize fields as form values. The Content-Type is - set to application/x-www-form-urlencoded. The presence - of any file fields results into a multipart/form-data - request. Note that Content-Type is not automatically - set if explicitely specified. + --json, -j (default) Data items are serialized as a JSON object. + The Content-Type and Accept headers are set to + application/json (if not set via the command line). + --form, -f Data items are serialized as form fields. The Content- + Type is set to application/x-www-form-urlencoded (if + not specifid). The presence of any file fields results + into a multipart/form-data request. --traceback Print exception traceback should one occur. --pretty If stdout is a terminal, the response is prettified by default (colorized and indented if it is JSON). This @@ -139,12 +144,12 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` --ugly, -u Do not prettify the response. --print OUTPUT_OPTIONS, -p OUTPUT_OPTIONS String specifying what should the output contain. "H" - stands for request headers and "B" for request body. - "h" stands for response headers and "b" for response - body. Defaults to "hb" which means that the whole - response (headers and body) is printed. - --verbose, -v Print the whole request as well as response. Shortcut - for --print=HBhb. + stands for the request headers and "B" for the request + body. "h" stands for the response headers and "b" for + response the body. Defaults to "hb" which means that + the whole response (headers and body) is printed. + --verbose, -v Print the whole request as well as the response. + Shortcut for --print=HBhb. --headers, -t Print only the response headers. Shortcut for --print=h. --body, -b Print only the response body. Shortcut for --print=b. @@ -152,8 +157,15 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` Output coloring style, one of autumn, borland, bw, colorful, default, emacs, friendly, fruity, manni, monokai, murphy, native, pastie, perldoc, solarized, - tango, trac, vim, vs. Defaults to solarized. + tango, trac, vim, vs. Defaults to solarized. For this + option to work properly, please make sure that the + $TERM environment variable is set to "xterm-256color" + or similar (e.g., via `export TERM=xterm-256color' in + your ~/.bashrc). --auth AUTH, -a AUTH username:password + --auth-type {basic,digest} + The authentication mechanism to be used. Defaults to + "basic". --verify VERIFY Set to "no" to skip checking the host's SSL certificate. You can also pass the path to a CA_BUNDLE file for private certs. You can also set the @@ -166,6 +178,7 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` --timeout TIMEOUT Float describes the timeout of the request (Use socket.setdefaulttimeout() as fallback). + Contributors ------------ @@ -175,5 +188,15 @@ Contributors Changelog --------- -* `New in development version `_ +* `New in development version `_ +* 0.2.0 (2012-04-25) + * Added Python 3 support. + * Added the ability to print the HTTP request as well (see --print and --verbose). + * Added support for Digest authentication. + * Added file upload support (http -f POST file_field_name@/path/to/file). + * Improved syntax highlighting for JSON. + * Added support for field name escaping. + * Many bug fixes. + * `Complete changelog `_ + * `0.1.6 `_ (2012-03-04) diff --git a/httpie/__main__.py b/httpie/__main__.py index 5022a7bc1f..faa4045e04 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -30,7 +30,7 @@ def _get_response(parser, args, stdin, stdin_isatty): if stdin_isatty: # Serialize the parsed data. args.data = json.dumps(args.data) - if args.method.lower() == 'get' and 'Accept' not in args.headers: + if 'Accept' not in args.headers: # Default Accept to JSON as well. args.headers['Accept'] = 'application/json' elif not args.files and 'Content-Type' not in args.headers: diff --git a/httpie/cli.py b/httpie/cli.py index 57433ed5bd..62ca44c2ee 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -3,8 +3,8 @@ """ from . import pretty -from . import __doc__ as doc -from . import __version__ as version +from . import __doc__ +from . import __version__ from . import cliparse @@ -13,8 +13,9 @@ def _(text): return ' '.join(text.strip().split()) -parser = cliparse.HTTPieArgumentParser(description=doc.strip(),) -parser.add_argument('--version', action='version', version=version) +desc = '%s ' +parser = cliparse.HTTPieArgumentParser(description=desc % __doc__.strip(),) +parser.add_argument('--version', action='version', version=__version__) # Content type. @@ -24,16 +25,17 @@ def _(text): group_type.add_argument( '--json', '-j', action='store_true', help=_(''' - Serialize data items as a JSON object and set - Content-Type to application/json, if not specified. + (default) Data items are serialized as a JSON object. + The Content-Type and Accept headers + are set to application/json (if not set via the command line). ''') ) group_type.add_argument( '--form', '-f', action='store_true', help=_(''' - Serialize fields as form values. The Content-Type is set to application/x-www-form-urlencoded. + Data items are serialized as form fields. + The Content-Type is set to application/x-www-form-urlencoded (if not specifid). The presence of any file fields results into a multipart/form-data request. - Note that Content-Type is not automatically set if explicitely specified. ''') ) @@ -70,10 +72,10 @@ def _(text): default=cliparse.OUT_RESP_HEADERS + cliparse.OUT_RESP_BODY, help=_(''' String specifying what should the output contain. - "{request_headers}" stands for request headers and - "{request_body}" for request body. - "{response_headers}" stands for response headers and - "{response_body}" for response body. + "{request_headers}" stands for the request headers and + "{request_body}" for the request body. + "{response_headers}" stands for the response headers and + "{response_body}" for response the body. Defaults to "hb" which means that the whole response (headers and body) is printed. '''.format( @@ -87,7 +89,7 @@ def _(text): '--verbose', '-v', dest='output_options', action='store_const', const=''.join(cliparse.OUTPUT_OPTIONS), help=_(''' - Print the whole request as well as response. + Print the whole request as well as the response. Shortcut for --print={0}. '''.format(''.join(cliparse.OUTPUT_OPTIONS))) ) @@ -113,6 +115,9 @@ def _(text): choices=pretty.AVAILABLE_STYLES, help=_(''' Output coloring style, one of %s. Defaults to solarized. + For this option to work properly, please make sure that the + $TERM environment variable is set to "xterm-256color" or similar + (e.g., via `export TERM=xterm-256color' in your ~/.bashrc). ''') % ', '.join(sorted(pretty.AVAILABLE_STYLES)) ) @@ -124,7 +129,7 @@ def _(text): parser.add_argument( '--auth-type', choices=['basic', 'digest'], - help=_('The type of authentication ("basic" or "digest"). Defaults to "basic".') + help=_('The authentication mechanism to be used. Defaults to "basic".') ) parser.add_argument( @@ -167,19 +172,20 @@ def _(text): parser.add_argument( 'method', metavar='METHOD', help=_(''' - HTTP method to be used for the request + The HTTP method to be used for the request (GET, POST, PUT, DELETE, PATCH, ...). ''') ) parser.add_argument( 'url', metavar='URL', help=_(''' - Protocol defaults to http:// if the - URL does not include it. + The protocol defaults to http:// if the + URL does not include one. ''') ) parser.add_argument( 'items', nargs='*', + metavar='ITEM', type=cliparse.KeyValueType( cliparse.SEP_COMMON, cliparse.SEP_DATA, @@ -187,8 +193,11 @@ def _(text): cliparse.SEP_FILES ), help=_(''' - HTTP header (header:value), data field (field=value), - raw JSON field (field:=value) - or file field (field@/path/to/file). + A key-value pair whose type is defined by the separator used. It can be an + HTTP header (header:value), + a data field to be used in the request body (field_name=value), + a raw JSON data field (field_name:=value) + or a file field (field_name@/path/to/file). + You can use a backslash to escape a colliding separator in the field name. ''') ) From 3a96706e185c4cf99b4919ac7a7601918ceec7b4 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 25 Apr 2012 02:11:19 +0200 Subject: [PATCH 38/40] 0.2.0 --- httpie/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpie/__init__.py b/httpie/__init__.py index 861218351d..27ce11f2d4 100644 --- a/httpie/__init__.py +++ b/httpie/__init__.py @@ -3,5 +3,5 @@ """ __author__ = 'Jakub Roztocil' -__version__ = '0.1.7-dev' +__version__ = '0.2.0' __licence__ = 'BSD' From b8cc7c205c9233fbe50a8c6f5295a96160f13759 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 25 Apr 2012 02:13:39 +0200 Subject: [PATCH 39/40] Updated README. --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 0cb0ebeecf..452e0b9d11 100644 --- a/README.rst +++ b/README.rst @@ -191,9 +191,9 @@ Changelog * `New in development version `_ * 0.2.0 (2012-04-25) * Added Python 3 support. - * Added the ability to print the HTTP request as well (see --print and --verbose). + * Added the ability to print the HTTP request as well as the response (see ``--print`` and ``--verbose``). * Added support for Digest authentication. - * Added file upload support (http -f POST file_field_name@/path/to/file). + * Added file upload support (``http -f POST file_field_name@/path/to/file``). * Improved syntax highlighting for JSON. * Added support for field name escaping. * Many bug fixes. From 3d11042772fe7f75008e53dc48c537fc4bbd0b1a Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Wed, 25 Apr 2012 02:16:10 +0200 Subject: [PATCH 40/40] Fixed classifiers in setup.py. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9401a0ff92..4628f54c08 100644 --- a/setup.py +++ b/setup.py @@ -37,8 +37,8 @@ 'Programming Language :: Python', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.1' - 'Programming Language :: Python :: 3.2' + 'Programming Language :: Python :: 3.1', + 'Programming Language :: Python :: 3.2', 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators',