From 142348aa59d833b3c26ca8754d13e23e4dadc1c8 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Fri, 23 Feb 2024 23:22:56 +0300 Subject: [PATCH 01/14] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c9817c0..99788a4 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ print(suby('python', '-c', 'import time; time.sleep(10_000)', token=token, catch ## Timeouts -You can set a timeout for `suby`. It must be an integer greater than zero, which indicates the number of seconds that the sub process can continue to run. If the timeout expires before the subprocess completes, an exception will be raised: +You can set a timeout for `suby`. It must be an integer greater than zero, which indicates the number of seconds that the subprocess can continue to run. If the timeout expires before the subprocess completes, an exception will be raised: ```python import suby From 01df7a9cb0ec17bc6f4b87892b57e78c39960139 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Sat, 24 Feb 2024 00:56:58 +0300 Subject: [PATCH 02/14] logos --- docs/assets/logo_6.png | Bin 0 -> 13811 bytes docs/assets/logo_7.png | Bin 0 -> 14945 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/assets/logo_6.png create mode 100644 docs/assets/logo_7.png diff --git a/docs/assets/logo_6.png b/docs/assets/logo_6.png new file mode 100644 index 0000000000000000000000000000000000000000..48dd61631ea358738c9f31b3255e4a845300eef5 GIT binary patch literal 13811 zcmdUWgwIxrqaNy`{r(j}myM#soeN;lHdk2*RBY;=rnL`q_yf^>|M2Bkwl z1_SAL{NDGUc*kdKJ3Hs>y07@2?{%GXN9ky(JS3whyLIc-y#|4_lIa>y}uls^Uxix3jz1fHX#f=8x1iw4^pFq*T@9%Ol?( zDv~02qsgPqsA}r@$V-=k#Sj(^ua_M zVO6`93a95MGO~B>YV;0nRd1K?odo9uNT+MGR8(k9`tM}z2QBeh{6m!H|E~w&71aLG z6Z(F}FUT9g|C|03ykQ>lGxjfLj*ev8{rihcz6T2ljtliND)(+WG{J~DdyW~ykN2U$z*h7bk6hPLB-m~9lr7&CIx z_jDnYgl$+b26LVcdA*H+?-+TK-01Dqw+E-&r3cW`w)L3yac<$3{LKp6ke>o*SMVvyt~fpLM>9omhPu3X@g2s92Ocy>~Fj_ubbkawHhddX$11@ zdvvs&zwI+W<4ErhrMACu{k-t|?*}82!5Dl%1dDW2 zG-A;Pk5U6(I1S{sZ+Us z*|yt0QkibItL&^_rgz`C0Q8wK`!y1tsFVCiE#&GF^3#l~wwe|iwB`TZYW?U%=CmH+ z$Gdl-zqK;BZlpjwxtEJ{Qx5!kEhIQu#}Op6be zo_e;h@e_yK%2SK{vjBe#4-0#LhG^?i`S3+b*?Hq52E#23m)>pozh+hZuZ$o7OjUtQ za;`4PbL@L0wM|8JCVf*w98F`M9$r~_%>IHmF-l679^25f+{glnJX&~%aI=6!6m^yH z{S4@+$y~HITsoHyw5i=>lB>jin5xPB)CAqC&}`v_QxJ!IArb2PiNqbKmvW21Cl-I< znIoue3BefLUlzE02(C0me80teYn3VOf9jkjgE#Hj6jB2CRUjhn%*;8SAEBEJ5#bX% zw(M6SA3ns@i0C;%n4j>I5~rSi01EMA!=O;OQR)+?5ucr$X=`uf_`G?2yO&C`hUJdx z9B%tY>OJo8ZBekO6F}^sAYrePFvg@I&6WO1MUkkmymq1YV9%*AL^mg&sP$0uPtRi za_EGn{`;SF67F{f**r7RaCP_>}5!`*S*!v%V>cRa5_IN zlI;My`=K^Qa2n$1FNXgD&ea)#v$Ul>5}X)*49o#A@y2=6&E?@l_!g#hPjzYQt@s-| z0m1T)lX%G{nmZ@UDbP)~O2myDKe^W#vcBWNuaU7=@wG~|^dji;=!?08tp1(xI}LUL zKPz)|y$$84OG{|)E>i9ahbwkY2pY5(?vy-yZVmBLIGn}z`GD1Bmvpn78W|=KD z8eB2)gQ=y&FKjO~!EKvztXNyr)MD>+WP~Qgj?8;}FG{`#bCxveaevat*}qted9cI5 z%WRO30;_TR-%)AaoadN5Sy1W+UDZ-LCX~Ej8q?=Po6I@!{Mj752yBCTVs}@#e_ZDI z?(b)VIeJon?1Qt@Lk8$~66)_7WgG0rCW?Q`-WGW=nr;e66ciW3c1F|hBzw=d+_tyL zUs74!40SGA=sh{$Ji9z>Kio|_c9ryS^&c=@ntt$gsnr%!i40^bKlCB&6F?(NO;;Ae z3dRMu1IpJFe47BT^LtcpF|Zfwg6rAhZ3yJbgFOB+fNZ)JUQQ4Oe(59^NM@QSZ-v~*h2*T*V3V`>cQTgB zDIxC1*jbU=P%a?-LF3Enk)A=Jft|sBCMA2;>63%gocX6(4tyHCM}AKYwf3KEe`@jT z`^|;bdjD+sNd%&rY@u&5MaSPYsiXBq48P*xM+-gnv<97K@`n*h?+!c7rvHY$tdjdE z2AB-!7pSK%O$-XrcZ+rv!>QJ6k!8ytlcXo;D?pJtV9{>=6xZ_f?S$5<7zDHHdEP8j z`JB_%qN8#-zsgG%%!cX{km*JjE9N_{Ssm>8Ocf|yxB2|oW>ZdBM(6PWbW1@yeEX^d z;7j+!@z#N{BG$l1UUh3%SL1xoE5nX+4kufCnD24~Jh+?8ykwF3piecb!uR6&QaX!@ zMrjpdm@NC=9Av-U1k=*Q@4cTz6nO30LeMckL{6PX$~Go$f3P~YjkfBp%d=WrPqsG2 z#ymTjby{~3F#3p>sB!qXX(>8AOxuG|yDm~qu5QZHGS_k3b*`wn%6Z{q)$VU3->c`j z7F-x;J5GfNjE?t{VO*Fd=*(zE#%&*6@i!r?bJ}%d@BA@-PBFd-Zb_4<=qI|<@D0}2 zOi^ZUs4jnmAwU?PPqI`!?^DOr{0D+l9DlPEHdhT;)snlgL^k9oN`Ef|0hUH$6d>#` zud+eO9~_f(0HmJ{yAF*q)k--X^FDbBHN}3W6+hpW!3TsS=boym{|x@DRN*(6XcqGj z-=#e8UQdOu0Q@P@-kgbyi>S~?Qzn6yK$Wu!y?D#kwB9&u=i*mKmklXdpU~4scW9Pm zHjlB_g`8^7I%j1h9|2HPGC530?o&iJqFo=dCgKJ>ZLu&TeSGcQbO^B>* zSPq2`bK_4={5?mtO%A~KHn~NOF{$*8&{@%^0Ovrw$i*9hUs-a$h65+IR zm1pRYOpl$<%G{8{R*-D2SwRC|p4~gG%YM!qXQ@D-X*PXmvzion@(Uh+_8rFyzep+; z&q=*lM91{Z2KG55KhlsrmIT*7h0TM~c8Dx!FMB9STfghj4~5e4$uRQP;*U$D5zcja zl%1Rzv9Mz5JwU9UI$@P5U%GJ}yLM*j!fEej4_~d+ zt}seKaW(ed&(kWDP#b_c=wihl0SF2kKgLpmAl8tzjg#pAEEcFfr+#O}Xp#~}?T~jV zwRv(qvVxB9!P!HURA-bMe$@usimeRS4|}t+QOQ@k*c&EQ(kX)jZ=ZbdUuc1`AJ?g9 z2Nsk`gAU45`vQ5BzmX7aLirSF zZ}aCGsp4ui9H*8FCUcIU+zMUzZ$#t%lxd1~sn$j#?5@V>?c9KXHXcXdc3-c9q5V>s z&16vtwnL9538GSScq?fvmwJNY82sR z8=BE?Y<3f_2C29M5Nsk)eNGaF5QWu}hG7B~CeELWpE=h-%h=1xVg^I{u7>Jm)`#hc z0x9mScP=O5bPTiQDN9MCq5%AM%;*tR7<5?75s5RbdL$&JX6n8E!rh^tA%i_QEH-g( zhEL2#b5YM=Entxl*=4y1d*^skp=rKa7~Ir`i0Ey!(>`1YiPRdkVS6l zSjg9^be-h5&+g^=|J1Z5*i&S4g zHpc!pTSt>oh1)`BY$81?DyT?iA>VywI5x%Ul1yN*RGLr9-8Me!Xzlh!;i`P8)~xa} zR2%(WoB1ZzJ|WuwFhK~DpJwfxLLl z2$W_F(2MFdw{!)dPEKKU`}4*XKxrkz7a2%h?jw10ac4fUGUK zr|q`y)Y_SWkX%H>gjjD6oP^=UtA-oUZy75-bPlA};^Mm%xi1|AH1-{GW* zEz}|O`KR9(i=Nk4+}9`5ij4MKwEX);UMBUXchZc>kOSS4U{TtZ7f6&-C~|}XBM|*57n&f<2M_hl!7st}+}>Blg1}jw zH3s#YC{njQ`|WmSG&Or*EWq7WNZH16^D~+d^`#!F|32mtB<13Re?MB#M%PN>OD3PU zZ*AhQ` zJ-~1k4j;C**DHjUv{Ky6uL@y*I2YeoixK{IviA8HX2r(RXx_KPeW@lE@2Yhsk=e+1 zlJ0i+N8MdtA#M6)sJ<{;D$ZAgoh2F3zb`5tv6!nUw_kn_kX^B{2Pu!Xk!x1TmU#w9 zQ=I0Ylf3bwXhb}~;)hecK)Ca-u=Aw81BOxp8YJCJKm6Jg4Uc~x5}i|em*_+OjKG#f zBZ(-)BO*1eyWK-w8~6h8Cnq3L=k(AS`ie!JQ%0%}=0)&$lz2l{?rHaNXNRNafE8Ef z=P7#I^>0rME)&+;<+_+YDifEpg5^XV{{;C#il|s&4*jdDGLwGKe$k6yqB=D7a;o2X zYj^-&EIPeRBKhfcbTeZx5Y99EO2mpYSh=kr=HVP#H>8QPn%k}J)j;tw%p!=jM&#a` zdzHF2^hU+2D9Q*#2KVWGcJCJO_v>quCI6rP00Nn2C?VXg$&S40aT8*%ssW4MzmVSu?hR@5)~nI zO15}V1dg%u+@Qd;mkN{?wH*uv*J#E#p z@qUGg+)8@wzL5V9#klR_PZ9pb@Wy+x9b3_&(9*8=pMY}1y5aBrN^PHSYQ*1QNwFx$ zgr`tG_pWJC#M***a);miNqMPFjc77ec@fRI{%=0%2#<}5JM|hn(fZ|*U~dy$SqoJn zl)O>gW?sxkJR0eD(S_Wjd2Bl+FthoP&t$*KT$uRE^yi1b9{%onlkL3?xeO+^Rv`wP z&?GRxpyk(O{d5|;cfCf=5bOf@e}(V{>z_T&)cr13RqmUBp2w8TrBeHj#Fe_5S)~sg z8O;;6okfp~h)HP+uK9J#zP=*FzE>_9cX_!6uJ1e9LyrzGe`fa{8f#dbEvmpa44f?x zpYxLgMgeyQ*8T60m)J=>w=O(30u^i+DnRCXk%rmB&}}SdGlGSv0}w_x7SWRPUF=$8 zk|o2|4u=nE_<>+H@U%3fVOVlg7Ue&-MfOeho7coYVb1Y2V+8VCZ{Vfg)qOStP$RQP z8B0T53?Q~XZ4#1xN~(~1mEd}bRy(DHCOdy4U)Mmbt9hh3)~dG2E{b#CC)D@P7H=k* zD=jgY%EKvhIJ0Zbf_!~42$X?uNN(7^IZ(QBIp_;$ZB&!E;=Pyd5+7|hd9L4VU25sb zjn`YUVCrG28OD9WDJkj_c}WrXsW4c--(#2t85lGVlop*UD@9aq86$(MgVUQ@f}_sO z&O!Ul!=#H|yCOuDT&-7`zs+v?mCh2_Ib>O$f+&B83YHFwdOgNBqver47QpzD$eA=# z5gB39zA+Tp)=8s=ziABOvQsH}ydGq`8yjY|WVf1UgFH_&iSCeHQ%yT#=FEQ*2&vfZ&$gqP16QpK)M*sy;a zd`eT(A+tm9ZC><}h1FdygdX3W4NYY-_IC4K$%4&)kquA>N(UP=+2B8q2~$2325q7F zRA>UCTp>h!ID$H4y3J|Pu=^O-HykD%$quG8rq4EN2>R)o?0)szZ_JXC&XzG}Vyjs7 zqk8R4WFNK|6L$F!0BXr}8g#%8%7`-r!ZVU;J|T|%?AzLN%G|E|d$8@O>py3KEC&It zEN{;7Q#M8$?U_u*0U7w*=l#%9;qgD<0_}K&T3};N(#d4{|Fus9!nZFU7PAwSgPd9o zrj?-+-54({u5%{eJ3!-Q(pwpO9ZJv4iGZbCyxPN$5hmkFngQXrrqvwO(=M%j-@Ile z(z5Dp|LI**0`AWMit_I5Zqthhc4NdXm)|L*pXb+J zfG5tO#E{uPm>cCjB^Gw-%xt{EyR-w=prvI@xlBRDvZugVzou;-vt4f*K`-eKOXcxD zfs=G*tE(68QoFyn-G)OGoR&TcdgKeKZ*E4z%)7H8GpvQ)pQNd7r2LjM@6bDLm=PBDUc-B=moN{M zn0=HC*LH%8yn;o)J3lAJPTam(2Rkv%GmEK2jNC16umZwUxKDjz$W&1}lMM$PC7m5k zX21-F)An%+GY6ZA-J=mdFSaF5=}QqCvg<;Ph|t2Rs-zNT1Fn}X{!^m$*;$n$A06ebxs$6|ayMJ(GRa`FpSV(68QLPB z9ckULIKq@Grq0_7$V2$KA%QCX#mk8qYWK1pZ}DeRP0^_d?A!&VhH|Mu42I=>Z{KJe&ZT;=O~Fo@u*eP@-bmb)06)`{8_tn|$iO{G z?ld~KMz4ug8t(L!WdtV$4i}-9#0F3I0xga&B8KVETY1&1!*?^AUrbggDT)wb--<}1 z$`FleeF7ByGf3!WqDCL52E<^brB#u!CI$jAQ2AS=5qRKTB65+n&6k573M+Xlb;()+ zV?p=r+|kc1rnyvfTWvpsk%Es-hxq>cJe$(E(hDLkzY~}6&PLggbto*^OfFQFZfaM- z@j(SQ^}-*6)-^x3Ilbwx)5|68QB&ncyI5kOW`5>XUF1^>iU@?9#IjijQK;}eJVz8o zlm;Ybk!ex7PEC##I4koeHU^?Wh|JHF6}gG+fr+nrzj`=n}o+VA`XmfNmDU^eZ%axY=)o zI!GIg$*^J?xG|2i^XWH9VqASe#P9Ns<{b^_Sd6k!5kA*IOUL8xp2J5}S&U;1N?$Xb z7zfCMWijf!fePA3V%TY0Opi$yILY{mS7%+>fX zh2nMby`@Iw4&SRFY%tb>!H%c;Ht!l|OL`dP(89aGxTp@{0{J!c4|qBPX5d(Y95n<*L)^ddmn-IkvY=c}h=<-%6I;wDz zDr=9Dt*aVh+%kj*{gl&#|3^_iu91HUf717o2xL623>t)|hj~*~Sc!>l4g1bU->6et z^2txNDca(Xe+h&czPkOe!RIl>_wG&b#ObduU*vrya@m1rA0*jDTVKaVn?ueGHGRAk zPNJSJnp6PG1CDaEBO|qvxzFv8qm9hiI`G)i*Vv>V%R?%NeMSbU@^9i#SxFMqv$h0n zL$#sS0bDoq1iAxg9Abr0XEV0jzIc@3BI8 zE_*H2Z=}-2jnNESpR-2c+L?QH=|gl1_i_S~bwqf0PGuXN9ZH9`0@5E{dxqg7x|_qS zsjaHTeQJ^|2&BYRD_LUYr*FT)=5?Wo^4g-0xmnM^^IO*X&t69>`M^nlXFI=sao_8B zJ7LhF2lj@W-E0z~n%rIr&;ZOAcBM`Uq0|TGFd(>IPY6Sa!ol0MJlg}ByrE3o7MHDX znpgAIkOyaA?PvdEnkzXu7EYgx3u`sg5$8qUjYe5Yln9N9K%TBM!VFgNX^Ej0WMM$j zWvRA##EDr~J{|_i49_vFg>Lo}5+a{0T8;qWk3C)_z4dpWJK_Y)-7T`la$C9t-PGVf zm=zaiOv?}$p>5tumOY{r=#quZc@cao^R}}hUrj|UBEaY`v0h|)mSsn$8EpU|uWC}^ z$GA;>u|W>r+cAM~PMVbA_Ha_{3kCUtv&DT*)5O{;(Hu-8DRluqsOq5$vg&8!_f?|Z zyYut-Y*z7yC?sw$!g9}xqmRr2Iov%B)=!ELyhDD7RCO4cbp*YA%&rMpi3Lphq%=Ch z1}Dai=~LS2w_Y(+$O_-c%MEZfX=s4&s9M(p&A{9n0Zvk`j9rLT)ww1!0C78X<&=-2 zGq;BuGehuN-~#Itj+#MnkEiModRK?10Yk$Q{K?Xs9zx@j#8MmO|1@A)CIA)*OK z?AHr+ZWdTwZxdh3{+;i(bgoUjdVXz4HhIA`ZPd_W5lmv&t+8#G5oh8Ml-!5nWffLI zIh90gR}@#bX}q*_>R0K{wU1l7U3KJxH`6B86Zv-sD)Fho7CK+|ul@EebW{Pd3u+LR z`9n@&_PM8JR*L_M)T);9rSNF>89^bF<%@J~Du2=9eQ0Xg*=rB9d0QhWLS&JcNU(T2} z>XKE6)^X<_N|erNHj86S{R2>BM=T7Y4#N`(P&>+%$0*3m=75F3gBiLEFsepJy;gS8 zkbMga@v7tqPDFPtaO_bNgJfI)bIoC`wEu>V9a|A=vzKZ3EbytpuEyD)Pn{H2PJTM} zk*^j-Edcy?)79&34bWTCff|);m`;&BE+fc7dv%FH^)pQpPfx6x1FQtSZIoie+j=J@ zZ9q?qGK!sA3ajh3T}7cuYshh>*-v+~GV`l$9;S`z&P=W2$0ejn3X8G{4hp2R@Ct1vXBFQhb_yJ;d#wGa0|#d;wE{Pwv2o*I{Qo zbR{JKrPE-%ud4Zz%O1qxIxh2@$;E26rKqc_?P_%X_t5P~MLy%C%NwE(PsWWpYZD0^ zp~N;WTFs|Ol-+s%n3(*K`%y1{$7nr4YrSCv1}t>P!A=BE>J+6zsY?)cQ}Qdbs->~- z*Td^Tp5tR647Fw2MD@v}51L%mgpD@+4!hjps^0U=vH&po`Lboz@9I6=%q20x>VJTb z{51>;J;$DW7qiykK0tpaR1Te_q-e-^8in`%3HCWe|F5)4OSXtX{bi)+Tv<-Rjip?W z5HYvKx^_x-0_3?lQGsY&C;UUmAQ$bc-)h`de6h&M_H2pzh>)L|2?l=pIy&WykTF_WjS zL9~qc@Oib~wU2t%Li81W-tfmRX*Eq7<JND6d8Po6<7C2r4l|Ie9bHY9Xguf3|q< z{UJJ1(Y_SD@~8XY@=nZts5p@R>j{(QTX&TFI5V2qpPz8OiZ+)lQKk5+T z)zcpzS9KfGJ zg(QI6OD3z&C{q#rBZ9tD0$a2C5bRZT*8RnCP?!%d#-geC(Hkb+@@akLYTZ8504I|C zx-KhAfild!4}jczl>0FVmL4=SsJb%3gtiF8F=!r>hnc9nJ#7OYoB2LtQgey?k3ZsL439!D~3Y0bgS&# z)Pf-x%Jm{T5tzdg1A{EY)m<4U;U<}|Zq*-OfOpf0Krm?$#56(sdMtsSnm1VkE_U1iM-NMV^MoxG-v(3vYmTV+F4K~&9H);x4bo*3`Yq& zkba9$JG*}NOsM@vMh7xsqb_kK7MqaOqf4NcN-U^?a|i)3!c!!XuEqD}e)pPwx>G9BUn0{(@tZddFX~a*t=}SB3WU z?*Y$dzd}pM8%gs z@yKHd+1e;O{#if(Vcd+~1o;*%#u(nswAwbCTLT#I@?ZstN58tOL)s2^MRV`WF=9Ln z)XR+kVz6!WV+Vhtmg0crxzh>=4|ox~C_}ln``)2`>!L1+tFJ6{GsRW`To5tjQ!fMe zt@i>YWlPbpX@_bOxEwZf+`Jx1_dsG2aSpww+Y9Ka@DIexOX27MC!&&ZI2r4t*pDt- zhl(UMWnuuI*_aX+9*i*QH3ytV-;+wKIN_Qm>i6GaS;}0r?^HU)LVeDis4(pKGGk=| zuPh9!Mq~go18xZT0^(*?H15=;2wd;4n9U{ywG@9`jBJ1t3tR6)Wva*;C1=?VQqaHv zT~Ve2>2Xh|vlYkZSIS^pupjFCK`6*jw^{)pMoL!+G0+1tzen7539lU9WB+ujI0KYk z4(>2$aua(vnqq;Cxj*+Co`Q2pkW2E+TA@4WZJXl5mG$hqrRVBpu5KftwQI|TrOI|} zwC`}IDU%0}ClZjj&BW)qt!WSbHFO<4xuOJ+LhB;Wl)<~~^-^y_MxVcnrUrRWO~Exv z=O`F8rG`EHKDye8mUH$76+Y@{wH~D)^^aPL*NK(kKknQAvB;qJ_JXB>H?uq*0x1ZR zgl!mie>g5)`^o|!oxVMUIgv62h?S+$`>gD6;Qh;GFTD9xOZ)HjG&F4OI;c`2ae5_E zpqkXpD#V)!GTw;Em-t|XnE2i}&kmauLOeYF`<$Y8{Iennej2N)_|~`|$%tcBI>&)~ ztgcoW<9J!5&VT%>7{hb8+NOaM6dUqwY_7(SS}4na9JpO|U+$AW@L)XJg;*~rGoRWS z9bYs)T$1s2|H!Z#Whl@B&dyi}X;u=+&du@Nkh9{RlQ8;4U&a7H1$WGPQcWOKgQx(c zrT-Aui-(jcxE*+dbl34=mf2hDS@wxtz92oqmeF`Xe==@^QY+KuCvkH+gX*kSS8^$z zl1I^;c22{77OkFw!o$YiT*OsQM{8;4$^C~=CcG-vs$<9&kY(f>7fg;KCF(yJp|;m{ zpjLWui8eI1c=mamB1C)$n9(;N8q~TNhlX(jf?t0fsB6$c+QZJ+EoOrRTep-?_TGYr zu+xTPiXS`Bt1C-onZBvPE=~MEow&5lfJB_x&nz1lA8XYTEr9ebosHTRVFjrZ#e&5) z-)6g`{8RDDu1FWcFc*{SZiYF*OzK-edKyF3W>NB)(mRgV)z;KW9HzeY*T0F!u)f#k zaxi|=s4?B!NTl1+Ts~l_AQNkTFna2Uszzp@b?E%B-9`G{LoMdrDAl78wAjzPM#X%6Pkr`;)zm~vBs;<`qh`S+6jHe#E#;Q z1!NEY{&_MxOKr<|y+N!k)x3o8p6cXTuwy7vO|`$4*c>qdNIxd&5Q=cfGw48?(?$?02UOLi}-!-4GWcRy&)SmwW+srqhpi(9`y42><`a??JHZ&gy={P zTTD_qB(>~lryrQj6Zif{Iimk6`{}tA(PyTa%y={D>KGY#qF8T-ZKG6>fbs9T-BeoBfrOTIQv}U`1$MF40w|p0W zyyavI;4-L28uZxib)-9CTj+%Xi@aftQk)VfN0U;MHD_=G(20yUtzX|$cHS* zHtvY&dfC7ED`E98Re!Vffq~539|&1vj>*uiANI;&hbvqgrUEzRIDanxO321fLBMBa zATP!a@wsFZs~LZC0L1^Xr8~WP7j(s3j!JH=4EPu_8*%K2viiO@e z9OCgpe%&HgQUzz|~cG=Gcb$LEW3ZwxD%uPrF(ckXU{w!Cw^))+B3AqOPWd0c>LZ;{%ucN?hAWgHkXRIXIR%jlZuw7P3Fuck|PLa1`K%%K$CPi8wu% zYA@GWl@~-aAVkEPJgya09Rw}{4nbI6`@4WR>lDM)jTlu~qnq-ZYXe49mc;vfxC!VR zH_?j7xP5sL4MZM)h?K5av z$u@ZMX2NO-Y4zfc&+Y9zdL4w%H)-s@f0jk9jy6gs>i{BjLbrcdXr?MC6Gf4upWRwA z#Ugbs9}T}iDJzpNVm#}xidJ8wojw;3;=UME(D*Bj80E!RC_?`7xPHoCywn_1ncF6w zGII{wpSS)5o9GOFL{vo!V!czOf)$faeHAEmruu|wvPM)WNm%dgxv|AJ_@+yQX8hpi zHbs8OyTG<6Gx`c7K#6*g1if58Mqk3LDYjbwhS)g{QoOvIQrsEfVK^~Ml zU&mfhQR934fio|;H}RU*eGBz!rDnOj>TJW9z=&oGbrA-k6jvq4KY5@?{SXo2dAB90 z;G`dOZ@R`KqBcZ|L^L@$*?3P93>C`9tmu*zV9K|LKo#)F6Ta(rugAoTw-bANi#&tY zzhh_3XTMpppMRTCjvfzU94f^~h4;;7S;iZ*oFTbWrQz6qsTqW1+M8tN%gy2W>_&}Y zqy0vyJv$0cmB&v70J}fjqbwkob#tO?lFm`1Pn1p^#)UFO1wj#hD5vNI4meBYm;3gq zWz?4N@22#>JhaN2(!^US#s=SU&~d@* zPuH{{FF|(0mWuhOYS!-m?}mwvU*6lDJOY^0Wx+aLf(4^F@sRbcX+FC%*y_OuDoID= zVXlc#&{LJ0quaMEXpp^!JggWVqqcby-M8c_R5z`SYT}kb_QXvSr^z*zucIWyrvE%% z7q5yaiw-2}l*me=*#I~FC?O<=bB(}l9|Wh@|GRgj7rKcgvQ%l6$2T1+9dH4r#3CaH z2*c6CwI+FUWSv++v^kVnAtJN{9@{A1?{RaJ%8PW-^^22Ob;w){t^90(-+JUt*B3Ly z#Hwia@}32;IvVt5rhd(ttLJ~eOieW!|1;1uNe6XUW3MRYU04#qU z1Qt(8oZ=Rbc4rV4OK;A8EeO~>+D9d2?f=}o`QnAmXQr=@#gVx4I{#}dBlS&NBo%Vx zajfd5Wn1;nPR5&?2yR7Y-6TSGYKsFAC7z-;El|v{)4Yx-}-8F VxM3W{C3$l(s!Cdl)sR>3{|~H3N+AFM literal 0 HcmV?d00001 diff --git a/docs/assets/logo_7.png b/docs/assets/logo_7.png new file mode 100644 index 0000000000000000000000000000000000000000..17d9db604a293761937cc1c748a33d1c17f98683 GIT binary patch literal 14945 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 Date: Mon, 15 Jul 2024 13:31:44 +0300 Subject: [PATCH 03/14] Path objects support --- suby/proxy_module.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/suby/proxy_module.py b/suby/proxy_module.py index 9237fbb..a6e7886 100644 --- a/suby/proxy_module.py +++ b/suby/proxy_module.py @@ -2,7 +2,8 @@ from time import sleep from threading import Thread from subprocess import Popen, PIPE -from typing import List, Callable, Union, Optional, Any +from typing import List, Tuple, Callable, Union, Optional, Any +from pathlib import Path from emptylog import EmptyLogger, LoggerProtocol from cantok import AbstractToken, TimeoutToken, CancellationError @@ -15,7 +16,7 @@ class ProxyModule(sys.modules[__name__].__class__): # type: ignore[misc] def __call__( self, - *arguments: str, + *arguments: Union[str, Path], catch_output: bool = False, catch_exceptions: bool = False, logger: LoggerProtocol = EmptyLogger(), @@ -32,7 +33,8 @@ def __call__( elif timeout is not None: token += TimeoutToken(timeout) # type: ignore[operator] - arguments_string_representation = ' '.join([argument if ' ' not in argument else f'"{argument}"' for argument in arguments]) + converted_arguments = self.convert_arguments(arguments) + arguments_string_representation = ' '.join([argument if ' ' not in argument else f'"{argument}"' for argument in converted_arguments]) stdout_buffer: List[str] = [] stderr_buffer: List[str] = [] @@ -40,7 +42,7 @@ def __call__( logger.info(f'The beginning of the execution of the command "{arguments_string_representation}".') - with Popen(list(arguments), stdout=PIPE, stderr=PIPE, bufsize=1, universal_newlines=True) as process: + with Popen(list(converted_arguments), stdout=PIPE, stderr=PIPE, bufsize=1, universal_newlines=True) as process: stderr_reading_thread = self.run_stderr_thread(process, stderr_buffer, result, catch_output, stderr_callback) if token is not None: killing_thread = self.run_killing_thread(process, token, result) @@ -80,6 +82,20 @@ def __call__( return result + @staticmethod + def convert_arguments(arguments: Tuple[Union[str, Path], ...]) -> List[str]: + converted_arguments = [] + + for argument in arguments: + if isinstance(argument, Path): + converted_arguments.append(str(argument)) + elif isinstance(argument, str): + converted_arguments.append(argument) + else: + raise TypeError(f'Only strings and pathlib.Path objects can be positional arguments when calling the suby function. You passed "{argument}" ({type(argument).__name__}).') + + return converted_arguments + def run_killing_thread(self, process: Popen, token: AbstractToken, result: SubprocessResult) -> Thread: # type: ignore[type-arg] thread = Thread(target=self.killing_loop, args=(process, token, result)) thread.start() From 2742d75caa7bf9fed02ba88d0fce5295ccdec31a Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:33:12 +0300 Subject: [PATCH 04/14] lints for tests --- .github/workflows/lint.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index be7dfed..59ad1fe 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -31,6 +31,14 @@ jobs: shell: bash run: mypy suby --strict + - name: Run mypy for tests + shell: bash + run: mypy tests + - name: Run ruff shell: bash run: ruff suby + + - name: Run ruff for tests + shell: bash + run: ruff tests From e496781f156e359e08cc380e5bb90862a551bb63 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:34:22 +0300 Subject: [PATCH 05/14] old version of macOS in the CI --- .github/workflows/tests_and_coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests_and_coverage.yml b/.github/workflows/tests_and_coverage.yml index bb84f16..ddf73af 100644 --- a/.github/workflows/tests_and_coverage.yml +++ b/.github/workflows/tests_and_coverage.yml @@ -9,7 +9,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-latest, ubuntu-latest, windows-latest] + os: [macos-13, ubuntu-latest, windows-latest] python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] steps: From 7e3c58a163e131da72241bd97c2ccc13ebd8458d Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:39:24 +0300 Subject: [PATCH 06/14] new version of the emptylog --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 63ad4b1..7d6935d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ description = 'Slightly simplified subprocesses' readme = "README.md" requires-python = ">=3.7" dependencies = [ - 'emptylog>=0.0.3', + 'emptylog>=0.0.7', 'cantok>=0.0.18', ] classifiers = [ From 0af60680f404756e8ae3186f07f5f989f8dc8eea Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:41:14 +0300 Subject: [PATCH 07/14] fixes by lint --- tests/test_proxy_module.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_proxy_module.py b/tests/test_proxy_module.py index 34a7431..e74fc9c 100644 --- a/tests/test_proxy_module.py +++ b/tests/test_proxy_module.py @@ -68,7 +68,7 @@ def test_timeout_without_catching_exception(): start_time = perf_counter() try: - result = suby(sys.executable, '-c', f'import time; time.sleep({sleep_time})', timeout=timeout) + suby(sys.executable, '-c', f'import time; time.sleep({sleep_time})', timeout=timeout) except TimeoutCancellationError as e: assert e.result.stdout == '' assert e.result.stderr == '' @@ -145,7 +145,7 @@ def test_logging_with_expired_timeout(): def test_logging_with_exception(): logger = MemoryLogger() - suby(sys.executable, '-c', f'1/0', logger=logger, catch_exceptions=True, catch_output=True) + suby(sys.executable, '-c', '1/0', logger=logger, catch_exceptions=True, catch_output=True) assert len(logger.data.info) == 1 assert len(logger.data.error) == 1 @@ -171,7 +171,7 @@ def test_logging_with_exception_without_catching_exceptions(): logger = MemoryLogger() with pytest.raises(RunningCommandError): - suby(sys.executable, '-c', f'1/0', logger=logger, catch_output=True) + suby(sys.executable, '-c', '1/0', logger=logger, catch_output=True) assert len(logger.data.info) == 1 assert len(logger.data.error) == 1 From 8fbadbb6e1ac67b8fd9e833f54aae7f3ffd70435 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:49:02 +0300 Subject: [PATCH 08/14] old macos for latest pythons --- .github/workflows/tests_and_coverage.yml | 4 +- .github/workflows/tests_and_coverage_old.yml | 45 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/tests_and_coverage_old.yml diff --git a/.github/workflows/tests_and_coverage.yml b/.github/workflows/tests_and_coverage.yml index ddf73af..553faae 100644 --- a/.github/workflows/tests_and_coverage.yml +++ b/.github/workflows/tests_and_coverage.yml @@ -9,8 +9,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13, ubuntu-latest, windows-latest] - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] + os: [macos-latest, ubuntu-latest, windows-latest] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/tests_and_coverage_old.yml b/.github/workflows/tests_and_coverage_old.yml new file mode 100644 index 0000000..519a150 --- /dev/null +++ b/.github/workflows/tests_and_coverage_old.yml @@ -0,0 +1,45 @@ +name: Tests + +on: + push + +jobs: + build: + + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-13, ubuntu-latest, windows-latest] + python-version: ['3.7'] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Install the library + shell: bash + run: pip install . + + - name: Install dependencies + shell: bash + run: pip install -r requirements_dev.txt + + - name: Print all libs + shell: bash + run: pip list + + - name: Run tests and show coverage on the command line + run: coverage run --source=suby --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m + + - name: Upload reports to codecov + env: + CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} + if: runner.os == 'Linux' + run: | + curl -Os https://uploader.codecov.io/latest/linux/codecov + find . -iregex "codecov.*" + chmod +x codecov + ./codecov -t ${CODECOV_TOKEN} From 1cdf593108e5ce958cb8354c2fab7bd01a32fe81 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:50:13 +0300 Subject: [PATCH 09/14] show the branch coverage --- .github/workflows/tests_and_coverage.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests_and_coverage.yml b/.github/workflows/tests_and_coverage.yml index 553faae..02d88ce 100644 --- a/.github/workflows/tests_and_coverage.yml +++ b/.github/workflows/tests_and_coverage.yml @@ -43,3 +43,6 @@ jobs: find . -iregex "codecov.*" chmod +x codecov ./codecov -t ${CODECOV_TOKEN} + + - name: Run tests and show the branch coverage on the command line + run: coverage run --source=suby --omit="*tests*" -m pytest --cache-clear --assert=plain From 7c48f4cff26b0d7120e33508fea739ff09a7ba97 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:52:26 +0300 Subject: [PATCH 10/14] rename the CI tests pipelines --- .github/workflows/tests_and_coverage.yml | 2 +- .github/workflows/tests_and_coverage_old.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests_and_coverage.yml b/.github/workflows/tests_and_coverage.yml index 02d88ce..1c1bcaa 100644 --- a/.github/workflows/tests_and_coverage.yml +++ b/.github/workflows/tests_and_coverage.yml @@ -1,4 +1,4 @@ -name: Tests +name: New tests on: push diff --git a/.github/workflows/tests_and_coverage_old.yml b/.github/workflows/tests_and_coverage_old.yml index 519a150..7dea647 100644 --- a/.github/workflows/tests_and_coverage_old.yml +++ b/.github/workflows/tests_and_coverage_old.yml @@ -1,4 +1,4 @@ -name: Tests +name: Old tests on: push From 623837de3364cd1c56a09c087c17aa01ee5faed1 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 13:52:55 +0300 Subject: [PATCH 11/14] branch coverage reports --- .github/workflows/tests_and_coverage.yml | 2 +- .github/workflows/tests_and_coverage_old.yml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests_and_coverage.yml b/.github/workflows/tests_and_coverage.yml index 1c1bcaa..be6a08c 100644 --- a/.github/workflows/tests_and_coverage.yml +++ b/.github/workflows/tests_and_coverage.yml @@ -45,4 +45,4 @@ jobs: ./codecov -t ${CODECOV_TOKEN} - name: Run tests and show the branch coverage on the command line - run: coverage run --source=suby --omit="*tests*" -m pytest --cache-clear --assert=plain + run: coverage run --source=suby --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m diff --git a/.github/workflows/tests_and_coverage_old.yml b/.github/workflows/tests_and_coverage_old.yml index 7dea647..65ee5a7 100644 --- a/.github/workflows/tests_and_coverage_old.yml +++ b/.github/workflows/tests_and_coverage_old.yml @@ -43,3 +43,6 @@ jobs: find . -iregex "codecov.*" chmod +x codecov ./codecov -t ${CODECOV_TOKEN} + + - name: Run tests and show the branch coverage on the command line + run: coverage run --source=suby --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m From 41d9268155dda78a2cef81e1feff905dc9429d02 Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 19:25:39 +0300 Subject: [PATCH 12/14] new tests --- requirements_dev.txt | 3 ++- tests/test_proxy_module.py | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index 6b880b0..7605802 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -5,4 +5,5 @@ twine==4.0.2 mypy==1.4.1 ruff==0.0.290 mutmut==2.4.4 -emptylog>=0.0.3 +emptylog>=0.0.7 +full_match==0.0.1 diff --git a/tests/test_proxy_module.py b/tests/test_proxy_module.py index e74fc9c..046defc 100644 --- a/tests/test_proxy_module.py +++ b/tests/test_proxy_module.py @@ -3,8 +3,10 @@ from time import perf_counter from io import StringIO from contextlib import redirect_stdout, redirect_stderr +from pathlib import Path import pytest +import full_match from cantok import TimeoutCancellationError, ConditionCancellationError, ConditionToken, SimpleToken from emptylog import MemoryLogger @@ -308,3 +310,24 @@ def test_replace_stderr_callback(): assert stderr_buffer.getvalue() == '' assert stdout_buffer.getvalue() == '' + + +@pytest.mark.parametrize( + ['arguments', 'exception_message'], + ( + ([None], 'Only strings and pathlib.Path objects can be positional arguments when calling the suby function. You passed "None" (NoneType).'), + ([1], 'Only strings and pathlib.Path objects can be positional arguments when calling the suby function. You passed "1" (int).'), + (['python', 1], 'Only strings and pathlib.Path objects can be positional arguments when calling the suby function. You passed "1" (int).'), + ), +) +def test_pass_wrong_positional_argument(arguments, exception_message): + with pytest.raises(TypeError, match=full_match(exception_message)): + suby(*arguments) + + +def test_use_path_object_as_first_positional_argument(): + result = suby(Path(sys.executable), '-c', 'print("kek")') + + assert result.stdout == 'kek\n' + assert result.stderr == '' + assert result.returncode == 0 From 793cc53b132b0cbd32d3e3c31c938cec23a15f6f Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 19:55:02 +0300 Subject: [PATCH 13/14] new version tag --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7d6935d..b1de280 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "suby" -version = "0.0.1" +version = "0.0.2" authors = [ { name="Evgeniy Blinov", email="zheni-b@yandex.ru" }, ] From db27ddc1cdd4de58462caabb2f69b1681ded1bda Mon Sep 17 00:00:00 2001 From: Evgeniy Blinov Date: Mon, 15 Jul 2024 20:03:31 +0300 Subject: [PATCH 14/14] readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 99788a4..b440092 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,8 @@ print(result) # > SubprocessResult(id='e9f2d29acb4011ee8957320319d7541c', stdout='hello, world!\n', stderr='', returncode=0, killed_by_token=False) ``` +You can use strings or [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) objects as positional arguments for `suby`. + ## Output