From 0eab09e19d85ffd9aab0db39ff65f242e16e8d1a Mon Sep 17 00:00:00 2001 From: catborise Date: Mon, 2 Nov 2026 23:33:34 +0300 Subject: [PATCH] feat(operations): the job panel and job pages speak the page's language The job panel on VM and storage pages wrote its buttons and notes in English (Cancel, Open, Refresh, Dismiss, Finishing..., Files not removed, Worker unavailable, Cancel failed) and its state badge as the state's code, and the jobs API gave the phase untranslated. The panel now takes its texts and the state labels from the page's settings, and the API gives the phase in the viewer's language, as it gives the label; the job pages show that phase. A job that cannot be cancelled and ran past its time limit had "(over its time limit)" written into its phase, which then matched no translation. The phase stays as the job sets it, and the pages say the job is past its limit. --- locale/tr/LC_MESSAGES/django.mo | Bin 158550 -> 159122 bytes locale/tr/LC_MESSAGES/django.po | 41 +++++++++++++- locale/zh/LC_MESSAGES/django.mo | Bin 148339 -> 148923 bytes locale/zh/LC_MESSAGES/django.po | 41 +++++++++++++- operations/api/serializers.py | 13 +++++ operations/static/operations/job_panel.js | 28 ++++----- .../static/operations/job_panel_start.js | 2 +- operations/templates/operations/job.html | 6 +- operations/templates/operations/jobs.html | 6 +- operations/templatetags/operations.py | 16 +++++- operations/tests/js/job_panel.test.js | 53 ++++++++++++------ operations/tests/test_api.py | 11 ++++ operations/worker.py | 3 +- 13 files changed, 178 insertions(+), 42 deletions(-) diff --git a/locale/tr/LC_MESSAGES/django.mo b/locale/tr/LC_MESSAGES/django.mo index a4f64b5ca9a4ab47e1154260fcb000672cb9fea9..4736eb82c4605a6e4d03f410f8a4cbddaa08fa5f 100644 GIT binary patch delta 38201 zcmZwQ1#}h11Ml%o2u^U<3q-LH+zAkz;O>D02m}po7q{Y8thl?o6>o7`yhuwaUWyec z_P)P6!~gK!d3(79i;TkN8e_~eoNE@+^GD$m<<2K^z`q% zAmB?vqVF9i6Q)Ovydb8)2vmM6RK+f+2K!@M+=ebpJI9nOiW*oYOog3M?F_c@iI{`< zLd;D6&Orh#@j6CgvAJdi=3p)2n^5T=F%VnNa~wY$gK2ObYG#M9JU&7VAb7sxgkW7% zy3t4}E0_hi-XIlod5^sSSu)j^8iq(m4!Y=q8!!dfX;|#&I zm<5BDI8F%+M{T+xSP!@0A&j@w)H{j=i6>g-cANqPN-i@MJ0Yv=EWy-Rdbt^CZLCUs z0#?IIsE)F%Fav9drHC)Y)_C2n7B|4q{R~VZDSJ;B8dBSE!D>H}G6BF=~dXQ7huI>3LBDErMxv{%aFR zOhS892VFfGEH7#gOvYrm1T*4B)Ui5=`SC5PzW+wkaR{oz5~zV!!sJ*JRj#>>M`0rR zcj5>{<6w-Bf1sA=A*#ct*7%!DL)lRcI1O{-KGcfcL2bg< z=q^Mc{br63R!5gIP{$_S7PH$sq8iwY8qlw(4xgb`>>X-_e72euNrisI%cCX~g&JsQ z^ub~1i=(%){tC<>K_gm%n%PlIg=cO24r(bMVG4YK9np)ojv9KMv<{`cgYvUDEJ^vl% z!zTo_DeI#K)(q2NG^*bLZUP#~a9dz3>e$4Lm36xaLEhifX7&#d??y-MtCunNC0rWEraB8q|AWJL=h=L5=($)C_%gnE@n6 z7x8o$g2hlv-vRZ$=!@!jhIIjIVk?k#+|E`4TAKZ+nVvEk&UMs)?xAM-2-WaE=$Y|u zGr;8NB0T^#v#O|aovj0{6EFkm^DrZB#SoqU(*!i452$CEXpec77RE}%TcDopBJ{_< zQA?M0uQ3m%B_4(vKqG5^)IjE=2D}cnf_tzco<)D1|CIa8r&Te`LA*0+i6>ZRqMqqO z)U)4!8o(h;jh9j7AEH+5rS%)=PsgS8Hs3jI(G%*1B63|;sM)lv4tronuuM^YBmab463wnI&96l%beQ7b&#O+XF& zfEvI$)DrDRZK`9aiq}!;_fP|Qj@nG0QT0>*Xm+&=HM5eaay3xpnxX1tiEagR1`p)xOVB z&!%@fnF#3FMW8a;V*vI?J>x~F&9n*C@NTSthityrF*B1?n49z<)C$x>tw1Z(1Y%JW z8j9Lm6S1+*|8fGV@BtTMvg7tqpc>eXCGjL`hF&Mk%(G%W;z6jT9Ej>*8t%kJs0lPa zX;z>EYT)~^EPh5``gh8lGMlOf1`=P674eKsPw|uKFb368AIyOhF(Ix;O<+6flpMzd zcmZ?bRaCk6r~!KY%;Uin=vKiN1T@ojs7KKgRbeb@NvGfx+=hv<(rMFS1S;MdwZxsU z7Y@V-e1?gz^cmA$IBJvE!m8Npj6MHLY{q)@A!83##)DWCea@QC?NX@C+7}DrOe~Ja zF$sP`b(rX!iKjvx$E=tPLog|pvGHo>SpVcCG$KJpp*CS0>e-FMj5r62;TBW_4^fZe zHO9xJ=gp={g<82_RL7yHfrX#^9{fIYn6VQx?q8`Np)FxSmMeshVV&)5G2074| zcs@*lrK~kjkD@v1yhmXs?2j7obeq4>=C4K#+`Zps96>$9GpLc@MlIzFOo{)YW|s7# z8BiKjdPdY{48{Uj9W|l;SO#Zf75oLmG4myp-v*P@zcYkD3o<66&gDasK@IZ?PJx

7-s-07qQ0M=;C*U~0qju#Z)T0Q! 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 G?ff4`lcY`n delta 37673 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 diff --git a/locale/tr/LC_MESSAGES/django.po b/locale/tr/LC_MESSAGES/django.po index 0a8cf168..2674c57d 100644 --- a/locale/tr/LC_MESSAGES/django.po +++ b/locale/tr/LC_MESSAGES/django.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-11-02 20:06+0000\n" +"POT-Creation-Date: 2026-11-02 20:32+0000\n" "PO-Revision-Date: 2020-11-04 12:00+0000\n" "Last-Translator: catborise , 2020\n" "Language-Team: Turkish (https://www.transifex.com/catborise/teams/110663/" @@ -103,6 +103,7 @@ msgstr "bir yıl içinde" #: admin/templates/admin/user_form.html:16 #: admin/templates/admin/user_list.html:58 #: operations/templates/operations/jobs.html:15 +#: operations/templatetags/operations.py:91 msgid "never" msgstr "hiçbir zaman" @@ -290,6 +291,7 @@ msgstr "Parola Değiştir" #: nwfilters/templates/create_nwfilter_block.html:33 #: nwfilters/templates/nwfilter.html:178 nwfilters/templates/nwfilters.html:93 #: operations/templates/operations/job.html:31 +#: operations/templatetags/operations.py:83 #: storages/templates/create_stg_block.html:183 #: storages/templates/create_stg_vol_block.html:35 #: storages/templates/create_stg_vol_block.html:68 @@ -3596,6 +3598,7 @@ msgid "OS details" msgstr "İşletim sistemi ayrıntıları" #: instances/templates/instance.html:39 +#: operations/templatetags/operations.py:85 msgid "Refresh" msgstr "Yenile" @@ -7435,6 +7438,11 @@ msgstr "" "Harfler, rakamlar, nokta, tire ve alt çizgi. Kopya, filtrenin kurallarını ve " "başvurularını içerir." +#: operations/api/serializers.py:35 +#, python-format +msgid "%(phase)s (over its time limit)" +msgstr "%(phase)s (süre sınırını aştı)" + #: operations/templates/operations/job.html:11 #: operations/templates/operations/jobs.html:7 #: operations/templates/operations/jobs.html:9 @@ -7509,6 +7517,7 @@ msgid "What you checked" msgstr "Neyi kontrol ettiniz" #: operations/templates/operations/jobs.html:14 +#: operations/templatetags/operations.py:90 msgid "Worker unavailable, last seen" msgstr "İşçi kullanılamıyor, son görülme" @@ -7586,6 +7595,36 @@ msgid_plural "%(count)d seconds" msgstr[0] "%(count)d saniye" msgstr[1] "%(count)d saniye" +#: operations/templatetags/operations.py:84 +msgctxt "verb" +msgid "Open" +msgstr "Aç" + +#: operations/templatetags/operations.py:86 +msgid "Dismiss" +msgstr "Kapat" + +#: operations/templatetags/operations.py:87 +msgid "Finishing…" +msgstr "Bitiriliyor…" + +#: operations/templatetags/operations.py:88 +msgid "Files not removed:" +msgstr "Silinmeyen dosyalar:" + +#: operations/templatetags/operations.py:89 +msgid "A short operation is in progress." +msgstr "Kısa bir işlem sürüyor." + +#: operations/templatetags/operations.py:92 +#, python-format +msgid "Cancel failed (HTTP %(status)s)." +msgstr "İptal edilemedi (HTTP %(status)s)." + +#: operations/templatetags/operations.py:93 +msgid "Cancel failed: the server could not be reached." +msgstr "İptal edilemedi: sunucuya ulaşılamadı." + #: operations/utils.py:52 msgid "The host of this virtual machine cannot be reached right now." msgstr "Bu sanal makinenin sunucusuna şu anda ulaşılamıyor." diff --git a/locale/zh/LC_MESSAGES/django.mo b/locale/zh/LC_MESSAGES/django.mo index d403fe8fcc0261f713eff7ec20c3c74a71c1600d..b0b09b558c61dc835b372f33c3b2fd46026723ba 100644 GIT binary patch delta 38209 zcmZAA1(a3Q-^TGXLw9!#%`kL#Hw@j~-Cc6&lJ4&A?hud;0cj)@hDM}BBz(Wm-9P?| z^`5nkpWSu#KKIUm`gU}b{Xa(W-HjW5rpI+RqUR;Y==nV_B#P&K?xIxBTQkk`3gKGJ ziw`k3CY|nip;#4zZ~x^2~%Ppa|UK0z8$mREeys;vt0R{sQQgj6Y!z(_hEE=hzaT6drcq)36W=e zUJ^`*8hH+kg`ueYCa8*?P!0CS=C~b$F#a4@E-z|er7;e6M71;6;uA0x@kN-F{=Gv4 z8sklDf%)dT6_|rnh;K%vf5wd1be`v>!_gQI*P~{37>nam)Bu9#dtP>|j;c2lRc{Sy zMbD!zHi3T#XogW1xD`l*T7jIH0;`&xF#+-M$ae9TU|L*_+wm-F0KSE;!^4=D_+xC2 zDHeHNBOHQ-@zx^NKRtnji`}y=g2{v3Z@^$VR&qB3x0;A%esLl7$jJDoAvJ_@I)FbzWSVBRJL_!JF(pSLv z*c|=G4)thepq6?oro!`<{t}ZAkGjE?ONZJkB~g2&9%{2T#ctj;vi@`V*)8c;AirqtP!guJ)MIhl8 zju2MFAZ4JAO@gg%x3@zzumv@sE2s`%qE_r5)Cz^)=2j#QrXyY)HKEq1fp*03I22>x zsBNsj0@F#*h?b&eb`0a-d5hmeE#*^;g|D$42JqHVgB?(tt1D_i!%^iXp;lxO#>NAv z7teXrz@qG6{nc=+9WEges=*YffuuprGz$h{e$0vWEj}JI6JL*2@fxaL`kn5>Cp&6W z)aLWe-(|jr=dv48!ks1Bi)1#1mk4 z%!gX~wy5_-UsT7_%>}55twh@KdD{qRX%3)fddg*ZH&Fw6fST!3RKtIvf5v;<0Apeh z=^0QnD~~GI(Hv-w$3&#h!^F4^v+MkyC7=;~LOsjKd)=!vHX|M=J^PKQ z0UXA-cokLt32MdOnE#-b{wr#Nkq)>4#7C`oCiLl9=OIu7i=zroMJ@Rv)UjNNYWO5- zM&~gZ-a#F&kEj7AI_Nscfa_I)NqnHD4 zp~^)&m)0s{QcC{F~nA zB_W_^7mCVgg&D9v>KQLaZKlnrhWB7eJZ$*^Kf9U4!L+1jLajg*)Cx2~O`tPsLPJn{ zYXa8Q`Cmam6+Yo2jDFl61*(BPSP)O5W*Bh7%{)2QAf5@elmk&6OvPQe7&U>qC*2CP zMGgD_7R9d^gZ{lDr`)Ehgc*siz*2b5(qo-=9d7wXxK#l$!V^Wj!h15Z$o;vGi7 zXur5k6$iC)!KjXNq6St5HL+@DZA?eJfscS@Gz9f17N9oCa?FEasESE1x*4Rx7{s$+ zEG%SJLOqIxsPo<$lVE?;fTvmhBFkTc8o2L(WgJC4!*i&S-$gCuYmANmqGlHDk{eJw zRC;36W(>w`SP?a${#XQOVLAL2%V5&WF25PZq<`-R0*%O+fI62?Tn07VD>xQvW`$54 zmO+)PgR0jBHPF-89xr1dEPTc7nZBr*ZbPlu9#lK0Fp|#yO@F}ien;)fr>IAf^QxOc z0n`%q!MHdKi{T7ZxnEJw_!g>M7{f4}P%|2c$#5KIz?C=}&tYz?^_v^m7%W75lEqJ> z`nmWU>#wD|Z3(}l2J!+E;6IoIW8QH~nhC2AFMxW+qfq7Nq8{N&Oo*GXEFMSgk!W|_ zrj3i5aAq^RkAND;gL?KQP%{ffZMMd!rSE3x15nR+ti@-czhl%yHlZHb4h)B3sJ-wM z)8j`himC3omGw0tpqaM8KpccxnjzQ?$Dx+|BWmQy@4Eq~M#ZyQJQr#p#mw@kfmg@G z*bvojFI<2_u%*s_vftfq9)cOkSciG>GHOL4|KXN00cIuM2(>51VIWRLbux98?2GFdd%3V0?wz-ANw0XIT#QB58_x z=G{=oZ8R3f`Ir)~qaMNEsDVZdb8o`f7=`}5Is~*d&9FRnL~X8ZsF9z*ba)fB8NZ@B zNc_lszSl;T>xI&)x6s za$^DF(=Z*LMK$mj>e#)ZXAd!{ikI`I^!&6XLpNpqpfHAg-Bj_4lWy|1RsIudi347`c1P!(TTdg@oM!EC6_S_BhdBh;Shf!T2^>V>lhwTUmG2J{j& z!N9+qQ8B8{e_R4O$0<-9XTw-n0@Gr3RK?z?r5}tzI2<+L<*23IV)Hq6U^9Rj(pyB^sk9)ZrcLuO;ni8U0ZeN1^t_Op7l-RoH-9ft{$O{0Y_I8Pp@V zj#`1&sEPb%`O)6H`iW8XQ=?WU%X`*e4HvbHa;O2+KrL+xOK*#T#Cu>&?2TH=5qJoH z#2~Enw|nJwLJe#zYBSEn?6?V2<6X>%p6`QeC=+HPo&ytM1I&s&P$OQ9YG@rM!ef{M zZ==e6M7`@X{^QciU^?P0QG00&YGOxGz8F6#{w|6Hy)PL_ND- zQ4QQjjra-bQG7tnH1LaiWHB)T@%*Uc8;ZrS2Ij*lsCG`G_Rue=`j?fi^MBV0JVGt; zpI8e6zPeATI@p%@L=3`rm<<#B=bmvH)POr+ZtROya2-~|4_Fb)djbA|O+`K8i|Er* zz9omcX-S z^uPe0e|Lrk2KdkWSkw|vMm01KwNzU%10F=p^dahzyhd$4FPy6v-%N!XSZ35Y&y6Xt z3~ItH&355@uEEYEsG|YqC{zbiF*z>5RCv(hcQBavzo-V&g?HtGQR(GSFR1RQb_SwW zZXBwg$*4y&-$y_NpJPFMj~aRQ2m$`{Spb8GSI11)1N|$5{*^%==?75*EgCVve<~WH z2HXb=;Y`#cxrkb^8y5GyAfOK4S;808v5FAMEol&HfFY;`@}iz)QB=K9vo7k`HA5|V zf7GKKhZ@KXRQ(;Ol{kP*z~>z$pm+TR)Ent4YDr(BPQx3li4h{Zfz(Gm%a#@&ip7bK zN4*EmpgO*R>hJ+-K+mxWenxHPhEX&T)~-8&F(eE{4J2|@cM4*mDyBvaAQv{rQP>S1 zp&F_i&Dj|>)8VLRy9_Jg8!UxIqq_kO#bm_CVl?{qRuIsVY(YJnUFI3ofbODZ6o#7N zUziTRT6)?TuHkH`0p~+Kn(~%j9o0^Ki#M})JM`(5*_D8ndWvN%M?K?pSOoXsVElmU zpm$8St4E>g%|NZhYSdmii0bepro;=V0lh>`^l#LJKF8$zYu84K6*&0d}|ap{PAG4pnawYCy|T<@Tc98>dk#d=0fXp2gz)>v+5&K^U=Lib+jJU(SA!mh3e=!s{TFHioV3WnAsO6!2kK(9J7%y z33ZGPVg|g1I_FgvO9X~;p`x`aDFQ`|zFKRqj zASRY1Avx+9H$^?mZm6XnfSTcO)Dlj!{8gw9x1g5(1ZKqBs1KQN@m={07)-nnD!(-* z(fOZ1KowV^&i{T?$G>7)yo2d6Ac2c##3168F%Nde+_)5T;#Dk$krKLzl|wy(+Ng;& zw)8F-Ugv)h0qw@2*c5-nX86p~DBre<%{(vC-+qB*F6??dg4pRqPxM-3oL zVmHA&Sd@4b%%Jl>o`9asR@Bn&K^>EGmh9Si3qSA+>mUuVn zjrA1EV5&3$UOjA$+RX=W2L6kUaB|uJ|F2k{qmFOdbnY}%#315}kO}&{!vs|E5$er1 zD7|}8%)sKr51~5ziVd-J1~=11s2SYClK2nm(G|+*9z|7D$IY-TjzYbF&Z63VkEwM2 z^Ja3N0d-IvO~Gb(6{}<3VE3#>qrRf;L^bdVb=0wdI>=2xFN&I&3HxF?T#U;988xs6sB#%|x%A4Y zZ#ErK6WNGrIBRZqs_LQk(hStf{)BoY5%M@g@^Jn&(i$Y>#&M|4bP$8^lbJlPOD~Gr z^@C6YI*xh-QSw=XW(~|vdOveD79)NgwE_wAyOqnA-{+277ZP;b=A#N8MGY*VfP01o zu?6uKs1-S8>3^VR7`0%4S0D4CHsxe&j~h{YAz>l+@mw9t6CZ|}=xHB;N(3SmcIUe$ zYLm=GRXm4!<`IjyO;-wQ5+9CL@ha+(r7IfXjl)pX0Is73`X2S7iC@gUs7hlN;>}Sj zOtpwME{LK5sYyb+{3==^mg~AaYsvy`V7ay-*!Bvkq7s$Do$} zBqqVPSOH^{bC0YpYN>}{1U!Lyg`dM9{0)<8+kPRS4icAlU#W7Uo=p|hZXJ&r&=%A# zet?=;rV8#2I1ROVpP{}hrmPs?|MUO6n27ib)WpJ9a+@{Stc?D@|J#LtW-u1DJC~uJ z*-^}auTihyG?m>F*2YQ1hhP_ z)I)XH8slSk)Mg)5!{<7fPl6iWfg0(4R0k)_>!{uP1ogs+Thq-r4{DE;L7kG0sQgJ7 zid#^d?<;Br!`E^qL`^i4k3eJsIZ!K65Vf?$uriKDHFOzu-h*npH(xi5PJBD+{qYlW zoV;jt+|2W#+AV_`Kq!{QTBv^JVmS0IBB0&A3{~(xYAGL~mg*^LDZiptBzj%9lqpb4 z7>seTII4V2)Lv+ZF|i-2-e^moZLUThiO<_jKph-IHE;>_2p*vtc#T>*ub$g{aZxi% zj+#Mw)TdxD>ijpi_*&HWf%}*d-=SXZ$?Lmg+z2b_{4XJ(iqEkh=4s$M-hf)-{iu~W zg__v~)Qs+0{wvh8{ER9WzM{jgcC;b6y!W!#1da4M5c&huZCHF&XYe4e%1`{csbt(r?lK`5(ElE07U2 z!tAJLTLg9dYFfM#1`!{InQ$3uCC;J-@Eht4_yR*PTobqC*-@LbD>lHns7Ls=3Flug zkk2IOD^aedu7QcDk*`2)uAflv{$Ei`{MzzApjIGWGq)EqqLwzq;)PJJ=3=P!dSZ5* zglg|lGoL%Zzmbrhguv$RyI&?$g|Vp3xB|6FH(UH5YEzy2ew?%b41T~P6 zsDVyI&3q~9lx#*llAlnI_$2y&|9^#mX80RwY5qh#tAA0)>OWKmvD&(L0@MuCqn127 zs$PCeFO8}nidC^D>Xp6}HJ}x!^4rjtfxsb42t&>6HL604c5X(o%_OLir$Kd)9X0Sg zsDYG2?TxCI-vBl6rl=KZjarHRs8{#6cAS4zoJfL>%S_aaH={Z@jB4O#)Y6?XFQMw) zKs9(D^~L2iYKGCZ_&!7exzOze@i`ujy7>d#9#I3-jC-M0U>s`CEJB@{eW*S05Y^7#s7D&BtNV~kh5B$ShW_*4+y%TI z=5Q=Tf$7)=FQ7We)6F$h9WxSdj+)U})E-!j{`Uv!nIA_D_!&0E@ZH_-|68Hbk6<00 z|J#<4vxi&a$*2wvqGlRq>7P&o3-0MYL|UWD&A_a9z~ax$xV_xK3ZYh@GU{W#5o%=y zVlw*orYnG(E#oZeSw2L)vEJZOOwikXbGdlDNzf13j+H`ABFPJ~@9OfM0(!XLU z;spk}6&r*qzYAC5U#RwG4dVP)B(Qdno7r0|PrSfj7axkni62Luk_bNpc+Ig0s)L2N z7w@CW%^Tu2*DV}M{4;8TKXA-7!C9zw?x9vN;ZOoE2$US^e*Dfh%+0V5_9J~2s)3Zl zUBmfNZ@32Nf1{cGQ7@Pbkj1Z{_RwwAsd$PymS0gF#~$fk<-W88G@~4-0)@>`)GM`_ z#RsA~oPhcaSb%D1t;G+Rr%{{vn)$}kV~%q5lA&HenUMNEuY_gPLLHChm<4^PXS4y; z@pV+kk5RAGcc__vMa?wAXcv!XCN)!I6Y?`ze6%?clj;1=@CW$ff$HF#dDGG#Sv+uz zn^`Q>8!W^OHM^l6!BmT{M(z63co4&lb$jUu)+2rko9O)K8t2|vQ&0`;M9u6hYCxAQ zeh;-Gk1z=1jCbX7p~@AscsYxQnhjAa+s^VwqaO7{^r_-v%h+HU+i@`I$1T0okM3Dl zL_LbesCu1Idt`vcXJ8rPOHmVegnCpjE&jp$imD%B0_R_WxD)Kd0d+o$p+3F(U@*?b z8h8xVaDs{M5hO>&i=o;niyB}}OK)j*u=MU0A8PS26FL9d#j{B$itAA4`iT|%jQYF| zH_3ftiG?~X@lcyCCF)pavGj_l0oO*Y%n-|;iyG)I)IblS-YaK(1aw>;pho^5YRO_v zb`_GKKFxwq&%P{bz}->rg%PNR7oxu5tU&z)w9!0(n!s7qGrw-}r>L)BzV`&wz(>@` zyeY1O7^uw{gxc--%=)Nu1I;n!4AjT*Qq&6WL47)&v;23cM;b8IO(;F`+2Qjl5$H_D zT+4_!&2=1NmP9pN5A~+(YED26WF2bdcB2M-5{uv+)QTmY?q2C-Q4{HlsyD|k=Wite zE%`RfIDl&CG^*iymj4Rjd zmr$GI0cvl2w*161UBjtR4P-HMV=dx^EItV}fSITcms$D-i*HA@dk}pZ*-ZkfkZP7S zjGB3FR0E|^D-w#T*vj&K=45j*>X~o0_;pNA{ISJj%yz%jN`V1xe+zsJ*X8riYj*+RqvX`AEEkvJBRbHj3{%R zNl+DnQI8^@rB^_m=lYi4%N%O?6U~K|zR}|QP_N!Imi`pg@!zOp8QnL}eLg3~@FZkK zb(9NLAk=JtIt6V|GaHO;aRj!(XO>=lzI!j!L!E*isFmG>>i7uitKD^r`ywxJ4W=~H zqu$|JP!)QhHscu7vs{8&nG@y>R0q#cEBOWWNMbB>U)6$9D>@#B;cSa1S>#Xmc^L@k zyIgKmM}1KZO~%@|81;qW9jc+|ivzrqm;@F79rbbgCl<$YOWdEHjYhR|64lOi)cMb{ z)O{DMimmkdKbwG-^b=|(fy>;?6QI&VPz~iWOIdnN%s_eriw{K&Xbfr~Gc5gzrQb%a z=o3r-in(?EBPqd_d$Id9*n-M1dbEPk8e@0*pOB3dwWGJL3|{tf#awdUN!%)^j8-D&y2p> z{p6Db^;wYFEQVTvny3l2U(NYXMPLvKxo|$Jg9}#hHfqGLQG4Sbi^o~x29y{z^Gv96 zIn4Z+hIld5GjCz(BTzrEjK_RL?WT@!1wNfbpnDwhT+- zEz~JWx!#p)fttuDtcTN3OaBbjuD8Lp>x)f59R{N+<))hp&DE$!v=wzK_M-axh`gZK|C?OJqNov;#{$^I(r2N*YArzxa1*NB ze#^gv8qjT2!_hap8OFnm#M7ecRkrl{sB-Nwi~8?IK)ZASX230|O>-Sp@gu52#4Ro! z!%T`=%8X`yv%FakRj(b+!mgMXBW!gOD2)Dp|E~rCbu_>njh%^4M{O2wn`aTDc->J0?Ts4HNSup5qW|CjO~1nx$bxF12x`|ivUnHN zicG+|xCwQ9BJ6Yx7D0Vxlt%4=v8V}6v;4)V0jx52p*Ho2ot%FK?peY=*pPUfU9LiB z)TiKJ)X2x8zV%K0{I*NwCM&YlYfdT`&-bS^7vEKzx#qKoEh*d)?=MFlxrx zEMCas#Zix>GU}U76SF<4gI*RNgENRv!)BOqpL-LIL9Ng_EQse&1NTMT@1A8m)G?}r zn&}|a<{6G!fzenCr&#S8mnM+%zz6~?fr~wW}kO~fX?Yh z)DosX=yrEC)TU{J`a;pi(x;*}-)humy^DI5Ur-IlKIGnbNl^prX%0ZW(1xOZBXSxO z==|R$kdB0R{sg{Q9CokL?5J06Pt5nV6$`^u_!M^+I}$diLp0xegkm zI_zL}N43+>^2cCt;=UP{am9RyI#%yc&p6&`XLeLal`ZZ=m79-xRQpgJo;ROA}=KV{a*sASkx?o`tDX4RiP{DQ4F&D8K_M+-{LD#-+DKo%I`;YcnUSJ zyB2?qdK8h)x(};p7*XfHIssLzhg#CssF8Q~7vP0q@iFFXyhQ$LRJ{S`T=~(ciOfQM zi(ZInaX;#-**(_CT%FFpEz?|L^~o5YUqDwTxrtujT^`BL6L_!}z~AQ={r-Lv>KV(kocJ zj>X%c%JsDPV2h9Yh4Zflr<0&(vjp{SUV-{;)?VC;M^P&<_@Y~x$*6KGQ8U_y+3_^$ zQ|=@3;o>E`hcq!evB`Sdau+)wLcQ|Xjh>oe!xdSKc}BYjV$67H=s1Af>}@vm$LMl zsFi4pno&2@Ovj=++Ky`HcT4|b>6xy&0n|lJxWDNeZW$9$=Xn$AQJhCLbO}}ACF%|L z0h3^&Yc4$}<|1AgHL$K&9fzSlZZD(%QCxQ`Qw}wuPDpv5H;8~{GRY-)t1$-geV7MN zp_cLsYF8(|;XY2A3thn|n3KMQz%OsAu04BkKHj zvW%WeAU*~)lSvkzhFYPy<~CFVXD$DR#qVJq(qEXR?zlJI9MlBvpk6?aQ3H8{{{Q}0 zq`U4f7{)~{Q5n<{)zoN0_&qza35+S7jZt`N3}mV z%nf7&lJE0o5zq@`6?VZ7*a_P_ax=YTK0@u4PpD7JM33DMqpeUA*oPW$DmlJ|(|kG>rb-t!!fS|NNhofEvhy@vyjA%hKDSI_!yRcz`(>HNcgq8SOz0=s2qU zUCe`F7Ek)Zl}nA<8`)lP{?$M+OQ>N5TA-eFSBsA~XPYZf$7?I9qx}{?iux9O&J6d` z#S39t(tDsz&rH-KUiXsouaR6PK@I(Zn#oht0RBdG6!%Z}F`XQ>0u4~Ry&Ee3l6f1| zUYNz-Tl_z)N_wnUuKlK{dYya()Nvon7>w#*oE2D%TGF+s-}@a!eIdDpdhx{n%MCOX zvl8!sn%Qhry~C(_H!S`as=p|&-HP~P6UahB9@J)Ofofm^>L-*Ps9hX}`gBY3#(ml~ zK&{kbRD&B(n{+#B1&&+#Rg3?I`Wf&Aw#Q0u{VU+}wi8eT2T||jpHWNy2-QL0JNJf* zg(??}>L3T!z!H`|&C=&$8PeCHUg>{Ye!TZ?C6c1r$%Tpa`CpKLI;x3!Ce2WrvIDB% zU~>d&iN~WJ(H>L>7f|)zTDteQizh_YPiyha7SC@MlRE!ptw0saXn=Zl%`H9vrw|{C zTEaLV-0$zYp#~7;A2;x9s16IDR;ak8S3?c3f#tVFt#lXkpa030F$-02p~cr>G2&ZM zEAyA7|BLz%3Ha!Kc#VLn7X!6&NiCigwOI?HHeqkepMa{r_@n*&znlb(c%8Wq)!`Y` zQeQ!J@C-G>511XlqRw-+f8Fb;d-X7GZevdj`alX12 zQ$ZgA9kcG1uoU$J#SPT%PWhjE1l@5b@y*x)+wki|HT(-|hS388{d=Pjs)ISGiT#9& z@f~U+GXews1Kx-_&c4S4G}DaX0{tJu-LVkyBd9M3pRp*$3m@qJY^Z_ytZ0L&usi0( zDX4**K&{X_)T7HEA<+Ly4n=)zkHmg>5!>qXze2=7{|aoz{AAomZMwvfTm$v68u2cu z5g$a&>|E6MjeF?-`#(9N26|6OsDh<2 zZ?r)Ff5mbDD*ggL_uHK>xqxS_t)SKZ=@hoS1?BZ%`Rg11M*9Le-mM zZbScn|K|z;eQG_kjMT9-GJbW6TFPeF1DBzeIDTxmLZwh&)rO%~W(lUp`)0&AuH7uC z3A94(wON=JPohtO=LEEwV#N*gZ@Ma|1{a}5d>1t!FP`f#Icn((qXyIpRemaJ1umgx z{up&iqQ`f8B{ynCYoSif?D&B`f5A&6G$P?|RK=PJTu1#-A4;>ZCLTd`5IT_fi%Nz z#D`e?Pt=OUNE+yW(FCL7HBkfUiWqE6m%lJop#M*|!w0#6HbAXVf7H@X!o0W>HGt=+Jrh24 zp#P2QOKXALr~;)?FP_GzrP^faH&J`!4QjyI(**i|*sOsOiLXXYU=wNuj-XcL5o$nz zX`P8tn=l(v&gV5FphqwgwdDJ;IYv$A2GR-jLOO^V;6L~i#!2tumr)%(N6jo!1~Nuz)`QPxu4;u!uT71u_PDL$E2<#ye)NOs;`3*qrp`I1$4KyBEte zj79tgYDJ!yuPpswdyj7K$m z3AOp|q6U~Gr`zS_Q5`fyb2~Km+r;M;0A5fh4HSmJx$67itA+p;oXPhST{UOF$!^ zfSSoU)YANm8c>V^uE7+jB@aP$SQ6DxWz+;(Tf9AL?+imd!bzwJY_#+psDT`j^zYrV zgpX!|g6S$Zc_`TnTy?>>t!M6J*Ya}%naJ(hpmJcnArUoHNq zDCb`dzO;mQ<|ouS4lL$YBoeAzG&8Q5#0)YsqB_WiI#nf6OWwfp+hGv#uBZV|_7TuX z=bEc5W4n3KJc$~>CDf+8Vd+mWCh<3xA5h%oM@Ds!*i2()G4q+e5*Dar);61>_CkBq z06U`wFu>wNQO|fH&ch9u6w8-zwnROmAI$ldz8ABQeg*m1_jv&&1O0!xT>vwY(GG)f z3aY`asF|EY&GZ`T_=KUBI-r!>EAdeS%#2#0oE9&Mnm`3huVd+LFs9CbXG<7l1%{(K zoMtXCSD9N-E3*&vA#w-s)UI!Usy_t%KmQL`fP`_Vf>SKM z1U2&27T;m+M{Uld7y(bB>YX?5pgMSo8pvx@$DdFyte`Tkzk=xh`M-oElt)#lYVrE$ zKYplZ-O2LDV*%nbEd4xc0x!(B=D%h@S(hIfHSkzw{IZ;XJ<}wXkO>vfidwoNWa|xXDFMPvb_A;s;>7BnYw(~(!$lL6rFo1 z4P4}&%iV-~Hx0xmeXOhE|EJ!Sow*m0-qt2?+456i&*=e7^(SjN8zlx1Zfzw;Fyva) z)K!bLye{air?>B~2K3y;rnimqsmLGn-4dv59Llu9fmU~}euw+}YYpkuY4F>1kZ>6yuPB#}4lY?nd0b8WXUdYFqVh}|%p_c3ovt9=XAK=Sb+F=-UXgNRxo6Yn1j{Q$d&{|tQ9n2CryRe! z_O27}?IY5i#1B*m#tp=EH6h%<1{RsHUW)H%@USW?YEfB#mN zwD$~t59KPURjx+lr6!)8@Mgj%7(f!-WF7CO{6fP0NY503=RbhRMr-^GiMskYybt8P zk1o5h`g_*9+$4c1Cd3jR&O^JFf!w3*iNSe!umBAdw!!ky@71(v1G zw<{6lcGK`J68_-+jr`5Tzg;JYf4kBV-l5Mb{fw$>KMfVM0yF4HAM2^{4rw>6W0fmy z4R$8IDT8QB-Z~pZ70ZiCdJS$}WhmE`@NDvC5wB+HGc-B+_x~J`5YN-dV+!}8!5pY7 zzzngKP+CnISb&8suQ>7b#IsoE8);{T4QMW9_{qS_N?srC`jj0&S_Rr0jClh|xW>JR zdmIVXZKk&_eULr12{P|KIhmNIWz3Q(#>Dq@OYiP%r}tUnrP| ziu<^)ala$2AFk!r72O(+N5$5Z{dUbEkks<>k(ZXv;&6Ag0{JMr#mbMe^}J197t&6I z)06w|8c28h`pO)cC&tG*r4lfl3tCwMd05taw!_j^^f1R=ffM`&-ajmDJ_#fGxADs*P_55)<9M4ZjF4T(s3Hl zRf_bgmaceW(vNaKp{=TvYscMz^kCYX%3Y1JBXJUGg~)sF+V^>Ltn->A>Uv>uMYCGk zWYTU@;ibjb`AfQg?4#431P5ST^6ODS1YP%!JfwNuB0arW*xY(ea<()!{dA{@)9!jkuJ5 zhfzo?%>dTvzcPN13KK|ZNSHs|^1hPM$~yR)!j-7Bkn|DOXgi!t`gY3cib9^QYTS*u zD_eXJZ6xD9N_-yavnbCWjCz$wdrce5&{vVhb^Sx61_k(4um37X!3q>AV~s^2zdHG8 zF_ES5hn-#;%6G%m)Vj&Noc7vsU!~k*;`6EV(8>=a?fWZC=YIkP4wLZ~lhW8&?jI=C z$OiTU@jT>5BR+tJE;Fc(#Q7bw{~Cw<^$q`TMe30L1MS2lKAK#et~R9Us!zEkglD*@ zSC)3h==l$}0+T3Eg79OD|AGHl;YOCG=ny(cOb3-2&{pbPqoKy6eWA<~@{!t0l-owU1Z9U(_9AJc3F}&@Z;p2g>SLYfqG4U99bRoKvyAfh ztW0mpEG54bZ5F_il=&T#;BHB|#Dw*`<@D&=K!rO*bVVjX*K=!ZFyT1XX&Fmv&P>Mn zOSyksrVhXO^y+ZuxAgVYId5$}!55@YXOMMB&%?kb(#A5g9tv=!W41hnc@O~u! zGWS@@H_-FfwUWpw?w;ROUQB0asHE#96_3)8uK8Bxuo;d#T_My@NSVE)@1yPl?&Ovi znY?)1%g8?|T@|mMp1-a&WYnd?UNTd-B=={zq+jArzMGBG4ier%TSqC|m$XR%xzC#BWh<4-I$!uEFTk ziAdgSSIlcfJ5eYzk}}!2-x1gKnR^uBy9_G78@$h(Zw;L#V+4)-O~yRJOK7w{jp*9J zU5dP$+_@;9j=L)1+uRQ++nhQ-y9T{0qNcPk2Sz|Ppx8k$1c z7Sy?qW5~Nr-cUMdL3koIC9fTMx?WLd41Tt{w`pJBOv11!_kwS~4Lm_)2Mxuck)7NP ziHGNYK|{T0pt3cPkj8ZtN3{wtg4cK|lX{Pc5dxeHzG0 zg|nnTrjb?LVT8+(e%u-yO{EU1$W_KVPD{Kj@y9rYLCq%Ijl8MUD@eT)D*WAbpKxQ! z^`wmdJ*i&_A0ROYiN~xXm2X0P360DkKPvHpk8BYB5#wf=3K1~j0nABnoEkkQ`K3es^M;y-bJyEc&a(jsRl zSChePB&|O6M_?;l$K91Wp>(e65%D>Mm*5`CPsEexpMNWBJPXk*B(9@id(uAJAg0jh zcJ5Fr#pnK;^lLbbGKslcQa+#B;(9|Kf1BBV-6i~$_Lkr-QgYHpRr2)v^{d?5Xd}7S zKRg-1s4G1c_R;7atVRJ{7yYi$hlHO{@spKN-K~TVQ1&f#zg=l4 z)7RoZVqM}Rt(|{}zj9&yZ7_bO;XX#qon&OA;CaFqX!JVv!eiv?%79PF*EQH?w$^7Ce!$HYjh}`W+j}AJ1hC&X>=TSLgM9V zAlS;O!T#3qb89#sb-!IbX!AeP$6A?h=_x65gtV=C8~sOWUJ5Se*7Y0y!2K%~Q*ht3 z&TbNpM#X5b;4+;N-B{3@HI$%oTqbT?7@<0Epbk>c; zb~b>16w=j*3Y%$|zd`KnC!ELza>-oniuwNxUBS$>F@w66L}d)i}hU@<^4&$pJ?n4%ABRa%ao}?xE`jXYz6YV zQ05PAUH@VT`3cDjDogk@6=PDqHFo4q zNt&*;luz@m9O)A&QY4|4jmx%vobyrX(2jMK#|AG7i_=sEA4$@cXH>@uR z^rGT$5;OU;c;@(;^zl^cWEFgbQxMLNWhozza9qlzviuUHt>ONU0sKOlL)4E+{72%e z3D04o$%(HdoQ8XWzaHy9okpf`UnlWjDjvbQ+`5_)FGK@Zaiev#i}=5UThQ1r%C#h( zmUv-0*iN08+>=P#Njx`Yb`aKeiSVBmR{R8QcG1sCE69jKLUtNSs~oO>DVWa+pL0oG zcq-`nk2-s8FsCUqhx%hk)76{waHQ3-vUABB&i(CrYvopvUz^)EiW%%7aSt`wJ?`h+zmlGt{O*+RXziRcS79F;#3KEi z^cx9#skEF5A5m8T4d_}!1KIFr{1Ma8(O))z<5uPlX@$Ahkbj7B2Wao5l_AN0#ind6 zI(}Y$%^PMo2Jx#ke1Pz`YZ@H}P_GLK(=0y{ z`A4kYaGXzGYsysrRtc|BCI)rqk*&tej(z|$oqDk(tC9s2_qOpb}HnhKvYJ# z*a~eV97F@nNN-5~8q(L2HiqzC(tA_CG2w65Zqjbh)^Fc+vYhg@sXv=?f0BNZ!Z9hM z%NI&wZVL3~eow+cEcso7zv98hJni{V6k(xUOR4O`?2u(r%IWt4sF(^Eduk zh5HxEOeHUf`or+M%jeA`QC9{Ud`}~pxFc}awLyfC|CYQ{)}bry{@I+yT3Ca(siW&Y z<(^UJN2_0vw58U^Z{!7#-kh|&{(7wc&m^28vX2HH;T7(h6i8^5bl83*ts=Ls)3~0r z5W@E;Gah>~!$Ovy(=2WST1k8t<+D*Hxuv}!JfHMhJ_6OgpBdrE-^HU7&PfNqaF3?5 ziZ-a0G+2bjrqf6mcRKQ~6CX%>k+B>3A4u2rhC1s>yG^`2;TeR#UB32I(DjMTRCIQV z0;{=?QD}tA^8UhK$lFGvHLX!)U7}19(jJkwn>rUz*Lc#x(QbRfL#+HzOio%9@^lq* zgYfZx&g6H8Hli5TfC^L~y$FSWB3zn#GkMP}zZactrm=~X3H+|kbjrsdJpyTGxC>LS zCuMbYBVE@f>gei>KkIwdN+KPJWV8a?t-%ANO(tz4cSIT~N8<|^=+FM@?jJQM6NmC` zNdL>~cc<({;`u1QlJIlVj}tFRm0w8HrH@nprSrdu%q=90r=d^k$TB~uLE^!rr>Bgr zB{WdpI=X_BNxw*b4a|t^xs#Ayg0hQA8%xA4z)^NxNm~Nvjk1N{11-KU?DO z7$f}lXH&mMNYTB0i(YMldj)0c*0)X1pbouz1@-RGrA<)h4qZC*4xTnA*|s^pnA7vF zO1^!-s(n^={uL zs8^ewYO__hKAl?!b?w$WsAZd=o^4vRYTu@Hw(UuGolF$IONU;)w%<8lH)0Hbe$O^t z7)9$s)3aXrGiuikz1nx^+U}2`tF|Y;I%itsHa%O0uhzXy*WH`i1uTe|#>V~Xz}T?e z+n($i6*gwyquINj&ff8K?v${xyIvg_H@ijGfTX+m$Mu+L9xWL6aL>?(d)7T(yz$ZW zi4PAhc(ieO*n%}r4$ptGbi#w7!@XH^0}|{G{UIPh?22J4wm#Xhl9vD9ENN3E!zRyq zv}^3QLh~NYUh-)B%qNEzJ({#KZ0wdt3nqq*Um7-d4Mlf1ni#Mwam27u+n>(fxcl?U zfSeKIFIX2gcFEJZD<01q`DoUdhx-}nyxAce0=~qYxIJvk=&(%_9*v#Cq<3f77*Kpx cf=A<~haDK|g-zV;g-ux>HhNUp#yQ^q0djxe0RR91 delta 37673 zcmZAA1#}f>yN2OOAh=5i9s&e+clYA%ZUu@Jmkkv6;!cZ8akt_Q#l5%`iWO;bIQO%^ zmw&O&oHe~Z_nEyD;6FRYM13_ps_#a;h*LeTi;+Ap8J@`NdC8-CUjI%?^}K(6_Pm1l z0`p+zNuHMrTVQ3JhM{;5(__$N&r5_^QSFsQm2Zh*I2~1PJ0|fwpLdr)Q4&781h2>x z&kH7A4^^QvX2eOD0(Y5zVmR>+m>I*EMh2{kD&GfHe-UZ|hb=#Fn&-tJo*9Gb-zz{M zCJEIrF*ZSsyf?}n(o>efEw5sjEn10?HsW9d1U6^18hY9 zUcd~`YmQAY828|Jc*)Y!%=El;#D`-VT#fPZ9BRgYVKIz5%XM5Gvk~u&s<#YP?=)&< z{>3;LI-B*^%ySS(jKxqhuaC*Gr#S@^5?_xT6YmJ7##6WfU!exDbdKxrFU&(c_FT6@ zWw0UfC0Gap=XqXQEIN<%*PgZ_K^^~uiSQRx`c|xfm#_n-n(uj~aU2f7vzQdC{o;A~ zu_NZf#aJD$;BL(HtE=}IvlGw0fCGxn7x-Moi6pR!-cgK)Ef>0x_QZ0;*JF8nkLsw@ zA~&%9SdjQ3Y=QxcUA!4`-n`kU3FKHpo7fMvB{#7uM)oZwlR#a}gro2SZbCJ@Zkb!k zC)kI0*mAeGb1)t86BrF&qYm2_GwuqvRjJL4=-+CK7sJSu_mw4}C9i@BunlVI`=PdE z7HWyNU`jk^>90^{CeBJ%E+guUltZ17#;8Nu3L{`|jE4PDPs0d|rRRUT3wTS+O{kF_ z!033wyo?&)J*1-d4%JbV-?%Y0YK9@Gj>0WH2Wp@NQT1zKRBVsY_563Y3?FLmr(g_R ziXpfW^*EixEcgl4K&Dl$<2ScCy9PU>4%d&U0gXhJn}S-AMHmP7pt2+e+;w zM8%VDVEr}1)Fi0m^r)HU#851PIk1VvCt^n8>#z#`iK>@rqx-PQgF2M;Py=g<@v#G{ zV;`#H5tctr3EKOas3o0?8u2HmiNGD8$y>_zx*$GUrf_u#4sDWHWReXS2k!Ki;5qG&I zPl{Tx45$GX!em$xb=cZsChU!x`68@}>riJQ;CI$v6*B+s8mNHviPytWT#wq@bEpPy zqqgKFs^g&D?oE~mHM0V!0hdA@>Po2kHBbX+hT57=s58~aM?e+FTgD93OctS*dIPF~ z!x(}WPy=~}D)$9dF4i8`a2Tq5R@6!r#^hKNHL$Me?-*6iH=clIG6(f0T#ZR^18Ssy zp!V=8D*ZlcX5L=Us{@g-Ha0=k--zm98|K14P+J$c&!vZ8IPomV7W=$f1fr183e|8Y zEP+3|0^VlSOb(%5OxIB>5U}5^Ks?k0QlVy)3w5|kpaxhURemkb!@cO=iUX?eqeB7( z$moxn;bzp#&tP@Djv7F=gRXxDl-#b7+9i}+qI?9MCiI>30*c>&3_NcAsi;-{`royqPa;s4tZpKP@097u|QMXcw zP+Jj>Dqk3VsR@)OFag_PRD6r-Fz}d*$44!3a_olLure;dDEJSm!FQ;o4LI(;HOIne z#Ot8an`1=$0n1?bx_LklmwRL?^10RE0!Fi}H_AMo#z1xZ!(H_e1%m7-!s4XT*lY3!qkRs->^OjKp^$1NV7<5r{*=3sk|tv#w$i)JS_`JM>{e ze26+Lsn5BYHpSS)Tcg_Pftt{8b3B$KJ`J@MH&7F}kN)rfVdvd1AhMzgbVBXzkEkW~ zVSF5eYIr_o!KJ7byMWrdtC$WSq6Qx4f-^B@ARdM~Yu{mJY>k=p{7)hf7k@|X-Dy;V z7g002hY9dC#=@up(&&0!eWVY6Xs? zMtBxAurF8v<6h=B7T6GVHnw6uyo_3jI9J??B}A=YDx8CvQ3E`R@$d|W;k_&Dzh)Hq zsvAHsh7-?;!?8Z*!ds|;CAj9!KvGn^4yvQZsFiDH@gGoI*9Q~gFiecIQ7gI$zr%yq zSbyzpygyxqaMa%A#9%ChWv~XS!x@+e=c8u4#oUSNa4+g{K8c#xRn&|hp_cxmrANB% zwm6}WfC{EYf5)hq6hiG;35m9f!QW6z`!{N)FEJ3K+;A%s9Xk^bMlJbp z)WDac|8TFigzc8F8#R#Q=6Te}uVV=Qg<5j&rrX=-*n;RX%!JWzxu+l><{{n`wIWkd zE4cvm^gKic?(>3gyAh{Ab(9KgV$sK+h-UH76%k12?^LT$lMsDVz#(m2=RcTg+y z1k2$Y)If{fa|5r58b}+|VH|^n=-*pRAQj$5%`n1!w>QD46$ry*mdiDV|f^p;ukEAN&j-M@U_RC=|tc5B+(nml`JRbG@EwE^%Sf@4dejk#W7B%vW7!wQQLac~!@ENMZFQ}O$c;TLoWT^K-5iEy|P-kKh>ceU+mc=7j z9%H|B@0oh&(~@@}5F3YB#w3hIe6gi(#JI!{SpG%SN<2cH^8Zk$`HQ6oy>jivL!F5* zi)TQUFMwKslCM~QEoEgA)L>oI7PLaGz(CYY##;UiR0E4q4Xj43%r;9uX6ffp6S{#~ z*=Lsi3ImCMMolo_HS4dXjPshWUl@X+cnS5&eTy1c!hhXi48v^13!z@w9WWh^L$$LB z)8j7G(m%i~_!%|e%>TJ|@}csp`3NK@&<<5_II81~mVO4)5Pyz3ObOn&nN>xVYl>>9 zzs09uDDia|hG$U&`xlGhCya+h-ny0aRU;5eLVb*neNjt3-r}=R16+-n@C0h+Z&6E_ z&Tk$19i)lYDRkD2dv-W~lm|Py_CP+KQp*|NcLLfc9)QCd31%=l3cW#T%Fx zlYev#)j}PjMyQo)YUv%!?x-d1hc$6L=EFPK29tbpD>fLj>iJ(lKzn=!HRAs;7e@H( zzNO~Fs>Fw41w4;MF~t|R$Bj{^d=O^GVW`J-GwSI$f?9zqs0rRiJ+5!ir|6~%C@h?;2EfB^UX ze;^4ueB)4i^Q-wAs^cxFne4&jcm_4&=jLlvgYQrsMGADrL+yDAOomx7C04Zf_kq3u z|ChoMB&fl4ma!Q#5I=`{L486s6gfhGf9Zlz9VJ6;O?p(h-dF&Kpa#AZ6X8J&#p{?J zKcjzTd=YJF&__l^)JTtE68sA_;=mxc#9^o{X^dL2))w!B>Ts~dN2BUbLapd3)Bv|y z{yx-J`i>D$#jECB3?cpmwd6sOTm!+VfuuqWpakj=RY0voRn*=$M9sJbYDN2^o(3P* zz)7fq+()+3=RLQCn2`hgZ>U75_ds3L$Xla2?1CClZ)}XCP>1y|)J#6%2#guU4P+|n zDVT$*w;DBo-PjD{MGfF5Bi6h-0X1~je21E8>}YOpvtdQzJ}imHPy>n?J;47)ONd&5 z9H#h+OGHR_G| z0kzc0W4LnJQ7e-V3u8I#k3&)I2gKye=~Txfpo*zbE0G(uM-@>W*1{Cn5H+B_sG0tR zn$alKp`Bv!b*LHc!~}Q@)y_>+{Rfu+JSNY-fA1_KW-NDTf>9Ndq6U;5Rjw@RIj@6S z;+Cit>xFs&`A{8gM@?+6c^dV&-9!!SKh)WX7@Ox`GY^jKDr7))lpobmc}uU2>Zlc} zfsUvp?TdME3ueKmm=%-8aZgc23@6?abw);`o{DJ}pY0={=X5D*SC$s1A#umcAyY z!*&>k6Hyg5U+_n&@M{JbwYf zu7gCV$0#joL5%*JW3KbfGlPn)Cv_r9mZ;AW7JZAk4dpRYM>KP zD?82nB?-^JX0(EY9Jt;x?x89?L!It_QRUvD9?yWJ?$E_WEoCOu<5&PSp`NHM7>}yI z05zZ`sQPPA^>!!a`B%b867&YUj#|R^s1=ExEWrPZg*d2FUI=qyZPXW$k*Mc=3F;7E zu=Hrj-TNRt>TJ|Ot>6GGiwiJ6KJpQ$Kp-rI8&O9rM7%Gm!Of^8e2l6PIi-siHyfb_ z(i>HN8fpcOV9IrI3YSK`uzF%?^!-MlE`b-Q(_A4{fHwt4U_(q67U2K(+8g!! zuEkn-5koOkYB$60Q1!Z_zCT1st@gvOOP=PwReY6 zTX7B5@e?eA@xooh^-v8DK|Lk=P@e&JP#q;t=brx-SWWq;t%{%CeMKvY#q{~#pMV~> zov4}Jz*3kigDcnz(-B{X+JY;nGY~JMn@Jhe;r#`h;aT+8&*Z)(_dd9h9ww>RT(5%K+)58Gu8@W$dVSRS)vb2ILV8Hi6qb+89h<4sJD5wg2O zml>5`9W}5nsB#<8r;N)4^v&jt60l$n*YI}KV|5R8m{R3*OIsPWC6mmpsDa)|@Q`2X;!AnJSlLd=fW zu^h%K;AUC}D-xfAdcJR>&PaGcSFb*5&nIIsJcTtdwy#it|1T1?K<(K&9EDd=187y) zjdTd=^!|!^QJu!j_!PB5Ns73ws)+h@8-aSx=b{enIn!m3hhLF@i>Pne-rii-9y!jUey^NwKYjCo*N?(FI<)9U+?%*Bz^J&*_U81Mi_ae1SStpHQbgUNzT2dQ`(DPy;QGYQLu03bph-P+K^^8qdFG zyq5$Wk~65s~XAw@oTttnqn2= zt57e#k3IsLS@D|g1yULHIL$!Kd_St;GpGSv#WHvc)lqmY_YEf#>a=G=mFt9B$?m9? z>WOM^3~EJYqE^zkf`FEAGseRcs0uexEAtv-VZ_?5VtiD38Z$Slq0*=hs-fyPL2W^I zRQ-Xdl^cgTr1O!9`Ml)>B9O2i^)BCxdj6kUJZ~NMeV`MjBYiOHGhjKE#)nuDv($C< zdSfr*dr=)1sOMI=JZfcXqbAT0Vtqck>YHto(the-5>Uw=Dk&>MXoQmHXhcfY;0| zNf4@|=&0vDKB_`8OHYlem-cxYOs&BA`8A zjp}GU>Tv8p4QMaw&>Y8k_z1&rWDB?FD^c(AGv+HyLp)(i_pUF9I<&1YHBK-$U{XE* zmk8+d{S~U?=&js9;-W^H1U2)lsF@ZV)IiRm4#zcA{sYv=AEQ>}1!^UN+PJL?M%7D#dRoFzGcJs({~fA+ zb=1n$HJh~I`B%l(B&fkosBbOic~+OpgaK3qC`gwPfGB$2Yf+KmigeqeeKwGNz(V>uRiwXHl=z&DR6~7GdpQa9A+rGWxa~!4 z*%U?1Gxv4Ah91qh`Jh zwIY{MGkRgh?B>!lpti6i>IGE|_hEM|jd{Df7g0adPt{AX4gGs}3Fu?9;*Tz4F>255 zpgIif5#WE9Cq?aXVN`lmERXH52d=~Hn69V$k*yx8{619r1=LxK)XTk3ilgrY2@?n? zqfu}7dw^-ECA)%3PteEx08$0j;A^aak^8!tRmXC~r&;_479*azpL;r5Vl(2iuq1xK zZCJEF&%X-3?H}L`!u$i=%(kIsb{6$`B^~INt_D6KJ^;(&_dLFu**esBzB{OuX)wqg z((b4i*;Lfi@{73<^&&blhzbgvB0+n7(J~&GPf?G{Yt+o64R#+!$<0EjAIIyXUR*sf zG5&1nD=qy9s{OmD{$8Qleebh`I78gwNrZX|(xM*2f~bzaL%p+`qGr_5@_U)1Py?84 z@y)0XkD%&ZMzwR_;%`k~&`<6($1}5{DpWMM1GV;y$mcWz;bnqn_(l7T;$cMLl+>%_pdVMj7Tzh{_MMcu|X2 zLcOrsnxo8>m{6bpCoSPF>a+(95Ab$jG1OuDgmp1^gd5lon1=WX)E>S-%`EarH;`DU zcv94ggkdOFw)7uR1Mi_Y{d+?!VU#%ywX_RW0QaHJ!coh=X6X+t{W1J&U&)EU`i@zdzjo9Q|Mbrd$*?NtU;JeOGz)j$ce3Tl82QIBU|)Q8nN)Mv;A ztd3t$?NlG*wxAv=-WS#0;4wV^8sT`$m}f3VrT=E}ofhAZn%Oxlf)7y7b(*oR;r!_T zMuZVauY`J9s-g~E1JvW%&eDgC<@wi$Cz7D0*=_|cpho%mHwU4N5%cY^zn$cr6`4@0HDM0K2K zqB9Gs;Zm3!8<@RO1DS?esfDO|8&IEqN0Fz)=SBM2y~A^$p3@enibKtxQA<3};>%DC zZ9+AC-14uXf2GVPmjB9(Fv*pVk7_@)U!K401j>+51l7?`sD{R&1~kRun^9Y|3w0Jw zpV`0HL!!I3el%n!>F03 zM3v8mT9E>%dQ~mIgW1m^l5&B~~OHA4-!3u-_EP>Ixrp1>`=lR#0Y_nxtKy`cv^;o_|eH=%e;eHNCjOr)_ zD!+hP2K5wFN6oAqw!zM*Z^0KWz3@!;UMPin3L5(eXlZAmI$nkPMzi1IuTc#~o8^p) zdS!>8$~Q(G#_p)C9E)0+_2vOo`xj9w^$4{k@30yA63%u@+7kzp@RP-Z=D75DsPAkk zQ605FHPjDl;TY8SgIlPrdy9uLXs(N&M16W*MSa!FInVv6SU02{pSOX48rqL~+(PEN z?|ucbCGnq7EASU;CeKha5BSBUCqfMrzV0i_S>w4cJrcm?(Dzm0ky{DU#* z-z&Y)HCP=r)8^>^UXS_-W*z3ko2XZ8qDAiOc^)iIybEeT>rgY?YyM&B*DU_ne2Z}? z7qpn?Umpg+1Y}0k3KT`ns1~NgwwMz~pgP!&Dt8z);OnTfaSt_+PpBEkT;lQ*n#nMX z^wg-WF1v*1Uk$V)LBHYXjCt{QRQkWDCHsi#IQmj&28-~Zne(8%JfaUJD1%V0;+YoN}?Zd5~OQQzyYpk^L% zt@{;C64dkG4)vLG6SWebF#={==LVDu)lMm#spr3s>rEYDFqx z9qfd9S`MHZ{DAsw2;AVdsvK(Ns-yCopjN82*#mt#RKp0!dFB>uK>ReSLZ*%G)2n8iw^dMQr=6uQLk)0^#m|_RQ3JVYJ~7{IbtR;uPZ5u_-=4z4^*+bt}{!^|R&}9|4X0AZjnqq7F^eZEmIo zQHQ4lYQ$x*CRVlhLez?^LT%wj^CaqX{sF4}!0qnOm}6r&@kXfjd_NJ;Xq3bvw_ z@D}QH$J*h}KpIqoxl!rWPy=p*I;?Y1Te%a}@F~iLxpK8phq42z;eHs3Lr?=;h}Cg7HpIBU2Y5@c6Y6Kb1iRg# z&4Fq3^M6+Y`T{b|pTKXqQ4Po0<7Siy70-xSF$Zc%n^}G*iw`o#p;l%VYM^H<{Whwd zXQ&DPtGJ&3=zCp*@lXX)qV_!8;u$SJhglT0MU_x9?t@zLspfpFNPIb##n-4aRcN34 z1x80KPW%}9^t?vj?>f$c8gXva3`?W-w7SJxnO#w5WuV2Epz3WvO<=#JA45Gwmn{9R z`M3FEzkUCIOM-qt2s+?q76;W(QPim}gIcmCmi{BE!+w@O2DM^~FeNTSwRglkXZbf! z?cPC6@X-OETbln!h)hDdgKlQoPzCCmtxz3ywfJDvfX1U{xCr$^T8rBId#L(J54jH0 zo7qt9II#06AeKf>Kvzd{`DfMOo9f|169#y1%9>oF4V{6P1H&yKJ7j$a-!e*yL5`g_zHGvOK6eks(}wm!r2uchfng1+^RM2+kqYCyNG;A2$70cTx$T-1z` zq6U-|HPdpaj=G`R`Nh(ATKZq82_`(}+R5j$KnYYvCDilW3AGhtQ4LK*4d^%28*Vcu z#*3Ez59TEP9yPEm=iT3WEspxQ{TcmRf%=pUy5J_{%Sb>K3ZiCG+2U<5Ch*EGHS+m zQE$30s1fJ7>>8?v+Vd8ujz^p4P-h_7757GMfhxBEHQ-~YSMwRvp^b7?ThH^CoPY{s zL}lc#cv;j;DqFldYK7{VT~TLewB=8?_&lsl`bsn4ntQ+0MXkgf)C*_{CeZW0&Jqq` z4&rA}OBCTxw}io{j>1s`&1DueOQ4pzJn9=xJxlLl_Q$xS|77v0<{b2?;e`aW9}}nf-vOFwh)k>0?ndo`c%Ub*RU2C#w8K^E#@%dlr9z>i8|{Y(@9o zcE31`jg?6VM>X&xYG(aV4a`D)dM&m1->7nL%+IJj4!Yz1hI1m+3id%wWCG5{`KWq@ z?z(~aN)k|k+E@)+V<+5<9Wc#3H`9scV$@b`$4Yn+>tNV@H-SE=0Ut&^e&gdIMbto|{pH#T zMgQ}kj)30%xp6RdMHPJIFTjst4_$}Bs3p#TdNUS64X6U@y-*D`f%caEBdVQ#m=S+Q zeM;^`eZe`7{^$P^0X6gl)xax^kDtwWk6d~iPwYSLP8!i4j zRw4ZlRQt)F+Vh|Bsp~j5Dx(mpgYu|`o1m7o9VWuTs1L1~s29&U)IeiAbD#g|QHQq< zs@_0Uz3CQTgPQ0O9|0}NDa?$oP=_V-xoe;j>Swp^s8hTMi{WL|r(MWDZoo}Y4R$~s z(r%~~7;5QLEIu0>lfDw$p)cwSH^XkI2Ku93$v>fHv>3G_dr@z=KTzc!qB?kv)$xm^ zSAXf!>tSiq+o4|Rt5EgMqE_OHi~GD61hhnNQ60s7f<+u|2c_3v2xk;VV>%jfSWONjW|H4q(DAp|wBlorpA6Nwi?E#YaLiCO=3 z12}>@D^F4N-=J3Lv!%!S&$Sm>O*7? zM#clEdM8jTcg5mQP>1y$YUy*maru?d|L^~s5YUKPphn!@?1SoX6l$p_qdHiQD!&=C z;V#st;ZxN2g21=#5N1VvUnq{+vi6of9d($OzvcPY=lOL@_<(vov%PcA`9Rcnyd9{m zi1^<9#iQh?Ps6qtjw?_zJcD}dqJMCQIG0%)_1@@(I@B9cG1hgm5@gYW!66pVbs^ zz7lh)9B#z0Xs)A6ID+^))Y%yv-3|CO>KoJp)Bu8FI5VPNa8>>K_`D~e8BRtm(Q+$r z3pKF7m~JUkU{~VJQA>OdwL$^0Tt~%GE7KIy;(YTUs@=z^353OVD_t8?)4w-d0bGGv z!aq=lE_xi-U}MyX=b{F*8#S|QsHK088cfjs>!AGbDJ0@`LtVIpz0_v%XkTB5y3(4H5 z74o6l+nq4b{qKMNO@fvvG}xWax~Lb)Le!p~Ld`fuqCo%unq3i8d=+X%PM}^i4=o-y z#0?}1Y9KYtL8!-XHEQJ!hxlB_&q>e{hbIp7zdFlfGvWk0Qv0jd9?}TCt;ZR zJL>Uyg99;nTDP=w%onHz%7(iEw!m@3_oH4c)zi5ZosN-+FEv+N`X-~u^9a5p{S-#SqZtDIpN8jA@kbaDU!zv$9jc#@ zjP#@DKP>?*QD!Az8Pvz_cc>2QpiXfc%b$XEiO)tg^a@qZ%jDv5P_P)PPQ-CUOha@!#eP ztW5lEW}bgFP&P}T|A)xg=1VL~dWEd6;fYv~_*~QgFQZO*q-?H(#HbEZqqZs|YRMa7 z1Z;--VYQW|uSE@PQ#PMls@){0!3(IbNDoopXuRxh&k~|$oZGC1TGEcFr5IG+RFzSCSKVxGc111mU~?p9BtF67+ff7Ei#iL( zQ4_d~>gWN6;tSLY#LMF!xX;TxS8I2e!t?s1B>=ci;8uq24ExP!oBI3HAJcPypi=a7&sFHIo{sk=H@x_ptOas3o0X z@mZ)-KMz&@6zcJPX7S*HEG=+g{$63|F*qh|IHHRBJcj-wO`^#8^p1u8uw zs(e1w*Y~0pZ-m;CmS!hZ`CgVk)EtBAXHp@ae>Jq&GJZ2RnA=g$@m|!59J2Id<{9&{ zdDDD=>fkBrsqzZDB@aRM7mlHrr7+LGMqGsijkKQG8kOG7>~9W7H82r%D5qQcQjA4> zo#pSb{KJ-i$-HeoHvjcm;ENfxi0e4MnH)9qbf^JlLJc6l#fzc#{5zb59WV(-D(Xyy z+M>c{1559XnMwCeCZMlgdoU}$L4B19FXoo0DyqRQs1+H5n(0*3bG!(()O%28ZUT`}=?Rc>J}(UcHJHgIcm=IM2~>yG&4y-cvomUC`k+2T24Dc5MYVSx zRsSw(0#8vLM=9YR>ky2f-~SgOpb?ia%cBZbwRlt1(zmgAce5|*a1O>G9FD3t)|`VH z;BTmbtVKO-+flFVo9O@if2#lqU(84)U4@va^hBs%7^Xn&bw;@iMyQ6GS-drBrtMK%af(7q zkWX{})r8S?c@R^SKhNcvdHq@$+~rz|fO z726Yj&7H?ODnpqQHnZ`T_L8(Eg#V#jSHk+5wwyMjQeRs*l=A-()+%W${eS-}8ilja z*$-rVy*60GuP}-YDme{bCOnMt&$wq0?}vFw>qD525&u=6cKC4gUSJ45z#l26>u1VU z!MW7wkNW)a|7({@6xzrjhH~p#NQDDbu1|%U$S=G6*Jk2{xpi%_MqP}T5a}DgM$Gz@ zNk*HaxKmsC`?S}K_{WI!U!F=QDa>!%{Z}CI)C?w&_#slBa<8&MJtJI}yMdJ*Xm+&x z(=@!1`fG?!vNWC0>a?e8F=^|l^TP6SMP&Y?s8ES}Aop_$&!^y88oFdm-hn(LqG+Q10BM4WW~Wl+8(eEPlOmQ1&>tk9#S3^|k&yE#3nXzFvQm zk%qfB1L{R%VT7a8;7ZCRB5f6S8`8gCX)XMOg!kMHXzLHkHlti5>--CCbf+9Yqj;N0 z*Hs$*``?(vTh>T%3hKH|+9C?P|E8l;45AMCS-wdtPMIO3{Ya;S2v>8}z3tThp7OeU zq?aL|kCy*kE6IDT_iua>e9T3f>jJ4p4ugOhsaM%cr8vPe}a`& zc3cJ+owRW_&}xL=Gstd~tz-SCdlcfLSg5F#k*nILb6COr+|Nh6c!dA|k zLL-f+IEnN%6l`r3mA{X?i^xyg-bosmMm!##u))M9yuk($Z0#N=Zy;?Hpv{id{h2bq zaF4Y9y@OOJN9K4Et5c~mgjbuh?0|IN(5mYGK7v)ot7n{5rjb*y}52C4g^{!HPJo&u|KStjt0*lDh7l}?}22*$>@ie42RGeE^E7E3g z&nCaOOY-K)t1x+~h?imjg{bp@@Eq(+JRA2|$|bY5RDOr6H#t$yn7(b+hSGKI z0z#2JE;vEXVrhu-jIE9YCUQ5U?LIaa2 zlZU+8xP$m$3hbnfu9WSGBdpEAT3Z?zPQ@C^EaL7z27Mnk;+M^ z5SjFQ)=(M3C6(ujdQS;lv%LAF2U=L!8PpTkepBIrHo;+pFVIg1{La#R%NSt+8aQYP z`N-U1vpPWGyfoC^8f!$}Zp-^Dw6K04w*5cyZc^NE<6j|ATNL z%Ii81iTz(qpgom8aQ{J}trVC}<Sg)=5l#`r{vV~|-W2LWfk@oHP=F+_7-<~{|3_pF;ktxRDZ{Qf zls(ElleC%S{f&)?>*6^`++VNrmiINjg28XpcaVytlqE9`&c$jpR*w$vk$07F za_)>2&P0AZ!h5XIAi~YQ>ELU_&smub-*i@jxc&eo8TUEWq2O%NMpDLil#U*dFqwuX zkeQCV2${O}abK~9QsE%(3k*b8dct=p_bc^v6(+pS1-;3ZR*y3CX)md@*9IR^<^*jd zrN8JA`CVEc3I~x;Zu0FP;``QF(Ys{pR~u!h9?P0j>z`;cJ!KZ*Jkm3we)UlqqjOiV z;eAKi8OqJ%UPgK%;u{DrKwV>KzdJ6b{3ZI(wL>3Ak7+a#iJvf=OZN`aKxGOIqf#oY zL;iN_C<5`M+}ntMhyJ4jJ*g8@al6V>SJz_FT62FU+>-k+Vg9<8|5~o&sB4VPxCUNQ zm;(Hg%9~C2tu>@_{65#~N5_>2Z=}pm%urWX($`V89`T>7@ph!WC0v#AzcRSBy!lSLTWi(pTW%>V`pY(sI^CPjD45GD_ ztE`D|t;Yf`=!ILGDpHVke2-~d*JdIEES#I%IW#z(cw+9TmR{5>Mk9N<({ooL?G1Hx zWiszme-ZU{?V(I4;Y18#7G)0+)}o)|Zm+);drzgfB3b2zR476`p^ZMGrK?N@()!u# z6xS7x@~KE~O~cg)S0`;=B%STa|NIb9zujw23)v~rh42!a!eB}!{-)(zljHV`A2gHP ze*VW|1)-tb!G8&t!4U3eT& z!d19+?X`|4SVv0xl{=y3Z^d(z;SUJB|LAb2mHVBJ3eeUW(u+|hGj{^QFICSTORou$ z5yaC_u{)Vns4$eYkEE3){_VAi_!-Kr=Uzy70luO9U$~U`3<|HpAkuVg;NHd{veVuf z(pC|kpmN;4lZ-M8841W3MM4j&w24AruLYFZZRtHIQ-W|#GTT{!W0ZYIx~?w_;<%MP zM!PF4J)_I^PLV%`dk$@0*8G1Y5Ke-wz7B6C6@v*MwfG*)XN@MK!HINOiaHl9Ei3ua zX{P}7bhRZvz2)_%`~u=7DW8)3q&R}KgQU6N)Z#0vs4vYiXy`2W?>6#<6ueHEHmYFP zSi++zvxs;z8k~S1ti#&0@hADctj$DNhx}obe~wMa`)F;C{Q7N)bngcW%+&y_;#90f z`b7-kZbkU63Ud8Pr`c(!AnDiXxQP-c4;~xemy$p>a$}PEBe`jbKO`QcG;Uoj$xA|b z9X+PSM+|2^Wi!)ae$vj777GhnHMbT_Y_MZOqWG{&cmb;L?FN+eddhLv%X_yK%tX>BkO4e{sQ{{IEu zQZ(FJ1-ZUZR#$K9^e}nZxYtrAjJyVfS26%yS&1*@9&BY36ZUPU(UjbcNz6pSQ{3Gs zJcI_el0KUB5~Nk5aC92WLbxw^-(J&5&&a)n#J!YH!TmjTuaj1bu&&*zL;QQ%`Fa)A z3q2nNqEL7(sV~UfZ533AzpLo=Bd@*HXift=h_AGGD+UvrGGlQ!Y5G)qLK}_gtSsp* zh|i_`66-XKu&%-6$MC1I{yD9~7Bt?NhMG|52A zNE^F|ci?}j6ox5$Vfm&CBk>C zqb)SBoV58?ZV=%;-0O%ZChvPJ?Z)Q+?;ZZzm;A3+Cc+PCE0l7%C?6ZkTjuZ}_WzuX zP-!J8xQ0P|z1~uJwGCv(H;q0bZ5HJ^QE)o$v%EFf9;!3~yPh7M{Io^IuP67SEQfd;FSUJ8#`+4weyJLJzM z+=)6T$sg^y@_r>Pg}&!%AS0+W6?;-Z*9C|Fe|vnrHTawcmRQH7F(K&#a3O8nqLJ}m z^GFY%oq@E`2zPOp^UszK4buMReoWckr1^$ghcT_g9=U;7Yg1Y?=<0xq`f7a znY6crqY#cv`4J4D$k%#=buHtrMR=UW!&!xYXd{h3*ZpUfe(lnW#*R^_54NL`Clvg8 z{X{3_Nn1f$YVwN{Z)qL%r?Jfz{y=_^+M!|t+6p6mB5_^Isk7X|XUMBfyoSZy`k}DEMl#~Mn&S{E)}n#IR`Dw3 zI&h~lCFxmcNY_r{pXuN@@lnL{6HbRZJI`!DIdBU38LiGB z>i?M zYjTg_zC)qDbfPOAm2@?;cx3V#aG!R`{{J4bJVicJel4Bpib?0+Szd0!ugGhIU$2{b zISk_-N6HZzJ!=)mGl&ipu82`=0DZ{Qc{xYgS?-2}OK|_h9fw=j9y(iv^{MlM^1~?? zY;8^<{E%|-DYFHia{H!{S%VR6By&9BIaJllX&B`fz65&|njkC5|QASq^;+3NmAdPnY3mVb`)k(BR6AK7VhJ$G{b+FjRG?n~Syt#AUu0TvFX zVk0WxmzxZWPKTx4P>ICs2L$-&8+dMWKN-Se`~m>HF}w}PLwNyF_cERUx+uLTzV@*s{eXK-U8AK;@9iE z1-jGEChMzn1h16Wf(9>GLP5g02(PAMm;cx3Vj7HT<;AYc-u;Oy?++h#f7J}{{{Sw3 BAs_$% diff --git a/locale/zh/LC_MESSAGES/django.po b/locale/zh/LC_MESSAGES/django.po index 1849d5f1..52be3c82 100644 --- a/locale/zh/LC_MESSAGES/django.po +++ b/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-11-02 20:06+0000\n" +"POT-Creation-Date: 2026-11-02 20:32+0000\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -99,6 +99,7 @@ msgstr "一年后" #: admin/templates/admin/user_form.html:16 #: admin/templates/admin/user_list.html:58 #: operations/templates/operations/jobs.html:15 +#: operations/templatetags/operations.py:91 msgid "never" msgstr "永不" @@ -286,6 +287,7 @@ msgstr "修改密码" #: nwfilters/templates/create_nwfilter_block.html:33 #: nwfilters/templates/nwfilter.html:178 nwfilters/templates/nwfilters.html:93 #: operations/templates/operations/job.html:31 +#: operations/templatetags/operations.py:83 #: storages/templates/create_stg_block.html:183 #: storages/templates/create_stg_vol_block.html:35 #: storages/templates/create_stg_vol_block.html:68 @@ -3498,6 +3500,7 @@ msgid "OS details" msgstr "操作系统详情" #: instances/templates/instance.html:39 +#: operations/templatetags/operations.py:85 msgid "Refresh" msgstr "刷新" @@ -7120,6 +7123,11 @@ msgid "" "rules and references." msgstr "字母、数字、点、短横线和下划线。副本包含该过滤器的规则和引用。" +#: operations/api/serializers.py:35 +#, python-format +msgid "%(phase)s (over its time limit)" +msgstr "%(phase)s(已超出时间限制)" + #: operations/templates/operations/job.html:11 #: operations/templates/operations/jobs.html:7 #: operations/templates/operations/jobs.html:9 @@ -7192,6 +7200,7 @@ msgid "What you checked" msgstr "检查内容" #: operations/templates/operations/jobs.html:14 +#: operations/templatetags/operations.py:90 msgid "Worker unavailable, last seen" msgstr "工作进程不可用,最后在线时间" @@ -7268,6 +7277,36 @@ msgid "%(count)d second" msgid_plural "%(count)d seconds" msgstr[0] "%(count)d 秒" +#: operations/templatetags/operations.py:84 +msgctxt "verb" +msgid "Open" +msgstr "打开" + +#: operations/templatetags/operations.py:86 +msgid "Dismiss" +msgstr "关闭" + +#: operations/templatetags/operations.py:87 +msgid "Finishing…" +msgstr "即将完成…" + +#: operations/templatetags/operations.py:88 +msgid "Files not removed:" +msgstr "未删除的文件:" + +#: operations/templatetags/operations.py:89 +msgid "A short operation is in progress." +msgstr "有一个短操作正在进行。" + +#: operations/templatetags/operations.py:92 +#, python-format +msgid "Cancel failed (HTTP %(status)s)." +msgstr "取消失败(HTTP %(status)s)。" + +#: operations/templatetags/operations.py:93 +msgid "Cancel failed: the server could not be reached." +msgstr "取消失败:无法连接到服务器。" + #: operations/utils.py:52 msgid "The host of this virtual machine cannot be reached right now." msgstr "当前无法连接此虚拟机所在的主机。" diff --git a/operations/api/serializers.py b/operations/api/serializers.py index 39079a92..3e175ea1 100644 --- a/operations/api/serializers.py +++ b/operations/api/serializers.py @@ -1,3 +1,6 @@ +from datetime import timedelta + +from django.utils import timezone from django.utils.translation import gettext as _ from rest_framework import serializers @@ -8,6 +11,7 @@ from operations.utils import shown_label class OperationSerializer(serializers.ModelSerializer): label = serializers.SerializerMethodField() + phase = serializers.SerializerMethodField() resource_label = serializers.SerializerMethodField() cancellable = serializers.SerializerMethodField() in_request = serializers.SerializerMethodField() @@ -22,6 +26,15 @@ class OperationSerializer(serializers.ModelSerializer): def get_label(self, op) -> str: return str(_(label_of(op.kind))) + def get_phase(self, op) -> str: + """The phase in the viewer's language; a job running past its time + limit says so (one that can be cancelled is cancelled instead).""" + phase = _(op.phase) if op.phase else "" + if op.state == Operation.RUNNING and op.time_limit and op.started_at \ + and timezone.now() - op.started_at > timedelta(seconds=op.time_limit): + return (_("%(phase)s (over its time limit)") % {"phase": phase}).strip() + return phase + def get_resource_label(self, op) -> str: return shown_label(op, self.context["request"].user) diff --git a/operations/static/operations/job_panel.js b/operations/static/operations/job_panel.js index 3353d33f..d963c06d 100644 --- a/operations/static/operations/job_panel.js +++ b/operations/static/operations/job_panel.js @@ -10,7 +10,9 @@ var JOB_STATE_COLORS = { failed: "danger", cancelled: "secondary", uncertain: "warning", }; -function jobPanel(element, urls, csrfToken, initialIds) { +// states: the label of each state; text: the panel's own texts, both in the +// page's language (job_panel_script) +function jobPanel(element, urls, csrfToken, initialIds, states, text) { var shown = {}; // id -> job in the last active list var pending = {}; // id -> true: left the list (or just submitted), outcome not fetched yet var inflight = {}; // id -> true: its outcome is being fetched @@ -41,7 +43,7 @@ function jobPanel(element, urls, csrfToken, initialIds) { return '

' + (finishing ? "Finishing\u2026" : pct + "%") + "
"; + + (finishing ? 100 : pct) + '%">' + (finishing ? esc(text.finishing) : pct + "%") + ""; } // label, state badge and muted phase on one line, the buttons on its right @@ -49,7 +51,7 @@ function jobPanel(element, urls, csrfToken, initialIds) { return '
' + esc(label) + "" + '' + esc(state) + "" + + (JOB_STATE_COLORS[state] === "warning" ? " text-dark" : "") + '">' + esc(states[state] || state) + "" + (phase ? '' + esc(phase) + "" : "") + (buttons ? '
' + buttons + "
" : "") + "
"; } @@ -64,7 +66,7 @@ function jobPanel(element, urls, csrfToken, initialIds) { function jobHtml(job) { var cancel = job.cancellable ? '" : ""; + + esc(job.id) + '"' + (cancelling[job.id] ? " disabled" : "") + ">" + esc(text.cancel) + "" : ""; // an uncertain job keeps its claims, so it stays in the list with its error return alertHtml(job.state, header(job.label, job.state, job.phase, cancel) + errorHtml(job) + bar(job)); } @@ -72,26 +74,26 @@ function jobPanel(element, urls, csrfToken, initialIds) { function outcomeHtml(job) { var left = (job.result && job.result.left_behind) || []; var note = job.result && job.result.warning ? '
' + esc(job.result.warning) + "
" : ""; - var warn = note + (left.length ? '
Files not removed:
    ' + var warn = note + (left.length ? '
    ' + esc(text.not_removed) + '
      ' + left.map(function (path) { return '
    • ' + esc(path) + "
    • "; }).join("") + "
    " : ""); - var buttons = (opens(job) ? 'Open' : "") - + '' + var buttons = (opens(job) ? '' + esc(text.open) + "" : "") + + '" + ''; + + '">' + esc(text.dismiss) + ""; return alertHtml(job.state, header(job.label, job.state, "", buttons) + errorHtml(job) + warn); } function render() { var html = notice ? alertHtml("failed", '
    ' + esc(notice) + '
    ') : ""; + + ' data-dismiss-error="1">' + esc(text.dismiss) + "") : ""; last.jobs.forEach(function (job) { html += jobHtml(job); }); Object.keys(outcomes).forEach(function (id) { html += outcomeHtml(outcomes[id]); }); last.others.forEach(function (o) { html += '
    ' + header(o.label, o.state, "", "") + "
    "; }); if (last.short_operation) { - html += '
    A short operation is in progress.
    '; + html += '
    ' + esc(text.short_operation) + "
    "; } // a job the worker has to start, run or stop, not one a request runs (the Jobs page uses the same rule) var waiting = last.jobs.some(function (j) { @@ -99,8 +101,8 @@ function jobPanel(element, urls, csrfToken, initialIds) { }); var seen = last.worker_last_seen ? new Date(last.worker_last_seen) : null; if (waiting && (!seen || Date.now() - seen.getTime() > 60000)) { - html += '
    Worker unavailable, last seen ' - + esc(seen ? seen.toLocaleString() : "never") + ".
    "; + html += '
    ' + esc(text.worker_unavailable) + " " + + esc(seen ? seen.toLocaleString() : text.never) + ".
    "; } if (html !== rendered) { element.innerHTML = html; @@ -189,7 +191,7 @@ function jobPanel(element, urls, csrfToken, initialIds) { .fail(function (xhr) { // e.g. a queued job started meanwhile and cannot be stopped any more notice = (xhr.responseJSON && xhr.responseJSON.detail) - || (xhr.status ? "Cancel failed (HTTP " + xhr.status + ")." : "Cancel failed: the server could not be reached."); + || (xhr.status ? text.cancel_failed.replace("%(status)s", xhr.status) : text.cancel_unreachable); }) .always(function () { delete cancelling[id]; diff --git a/operations/static/operations/job_panel_start.js b/operations/static/operations/job_panel_start.js index 62d334dd..b5014134 100644 --- a/operations/static/operations/job_panel_start.js +++ b/operations/static/operations/job_panel_start.js @@ -5,5 +5,5 @@ resource: settings.resource, job: function (id) { return settings.jobs + id + "/"; }, cancel: function (id) { return settings.jobs + id + "/cancel/"; }, - }, settings.csrf_token, settings.remembered); + }, settings.csrf_token, settings.remembered, settings.states, settings.text); })(); diff --git a/operations/templates/operations/job.html b/operations/templates/operations/job.html index 0c4ac48f..9c615320 100644 --- a/operations/templates/operations/job.html +++ b/operations/templates/operations/job.html @@ -20,11 +20,11 @@
    {% trans "User" %}: {{ job.username }}
    - {% if op.phase or op.progress_total or job.cancellable or op.error or job.result.links or job.result.warning or job.result.left_behind or job.resolution %} + {% if job.phase or op.progress_total or job.cancellable or op.error or job.result.links or job.result.warning or job.result.left_behind or job.resolution %}
    - {% if op.phase or job.cancellable %} + {% if job.phase or job.cancellable %}
    - {% if op.phase %}{% translate op.phase %}{% endif %} + {{ job.phase }} {% if job.cancellable %}
    {% csrf_token %} diff --git a/operations/templates/operations/jobs.html b/operations/templates/operations/jobs.html index e14794d5..b920801d 100644 --- a/operations/templates/operations/jobs.html +++ b/operations/templates/operations/jobs.html @@ -68,11 +68,11 @@ {{ row.label }} {% if op.state in active_states %} - {% if op.phase or op.progress_total %} + {% if row.phase or op.progress_total %}
    - {% if op.phase %}{% translate op.phase %}{% endif %} + {{ row.phase }} {% if op.progress_total %} - {% if op.phase %}·{% endif %} + {% if row.phase %}·{% endif %} {% if op.kind in bytes_kinds %}{{ op.progress_done|default:0|filesizeformat }} / {{ op.progress_total|filesizeformat }}{% else %}{{ op.progress_done|default:0 }} / {{ op.progress_total }}{% endif %} {% endif %}
    diff --git a/operations/templatetags/operations.py b/operations/templatetags/operations.py index 7bbbab01..a125ddea 100644 --- a/operations/templatetags/operations.py +++ b/operations/templatetags/operations.py @@ -7,7 +7,7 @@ from django.urls import reverse from django.utils.html import format_html, format_html_join from django.utils.safestring import mark_safe from django.utils.timesince import timesince -from django.utils.translation import ngettext, pgettext_lazy +from django.utils.translation import gettext, ngettext, pgettext, pgettext_lazy from operations.jobs import take_remembered from operations.models import Operation @@ -78,4 +78,18 @@ def job_panel_script(context, resource): "jobs": reverse("operation-list"), "csrf_token": get_token(context["request"]), "remembered": take_remembered(context["request"], resource), + "states": {state: str(label) for state, label in STATE_LABELS.items()}, + "text": { + "cancel": gettext("Cancel"), + "open": pgettext("verb", "Open"), + "refresh": gettext("Refresh"), + "dismiss": gettext("Dismiss"), + "finishing": gettext("Finishing…"), + "not_removed": gettext("Files not removed:"), + "short_operation": gettext("A short operation is in progress."), + "worker_unavailable": gettext("Worker unavailable, last seen"), + "never": gettext("never"), + "cancel_failed": gettext("Cancel failed (HTTP %(status)s)."), + "cancel_unreachable": gettext("Cancel failed: the server could not be reached."), + }, }} diff --git a/operations/tests/js/job_panel.test.js b/operations/tests/js/job_panel.test.js index 86de38b0..8a769948 100644 --- a/operations/tests/js/job_panel.test.js +++ b/operations/tests/js/job_panel.test.js @@ -50,12 +50,20 @@ eval(fs.readFileSync(process.argv[2], "utf8")); eval(fs.readFileSync(process.argv[3], "utf8")); const urls = { resource: "/r", job: (id) => "/j/" + id, cancel: (id) => "/c/" + id }; +// the labels and texts the page gives (job_panel_script), here as in English +const STATES = { queued: "queued", running: "running", cancelling: "cancelling", succeeded: "succeeded", + failed: "failed", cancelled: "cancelled", uncertain: "uncertain" }; +const TEXT = { cancel: "Cancel", open: "Open", refresh: "Refresh", dismiss: "Dismiss", finishing: "Finishing\u2026", + not_removed: "Files not removed:", short_operation: "A short operation is in progress.", + worker_unavailable: "Worker unavailable, last seen", never: "never", + cancel_failed: "Cancel failed (HTTP %(status)s).", + cancel_unreachable: "Cancel failed: the server could not be reached." }; const seen = new Date(1700000000000).toISOString(); const running = { id: "a", label: "Delete snapshot", state: "running", phase: "Merging", progress_done: 1, progress_total: 4, cancellable: false, result: {}, error: "" }; const empty = { jobs: [], others: [], short_operation: false, worker_last_seen: seen }; -jobPanel(el, urls, "tok"); +jobPanel(el, urls, "tok", undefined, STATES, TEXT); advance(0); answer("/r", { ...empty, jobs: [running] }); assert.ok(el.innerHTML.includes("Delete snapshot") && el.innerHTML.includes("25%"), "shows the job and real progress"); @@ -108,7 +116,7 @@ assert.ok(!window.reloaded); // a job that ended before the first poll: shown from the submitted ids open = []; timers = []; const el2 = { innerHTML: "", addEventListener() {} }; -jobPanel(el2, urls, "tok", ["b"]); +jobPanel(el2, urls, "tok", ["b"], STATES, TEXT); advance(0); answer("/r", empty); answer("/j/b", { ...running, id: "b", state: "failed", error: "refused" }); @@ -118,7 +126,7 @@ assert.ok(el2.innerHTML.includes("refused") && el2.innerHTML.includes('class="al // a late answer for a dismissed job does not bring it back const el3 = { innerHTML: "", addEventListener(ev, f) { listeners3 = f; } }; let listeners3; -jobPanel(el3, urls, "tok", ["c"]); +jobPanel(el3, urls, "tok", ["c"], STATES, TEXT); advance(0); answer("/r", empty); listeners3({ target: { dataset: { dismiss: "c" } } }); @@ -130,7 +138,7 @@ open = []; timers = []; let writes = 0, html4 = ""; const el4 = { addEventListener() {}, get innerHTML() { return html4; }, set innerHTML(v) { writes++; html4 = v; } }; -jobPanel(el4, urls, "tok"); +jobPanel(el4, urls, "tok", undefined, STATES, TEXT); advance(0); answer("/r", { ...empty, jobs: [{ ...running, state: "uncertain", error: "check the disks" }] }); assert.ok(el4.innerHTML.includes('uncertain'), "dark text on the yellow badge"); @@ -153,7 +161,7 @@ assert.strictEqual(window.backgroundJobRunning, true, "a foreground operation ke open = []; timers = []; const el6 = { innerHTML: "", addEventListener() {} }; window.backgroundJobRunning = false; -jobPanel(el6, urls, "tok"); +jobPanel(el6, urls, "tok", undefined, STATES, TEXT); advance(0); answer("/r", { ...empty, jobs: [{ ...running, id: "d" }] }); assert.strictEqual(window.backgroundJobRunning, true); @@ -169,7 +177,7 @@ assert.ok(!open.some((r) => r.url === "/j/d" && !r.settled), "a missing job is n open = []; timers = []; window.backgroundJobRunning = false; const el7 = { innerHTML: "", addEventListener() {} }; -jobPanel(el7, urls, "tok", ["e"]); +jobPanel(el7, urls, "tok", ["e"], STATES, TEXT); assert.strictEqual(window.backgroundJobRunning, true, "set at init, not after the first poll"); advance(0); answer("/r", empty, false); // a failed first poll keeps it @@ -183,7 +191,7 @@ assert.strictEqual(window.backgroundJobRunning, false, "released once the rememb open = []; timers = []; const el8 = { innerHTML: "", addEventListener() {} }; const stale = new Date(Date.now() - 120000).toISOString(); -jobPanel(el8, urls, "tok"); +jobPanel(el8, urls, "tok", undefined, STATES, TEXT); advance(0); answer("/r", { ...empty, worker_last_seen: stale, jobs: [running] }); assert.ok(el8.innerHTML.includes("Worker unavailable"), "a running job with a stale lease warns"); @@ -209,7 +217,7 @@ open = []; timers = []; let click9; const el9 = { innerHTML: "", addEventListener(ev, f) { click9 = f; } }; const queued = { ...running, id: "q", state: "queued", cancellable: true, progress_total: null }; -jobPanel(el9, urls, "tok"); +jobPanel(el9, urls, "tok", undefined, STATES, TEXT); advance(0); answer("/r", { ...empty, jobs: [queued] }); assert.ok(el9.innerHTML.includes('data-cancel="q">Cancel'), "an enabled cancel button"); @@ -234,7 +242,7 @@ assert.ok(el9.innerHTML.includes("could not be reached"), "a network error shows open = []; timers = []; window.backgroundJobRunning = false; const el10 = { innerHTML: "", addEventListener() {} }; -const panel = jobPanel(el10, urls, "tok"); +const panel = jobPanel(el10, urls, "tok", undefined, STATES, TEXT); advance(0); answer("/r", empty); assert.strictEqual(window.backgroundJobRunning, false); @@ -249,7 +257,7 @@ assert.ok(el10.innerHTML.includes("Upload") && el10.innerHTML.includes('succeeded s === ".modal.sho open = []; timers = []; window.reloaded = false; Object.assign(document, { activeElement: null, querySelector: () => null }, doc); const elm = { innerHTML: "", addEventListener() {} }; - jobPanel(elm, urls, "tok", ["m"]); + jobPanel(elm, urls, "tok", ["m"], STATES, TEXT); advance(0); answer("/r", empty); answer("/j/m", { ...running, id: "m", label: "Clone", state: "succeeded" }); @@ -304,7 +312,7 @@ Object.assign(document, { activeElement: null, querySelector: () => null }); open = []; timers = []; window.reloaded = false; window.xmlEditUnsaved = () => true; const elx = { innerHTML: "", addEventListener() {} }; -jobPanel(elx, urls, "tok", ["x"]); +jobPanel(elx, urls, "tok", ["x"], STATES, TEXT); advance(0); answer("/r", empty); answer("/j/x", { ...running, id: "x", state: "succeeded" }); @@ -314,7 +322,7 @@ delete window.xmlEditUnsaved; // another job's outcome shown or still awaited: a quiet success does not wipe it open = []; timers = []; window.reloaded = false; const elo = { innerHTML: "", addEventListener() {} }; -jobPanel(elo, urls, "tok", ["f", "s", "w"]); +jobPanel(elo, urls, "tok", ["f", "s", "w"], STATES, TEXT); advance(0); answer("/r", empty); answer("/j/f", { ...running, id: "f", label: "Migrate", state: "failed", error: "no route" }); @@ -325,7 +333,7 @@ answer("/j/w", { ...running, id: "w", label: "Snapshot", state: "succeeded" }); assert.ok(!window.reloaded, "still not while an outcome is shown"); open = []; timers = []; window.reloaded = false; const elp = { innerHTML: "", addEventListener() {} }; -jobPanel(elp, urls, "tok", ["s2", "f2"]); +jobPanel(elp, urls, "tok", ["s2", "f2"], STATES, TEXT); advance(0); answer("/r", empty); answer("/j/s2", { ...running, id: "s2", state: "succeeded" }); @@ -335,10 +343,21 @@ assert.ok(elp.innerHTML.includes("refused"), "which then shows"); // another job still running: its outcome would be lost to a reload open = []; timers = []; window.reloaded = false; const elr = { innerHTML: "", addEventListener() {} }; -jobPanel(elr, urls, "tok", ["s3"]); +jobPanel(elr, urls, "tok", ["s3"], STATES, TEXT); advance(0); answer("/r", { ...empty, jobs: [{ ...running, id: "r3" }] }); answer("/j/s3", { ...running, id: "s3", state: "succeeded" }); assert.ok(!window.reloaded, "not while another job runs"); Date.now = realNow; console.log("ok"); + +// the page's language: the badge, the buttons and the panel's texts come from its settings +{ + const elt = { innerHTML: "", addEventListener() {} }; + const states = { ...STATES, running: "çalışıyor" }; + jobPanel(elt, urls, "tok", undefined, states, { ...TEXT, cancel: "İptal" }); + advance(0); + answer("/r", { ...empty, jobs: [{ ...running, id: "t", cancellable: true }] }); + assert.ok(elt.innerHTML.includes('çalışıyor') + && elt.innerHTML.includes(">İptal"), "labels and texts of the page's language"); +} diff --git a/operations/tests/test_api.py b/operations/tests/test_api.py index 6137caf7..a8d7d44b 100644 --- a/operations/tests/test_api.py +++ b/operations/tests/test_api.py @@ -1,7 +1,10 @@ +from datetime import timedelta + from django.contrib.auth import get_user_model from django.contrib.auth.models import Permission from django.test import TransactionTestCase from django.urls import reverse +from django.utils import timezone from accounts.models import UserInstance from computes.models import Compute @@ -24,6 +27,14 @@ class OperationsApiTestCase(TransactionTestCase): UserInstance.objects.create(user=self.owner, instance=self.vm2) self.op = jobs.submit("test.noop", self.owner, {"uuid": "u1"}, "key-00000001") + def test_the_phase_comes_in_the_users_language_and_says_when_it_is_past_its_limit(self): + Operation.objects.filter(pk=self.op.pk).update(state=Operation.RUNNING, phase="Merging the snapshot") + self.client.force_login(self.owner) + url = f"/api/v1/operations/{self.op.pk}/" + self.assertEqual(self.client.get(url, HTTP_ACCEPT_LANGUAGE="tr").json()["phase"], "Anlık görüntü birleştiriliyor") + Operation.objects.filter(pk=self.op.pk).update(time_limit=60, started_at=timezone.now() - timedelta(seconds=61)) + self.assertEqual(self.client.get(url).json()["phase"], "Merging the snapshot (over its time limit)") + def test_users_list_only_their_own_jobs(self): self.client.force_login(self.other) self.assertEqual(self.client.get("/api/v1/operations/").json()["count"], 0) diff --git a/operations/worker.py b/operations/worker.py index c4911ce1..33a1650b 100644 --- a/operations/worker.py +++ b/operations/worker.py @@ -229,10 +229,9 @@ class Worker: now = timezone.now() for op in Operation.objects.filter(pk__in=list(self.jobs), time_limit__isnull=False): if op.started_at and now - op.started_at > timedelta(seconds=op.time_limit): + # one that cannot be cancelled runs on; its page says it is over its limit if jobs.get_kind(op.kind).cancellable and not op.cancel_requested: self._fenced_update([op.pk], state=Operation.CANCELLING, cancel_requested=True) - elif "(over its time limit)" not in op.phase: - self._fenced_update([op.pk], phase=f"{op.phase} (over its time limit)"[:255]) def _progress(self): """At most one query per job and none waiting for a thread, so queries