From a211a166c8ebb2e1caecee6723b4e5f5e6296d01 Mon Sep 17 00:00:00 2001 From: "Billah, Tashrif" Date: Fri, 27 Nov 2020 15:39:41 -0500 Subject: [PATCH 01/10] add by_task_id handler --- luigi/db_task_history.py | 7 +++++++ luigi/server.py | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/luigi/db_task_history.py b/luigi/db_task_history.py index e1eabcb7d1..e654d54c3e 100644 --- a/luigi/db_task_history.py +++ b/luigi/db_task_history.py @@ -187,6 +187,13 @@ def find_task_by_id(self, id, session=None): with self._session(session) as session: return session.query(TaskRecord).get(id) + def find_task_by_task_id(self, task_id, session=None): + """ + Find task with the given record ID. + """ + with self._session(session) as session: + return session.query(TaskRecord).filter(TaskRecord.task_id=task_id).all()[-1] + class TaskParameter(Base): """ diff --git a/luigi/server.py b/luigi/server.py index 50948624d3..2799217577 100644 --- a/luigi/server.py +++ b/luigi/server.py @@ -261,6 +261,12 @@ def get(self, id): self.render("show.html", task=task) +class ByTaskIdHandler(BaseTaskHistoryHandler): + def get(self, task_id): + task = self._scheduler.task_history.find_task_by_task_id(task_id) + self.render("show.html", task=task) + + class ByParamsHandler(BaseTaskHistoryHandler): def get(self, name): payload = self.get_argument('data', default="{}") @@ -310,6 +316,7 @@ def app(scheduler): (r'/history', RecentRunHandler, {'scheduler': scheduler}), (r'/history/by_name/(.*?)', ByNameHandler, {'scheduler': scheduler}), (r'/history/by_id/(.*?)', ByIdHandler, {'scheduler': scheduler}), + (r'/history/by_task_id/(.*?)', ByTaskIdHandler, {'scheduler': scheduler}), (r'/history/by_params/(.*?)', ByParamsHandler, {'scheduler': scheduler}), (r'/metrics', MetricsHandler, {'scheduler': scheduler}) ] From 89c9aa750de8ae2badabe435d98c02e44a1aa8b4 Mon Sep 17 00:00:00 2001 From: "Billah, Tashrif" Date: Fri, 27 Nov 2020 16:04:49 -0500 Subject: [PATCH 02/10] insert missing = --- luigi/db_task_history.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luigi/db_task_history.py b/luigi/db_task_history.py index e654d54c3e..6b330a154b 100644 --- a/luigi/db_task_history.py +++ b/luigi/db_task_history.py @@ -192,7 +192,7 @@ def find_task_by_task_id(self, task_id, session=None): Find task with the given record ID. """ with self._session(session) as session: - return session.query(TaskRecord).filter(TaskRecord.task_id=task_id).all()[-1] + return session.query(TaskRecord).filter(TaskRecord.task_id==task_id).all()[-1] class TaskParameter(Base): From 76c62830441e33c127092de8faa96e2ecf2bf965 Mon Sep 17 00:00:00 2001 From: "Billah, Tashrif" Date: Fri, 11 Dec 2020 16:58:26 -0500 Subject: [PATCH 03/10] make all indents 4 chars --- luigi/tools/deps_tree.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/luigi/tools/deps_tree.py b/luigi/tools/deps_tree.py index 27a00313e3..ea3391bb54 100755 --- a/luigi/tools/deps_tree.py +++ b/luigi/tools/deps_tree.py @@ -9,18 +9,18 @@ $ luigi-deps-tree --module foo_complex examples.Foo ... └─--[Foo-{} (PENDING)] - |--[Bar-{'num': '0'} (PENDING)] - | |--[Bar-{'num': '4'} (PENDING)] - | └─--[Bar-{'num': '5'} (PENDING)] - |--[Bar-{'num': '1'} (PENDING)] - └─--[Bar-{'num': '2'} (PENDING)] - └─--[Bar-{'num': '6'} (PENDING)] - |--[Bar-{'num': '7'} (PENDING)] - | |--[Bar-{'num': '9'} (PENDING)] - | └─--[Bar-{'num': '10'} (PENDING)] - | └─--[Bar-{'num': '11'} (PENDING)] - └─--[Bar-{'num': '8'} (PENDING)] - └─--[Bar-{'num': '12'} (PENDING)] + |---[Bar-{'num': '0'} (PENDING)] + | |---[Bar-{'num': '4'} (PENDING)] + | └─--[Bar-{'num': '5'} (PENDING)] + |---[Bar-{'num': '1'} (PENDING)] + └─--[Bar-{'num': '2'} (PENDING)] + └─--[Bar-{'num': '6'} (PENDING)] + |---[Bar-{'num': '7'} (PENDING)] + | |---[Bar-{'num': '9'} (PENDING)] + | └─--[Bar-{'num': '10'} (PENDING)] + | └─--[Bar-{'num': '11'} (PENDING)] + └─--[Bar-{'num': '8'} (PENDING)] + └─--[Bar-{'num': '12'} (PENDING)] """ from luigi.task import flatten @@ -52,10 +52,10 @@ def print_tree(task, indent='', last=True): result = '\n' + indent if(last): result += '└─--' - indent += ' ' + indent += ' ' else: - result += '|--' - indent += '| ' + result += '|---' + indent += '| ' result += '[{0}-{1} ({2})]'.format(name, params, is_complete) children = flatten(task.requires()) for index, child in enumerate(children): From a29381421acb62968a53bc8ddd05ce49ac07bf01 Mon Sep 17 00:00:00 2001 From: Tashrif Billah <35086881+tashrifbillah@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:59:12 -0400 Subject: [PATCH 04/10] there was a typo in the description --- luigi/db_task_history.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luigi/db_task_history.py b/luigi/db_task_history.py index 6b330a154b..99a0265056 100644 --- a/luigi/db_task_history.py +++ b/luigi/db_task_history.py @@ -189,7 +189,7 @@ def find_task_by_id(self, id, session=None): def find_task_by_task_id(self, task_id, session=None): """ - Find task with the given record ID. + Find task with the given task ID. """ with self._session(session) as session: return session.query(TaskRecord).filter(TaskRecord.task_id==task_id).all()[-1] From e7b0b976c67342451ca6b94045ba40e2a8d5a47b Mon Sep 17 00:00:00 2001 From: Tashrif Billah <35086881+tashrifbillah@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:04:50 -0500 Subject: [PATCH 05/10] include /history/by_task_id/ endpoint --- doc/central_scheduler.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/central_scheduler.rst b/doc/central_scheduler.rst index eebc522076..f8cbbf0991 100644 --- a/doc/central_scheduler.rst +++ b/doc/central_scheduler.rst @@ -95,3 +95,11 @@ The task history has the following pages: a listing of all runs of the task ``{name}`` restricted to runs with ``params`` matching the given history. The ``params`` is a json blob describing the parameters, e.g. ``data={"foo": "bar"}`` looks for a task with ``foo=bar``. +* ``/history/by_task_id/{task_id}`` + a listing of all runs of a task given the ``{task_id}``. It is different from just ``{id}`` + and is a derivative of ``params``. It is available via ``{task_id}`` property of a + ``luigi.Task`` instance or via `luigi.task.task_id_str + `_. + This kind of representation is useful for concisely recording URLs in a history tree + than recording lengthy ``params``. + From 80f230870ebd68502da234d5d645c16106cdb4b2 Mon Sep 17 00:00:00 2001 From: Tashrif Billah <35086881+tashrifbillah@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:38:01 -0500 Subject: [PATCH 06/10] /history/by_task_id is only the latest run of a task --- doc/central_scheduler.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/central_scheduler.rst b/doc/central_scheduler.rst index f8cbbf0991..753a99be5f 100644 --- a/doc/central_scheduler.rst +++ b/doc/central_scheduler.rst @@ -96,10 +96,9 @@ The task history has the following pages: The ``params`` is a json blob describing the parameters, e.g. ``data={"foo": "bar"}`` looks for a task with ``foo=bar``. * ``/history/by_task_id/{task_id}`` - a listing of all runs of a task given the ``{task_id}``. It is different from just ``{id}`` + the latest run of a task given the ``{task_id}``. It is different from just ``{id}`` and is a derivative of ``params``. It is available via ``{task_id}`` property of a ``luigi.Task`` instance or via `luigi.task.task_id_str `_. - This kind of representation is useful for concisely recording URLs in a history tree - than recording lengthy ``params``. + This kind of representation is useful for concisely recording URLs in a history tree. From c120b8f55e3b7c3c933beeb08737e852a5f7e45d Mon Sep 17 00:00:00 2001 From: Tashrif Billah <35086881+tashrifbillah@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:50:50 -0500 Subject: [PATCH 07/10] write block for by_task_id screenshot --- doc/central_scheduler.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/central_scheduler.rst b/doc/central_scheduler.rst index 753a99be5f..74a19cb3eb 100644 --- a/doc/central_scheduler.rst +++ b/doc/central_scheduler.rst @@ -101,4 +101,8 @@ The task history has the following pages: ``luigi.Task`` instance or via `luigi.task.task_id_str `_. This kind of representation is useful for concisely recording URLs in a history tree. + Example screenshot: + + .. figure:: history_by_task_id.png + :alt: By task_id screenshot From bced3603915c0ac7d1f32cc3e95bf8069ad697f1 Mon Sep 17 00:00:00 2001 From: Tashrif Billah <35086881+tashrifbillah@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:52:30 -0500 Subject: [PATCH 08/10] add screenshot for history_by_task_id --- doc/history_by_task_id.png | Bin 0 -> 34793 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/history_by_task_id.png diff --git a/doc/history_by_task_id.png b/doc/history_by_task_id.png new file mode 100644 index 0000000000000000000000000000000000000000..cd4539cc76288add2a66aafdc1ab7ebe9682db23 GIT binary patch literal 34793 zcmb@uXIxX=_AMMNpopN-qzhP(jx^~iO^_-b1O%jo-aElUk*ZXY5_*TwI|QUjuc3vG z)BvF-)Z}i@^Z1-|-uu7zetG#2*!=b;S#!-b*O+6B#b-4Y`J2SF#2^sprou~^*C5ap zJK*QEYlOgSwa(XO;M*0K7Ydr!fG^)`??QlU8dq6eR}BXXR}T|sbC9LIgPl2-i-SC4&gLer)(-afG_CE-L7G->_jrZxsW`abd&2uf;2y7lsK8TE zevx}>%J*b7H0^EUBtW2hAO)G{nx4s9vmU+_i0PKS`FLCJz{5|pFG131*@8<#6eTxr zcvCjHm%V9V>j*P6z9F=AmGTQagLQh)oflT`LDv;tqLXY>uu&~9UQQ{Oe@PphAY+OV zaTyR_OHQ0hi4oyvmsO|ubnC@6=6}7&RAkt1g8t*$?THoZKbONK-Dwg3zL)?0N1;Ct ze!A8Fg=G5gzXCiUApL)PaBSgu61k6X85k3Wh)0F(e-pO5W37Osqtvx4KMW*E#9p!) zy|eiSJxJbAYl9$CLGI)T2YtCM1>cFIxauOS(A2A4M5Qf$yC?L~3q4;rM}89A=54H+ z(U*bHM{V6RO?kLPy1VdyK56pchR5{!jKuY@ozEW6N-M$$TjbXUzLXBgc-Ods>!uV6 z^*p0Omo&~EKW&Z)#OD1JE3Y#$k6p_xbLwpIb}+~u=Ur`6>h%4l@HY3hU`fTH)Ld+; zr0rP~o8WtMvNIh6)wM-=wJj_0kJAXT$e>O%$$%B)uYi8KwS<;2F!+HPt!vL-+tq}r z9C4_vb+#Bltz6$$IZf2>ceXSn8~TQ6q^xHxYF>3CWyT!l*S+Z>XXN&hMtAd!(J)h@7H1e!E&fe0SK@O?$GD% z*<^#~)hkms4^t6L(Qjg}KYK3w7)pvKYx@B!%|`VTT5KIhz(>fhJ7Y6-)O-x|(_4S0 z8S5Z)?a$lGYHb8-PXaG3tWt+|XsVx7Ky>5WD8mwGjb~qJ|9IkR#I-JRB6f~E>d^h( z)k$-iFOKr<7qts_>*ZGIn*@+C4R%DAHRgYLLw#@J|mOp12t`rY^TpY!|PK9>n zBud}C@TUbAqY^tcb&r$`2roQtrnaiPBc%+CTeIQ}YPsrfYIt`pY`jK!X8y^ty&AQZ z9uK=s>l_Ewte;j(i}nnOzOu1gc3n(R6E>ce&NcWmb&Bf#vs%UHIucLYFb7a3mHg<{ zSr!U>X?3z_>Bn(HB7!eYR@69VJ9^quf@4g9iw9ci_@E!WG3tJ<`1SeVCS9(H7KPCi zCWfnDy3l;Or9?2kP(x?nmdgQISH~z*MByV^9o0&EquNu=lqEN-MH|;7fuzaL=nBXV z{}%L&MA~R3WT5bBrUk>pwHEz55dY}g{C5iN9*J2CN*hi7%(sJo*`1Xp@p2+Jn4?i1 zZ(flh`L?b`H)cKrnV9r9!h1u(8^H;EGN{dNghOuHYnz`Em2*M?OE1r_OGyURWqeYv zAWhdTZio02ok6@p?PDyE<9zWe6$hgR*EgIl^DXC^aP!Dz9<*@Wr-chO{hSn;*PfVZ zqjS6w(!yWs%v3Rf<0o>o_jn)?VM#=wVpAgLcPQszVG0Bq{Ca6(iqH;ty^X-K=W1sB zFf~>0amUe0k;C{kz;ZR4tvvEV1ZksriMJ3115X6F?c3*YsoU5R5C2b!#rfqbhqXG^ zH2fq1+R{7bXZYE5$8bh2eezp^0U4E7il|ua{nI@IUEA|Kd=*FP6B<5j_L+rHaL}d% zw|UK;xBXPqmD@=_y5dT&)T`3QFkr(MA5(oICI^RFAT74qv3du-0%ab)A^L@vTe5iW zJ1-c1!ZuKXbkNTXXtqnd!&!UhDsN6_bzD3vY>lzqz)a6;Wv=cq4!=PPg-_Hx*x#*Z z=%bzah(ZR6y&?Oj>NuOyRjLxKk&TF)`Kugqq3bNL>!4W}Q z%S3kt_VNi6JeoDK>uSMouI=p>^38tTPzMzg&bx5W9r#P4wid1gBsp9g=O6W?ch2$C zvc!o&5;NucCWCce3aFjjTk5X}5=j;Y_l?$i9y@vNk%Yd+j+Bq`ibg;qRb`518&7A* z^W1i7Pg0Ufeod8gfmXcos~gNgFMJT+9#HTHtAt6s4r}7(Sg?XV(*?tq~E@gTNYc)k%SVk}H6mQoP zEs4I*M!dtt!f-R7I+Jmw{glUg*opUjiu}UT4$ASIFf5MePE2A2{_gvo5?{%3o{w$j z-m!ltatIv8&PvtB@WFQ??rVrEZCg@P6Qhl!VFlQ0^n#wu4 zuub9b%MHSgrs#*c$`O}#J&rOw)F_y?48uFXE0xV(n8;u?+0Yb5tx>6nX)mnJ?|jsa zSH%r;fix*n<1!R-%|txg5GE&eO5I64stM zGg3ww)_F6IfbLKJL3|KKt;;JJ=3u;Ti8YMSestt`tl0y~Ew8#NIS{G4_m#5xFyFH@UpY@Uo`C zl3c1`zmChE;P#={dV+V{Z9xo;yT9`dj$D}~O4|N3OC5yG+bp5?hH_5pQ4?&vik)D= z%icBF@b4simdzGAGWI+K68Z6l(epC>jdNI{GDGN}`ZQc5f_~5aV)84* zmd@J1KdY?@Z?~!T2SSBdz@`t`n3Ma#LglA$bt~5$S2#AzTOvUB4|F=tjowiI^KQRU zl~UB5e=exCD9DSCjL5R<&xcrC zRa&uFBU+J(C@^NwmS~C@>z{IijkRFZi-->#=3CB@!n+4%vu0wraQ_dgDJq z*@R7zPTNYQ^!hZAj*A(0ewCmwhZagjQCeWNdY^K$Cu2V**z_nKh*ciN_l zuwuR=o1)br$*c0Oti)I-bR4J!xWTSQ+{z5m%6`+iCCiqJWg4}4h&L15jdOf&ww7Q0 z9rSjQ=^WC97Z2pf(OaTF8-HnbRz>ASTU6;!?xTpZn8LddZAtHIl+(=%BLQII^;isl zocz2-)nq$CqwrV%xDK!N3YC4BeOqiQpJ)9TY||!nUUs+r`V>S5M}N|Gc342>C?{R~KHg>O#yPc!+cTrEtET+3k! zPID6BC(UhPiV@-iYx6X=iPIXwwN%krU2w54jVvkQ40Y?iZ|)u|QR~Z{iOvLtcJz#U z#Jq&xgEwKiC3Iz$W|s2=+4rO3c;6~oy8Ag@k$pdm#<=&i^rVV(C(nEfl!SfwK}LED zzrl>e&>^LOaBp=QN0&U>s3CvH#MZ8Bn_+Hgd@40XBW#=^eKx4)#vlcf3yU-F8l|D4 z35OPzDC%o4{xj1BHrhJcHX5q@em*R+a^z$lsGq+$G77TL21ooC55<+xbPp?Ry6N4y zPQDLE^_6Ek81p8nNZYrx)vN@{^1G;c=zIA*d9=ZX8d2e|g6IUvT@j&2=IJ%rO7TE! zeX0)Ijb9JdTi0$NTl2=)%P}jNlKcTno6A3Lx)3^fJ4o(98CL5D2{n7+2cy#8dbnnG z5zk70tO}EV#xL<+FrwZWbm`ifj?$fltTO>+3TZZCFjNoT{k(fW?W3@DQiU~tqqC^0 zwkZMQdwbHGlTTku1=uk$rlB)a)-T=)G{D7w?C?Z69*OzUvoqaW?4mf882@ZU{mUcE z?}^8n6Y%?|Ws)%rObov^JB>C__V~NhJisPBC>rQGV+J{nhYK`%Z53m`LWOumI^Hz86 z8w!FM(YO0Qpi1ul==~TxvHey-(L2s99%o4hpDB$uw%6_5@A4Sq@Q?QhC(|3HjK}3IwsKd z6o`1{p+guGgS^FR0oDCU0vrlecwrTcZZuEGyBqgS#4yG|;-pNA$%*I|GChbCBtHR9O z3or=apo*!AtV&77E5Y+MlTlB_{I)p<)|q_vbSP*(=Xdk_BJnlk*q_owwA=e@i%GQL@p>q?@||-<@M+og^-vzytsuFrKJ`OVlk^~Ol`H-CDCRl4zE4Yk+jSbXrQOq zz2@q|3kqpwj{dchdu?+`^<@p{jd+qWRy3;`lTQ|>7>Fo%`Zz;TWrInqy0HqXtwTsI zSiis6BBBtOT)$9-a;u7B?HY`Z)zGC3q|4mIj_0j9`d zOgxuVe)=Q-wS)u7roFK7VHzrg(KTh;!%v;@)tuL->o8w41I+6gBkk0_UzqiA@hN^n zvSOFQW=oYP#X(m_Gd_~(d)%B$XVhZ6bz^~H@qK!`(!l!{m&DH0jo!BO>jaN$Nh7~9 z1HI5U0#!GHtL_l5PZ*uxl;22d+L*F)1aF%yP>~!tA-v@_pq&4EcrZ1OC+@2w_V4a? zz9zT#Kk79mw>(lcRIFfELY(7P~g+KDFas%5yE6x&|fNg46!}Z2tZi>Uj9LYF+ zB+uXQ>-Z7aT}Ru9TR#UAwer2%q}}}2w-=H_4PR7MsrtF%bm)WzX1YE!2rZE>cK;Oi7Bzp{L35#z zFh?dEbL>K_0Ef1~s;K#v^~;uHq_xKLZSW$6)ytL+Dg<3&ue^#O2)_}%|Hw?d48Tz( zizUbixqMhafKGdEo&(=phc)Vd-d&1u6)^A^={r4s>SO-Z_fXC2_)BU!J$B%#lhS=$MmRAHv(Lyc=R z0%)(2;|)IC)9USLJ7oU9h%F8IKLGm0HSXo-N&jZ8b{`;f`7*~XxO>mwD%NUn$ zkITD{fT`v(Gmgjni6hbP7A4sCBW+8{RlNLZ=`2ZXtM~p+{7<*=_xs(4EY3FG%pu)M z=T0g`g$d_QulT3iB{PkgD=jbiuj1{s{3W4fMGMhgZt+dWbD>f#B}L~CKP&&in^wgC zJN7B%5~gFHEZcP%A=_!6eH4&Zol^MA;Nqm0B1PqDT1L^gMQpQ-XRc(N`Ko#Od0TGc z?xu%TB{xX7m}*rO9$XgH6sGg+i*(tA8~ayP@`M=m?@{n1Y7aTGmFh@o`W~N*r%609 z+GS#o0$)f!mbirE%fzQ#sr4dId&{;GXD3x5g}$#J7ewlxEJrH~jh_HrcUKU_D?&6LeS8oT{_U%-nO%usx+FGwP7i^Z6?L}(Soxdp^f7Q>%@|yF7^aFUrdxZG(w*KiA`ScgEdAU*^ z9V9MK@w*|qB@RfUD#ebyCC=&7D;2_PwOkTEXA?dpliLo8ei$~*F@7m8dK@ScTk;qA z(+Q!iBF;+&Q}~?uRPWc%o!n-x>Rdb~P&$3VLNq6vWJ0#E$q-@*@Sf9Uap+O6A44HDjHrtwqY6 zR*xS7Yn2T--zdA26R8P#D;QlN7yrf$zSv)1b}!n} zL?_;hqT|0E2C`|tO4-mCb_ib9NJ)SP8Or{dnq#Du&_|)=OqT18qkMJ-EXxVD@AfIx zl_Dd4$QF0@_fl7sT{82c5%m}(jDrntT8;W$dxWuwWbVvU8p%TVsfj-_3o!R+l9g`gm|sJ z5F`R>BK(_-id1W;HR0@b^Sr2dBYy6h}6h z&l>C5lc#TTotXt{HA5of$~D-R$h*D! z-BR^e141)K*(^<~b7z0bD;(pP*@^i7bMhiaA7 z;?%3n+?k%H%Q_?}_&aufACJ9%Ew2mc8|}F8L+^910Tbf7dt#JXQ*c`vuv+M&|ul+XPc(PZLVln5Kxmz zO-Fdg#-{{{#oDWew zPg>OfL&VYu+s<|Ia+qk%A#Gdzn^V~2{ln*6bNXzRBpR@q({8ntVn~#jkla&?xm~>y zRBl>*f#dVajaIj=Jic0!fkM=bvak>b#6iX7gZ(o_s%;pq(sb?J41KpythzA!gd$*R zh9r8tpLMPMImzjrO9ov-_|-1QgZ-)%w9~c({cLsgq4Zv@w_KA$=TNWi}BlLb3La_w=hC=q{(W`HyZ{>jf~64Hc!Gl=c;aY|95gQX#FsiNpQBeq#j1QxGp)a+Db zZyRB_ysWzc`qyxF*Z#KtN(ps9%$blGCr_KLK&eglL?ue_hdWlu+Mh~0j54772R#OM z(PUKCL{XE#b0^CARhKp=t*|Dc?Vq&}0vD+pUA^?*T}OPd`?|`H0_fv`?q_BCySsMX zaUK#n4`2-*ph64yOD_eAXQu?EOcT`K9uojH&{m-JdtS#{8Z6zk30k`bQyRV)LBP9MVi} zWt#cFCF)Lr4zNiFd3up2OKb68+n_85zUYNC zO_crd2ORt&fiKKxZLN)tp+`sO49P~k8X6sxE2ciT7~$6Wg^=^rA1{E9|7rFlWOL~! zh5?M1BXZt2T{CSc#WUE!_dmF5i_@sA?#Ld^Tk(V8LE~_BZqthtH=J7~WV8m~v#Qr- zqg>(LEjX(rkC zt}i(8iaYJ%SUC!1IyRUnIafncXllMvo6p(2^Pt2IiL^FP_)A_V%oQ75%yw8f6Wi+t+^8=8|pb>zXK{T*?=Mc&m6g?PG-blK5`M$0~A zuW@p9R59AHZNE!e_rlgkr3jxf;JI}Kv2$hgztR!e$)9J~bYRqTflLKL!uMU{!e;av zPGbIKyTKpK^LpG@(=LS^1%JET*BUXc;zyA>DLZ43sf&3DLK#J_9M?}J*diUh4k6Ns zhk^9^$D(vb=-&DSvm{aa+(Pupk+X)Ucq$h<(xfBCq{#D0_yt@t%(O}%ugFhIyr(?) zqL6D)tnus3(bJ0avU}rAGl+c1IUj{(#qu(wY=2|C$fwSxione0$VK~tjLVmSf&`zAPuUaElo9X?fL|dym z6dXiUjW5O~Ev;xIV$aQxlczhnzAO!QhMFN&y0oKkK)3du!@7N(UUKSfQBfAQnCSFpAe9TJM?p9Tsg6BZxXp9 zjCVA^PZmNeHjQKJgWYu`A_w?EpsMjIMQ^+91MPDHIk})Aj;Cq*-&JcLnTxCdP8XM( zp21#Y9L+&JVz2wAsojTBQo|&ERdg#}gpnnEEnsam8?A)ed>4N$2h$XBkIcAXFYazX$*G%Ggj*Q&DV0ZYC#Ip$n2nYi>s=%EOizW_ z$-!7webcD1O>`9Sx$KdE(Q0!eMem{$niTw<>48rDk|;^mS(EY7Cc`yN6{dCH15OqD z3f;ERJ{y8%cY9u*UR-_R!E+@pv~-SqUEJg$?QC7MWRu6^U}{x) zsLvf8=(Fhv-!V+~&pF&$$n^C5*W>U9bz3JG0^+Ey%<6d zcvTfV{b>>vLvWf1|J}ROsE5v^MOE2QUA#!sLr9dI&dCE#phLd{@tpzuK|20%ipuy$ z1BPr>>%1Xplfx8QTX}mK8P&Mr!i%LjT3H3}*XEqrb%#E_%*?YTRV#M3XHzJq{}Uzh z+ZkoOdJAwcxbM6w&nN||G|4IYJGkqm-4Sg2T+jQ|v8f0Ch4rYW20wvl7R=v1H=y&m zuqk0PpI42Fsq%Pi?{8AMu6xGt9UWZbuc!ZKR}rqZ_Uz6aTHAGwi%!65bOxmZJwUDK!Yd%+pj{GMdB=&e z*cC>Y4%7D@;z{hX+2Qwd34=KXjR)Ji(KPKdyP?~)u4EzY5(_gaq@kuO>!BVBv&Vu| z6$JA??Ohwr$Y;)f*rLWT7p z-c8!f4zFo0Fz9>vKhe>hJWzgOZQ!hy4}|M&y=v%-;^=y);*gowKp^+faJvvnJK5w|(%`wtF`88~yEAaiGYr1(Q51?am zHXLlf3 zqH|*KgzWJIcdC)ubbX~?&r&Qy=-fNCaH^R7A>)cTotg{VS3E+SadR%v*NnPnpPyiV zK70Uclo8QOwtIzNZP8yDh(kYKvB-?p(#|_fJ&ScN;vJ30=`9hPpO@V;Z)ZB z^W)lblhYP3%FfF&+}U}w1`%($qnD9occQ>Y*FzE3oo0LHm|VVwBr1%BuLi0p4z$84 z%=F%u`waN?bS6sMZur12qMUc5CV-weHiiza4d4i6piJo?RisfKXQ3Xk0D9D^hDsIz zg}x`uz+dfQiRVPTJq*IIAq6~Qfb)HIg3>gNGmku+?@as{Cpg$OHZ2*N!8WB}6I;b& zsBXi6QiRn(h&1)OOoiBc8LiVfA>uM+`dotXnZSrn>mn7cF=d3=6V>>w(@i7uvo8GW zzMv-^nnoG67Yl^u=o)-kHdN(U!^wFWCSUXS}1-0dZf1z?rde)KXs zd9k+nu%Bp$?GT5&PGfFX(TNP-Mp*0vGH}1AB120;RPd%EjX^QJ> zdR542^RFtF*{r5_`UP5k)MOL44Dl<`q_E`3)|0o}04#2qz$A2Ie1L$*-sC4l6yn@c zq);0EcAEw8ri*!_Gf{7xn~d^B1FBb{XPnGlP3e@SLsvU(>-gBhd=wvq_=f+1QJ&q; zEH}}I$f~nrdnq+oC_2DeLU2Jv1tjK``ANhUzJ94fzpp3b%vDj(U9s4$y5=GfKh6#e z))o$(IV>(;N#U!W-}aMa54|{$H{43WZ*NOsreP)Lb@DIw{iHT85Xn?+G>tvN6`@9i75uDJNetx9y(4iJx$QGJ$ zp9i8dbw18!;B7e11kAPhViRq423v2n|6+Gj&v$B3t(!we7n?6@sORi z4=e|r#eKFM;tJD|q&Rraj(YXQJb?jC=j)h#)UjJny^cGFe0=ufl|aJmr_v6uqI@jj z`x9dlp=EtpcNLX-I%%%=6j*v_3x#zQoV#w*X5T-UIi)VIxnP3n6$A1r(qF2Y-B9mr zgd2(GfKI1#rqbsotNhd;jOyz)N&p$HS0n+Kbpkuy8cS7)j^-pC;h z$u3q!z;|R_cP(Hj zh3XQt#EH^4&Kci}qOjn7TEuTpOFbj*yFot`nkk!Wy+(JbrG{u?ACu;@Cw7pq<0Bfi zFxoElm|ttb+Oj@MCDY=CCP(n*?U7~gvCW`}CHLA@y~Yn5@^B=nPe4^6p3F?Id0V?* zvTk)1F|jYTar|xxq72`I5AMDc(Vm*UO062$rukIxHYg}pgj5O-{`qOXmDVz9PqxIAC{lc+S!#d93 zvp07Dv+2Sl-!b%rqZnZd6t1D#T6IrnGFockX%Zh$n0i!(u6q8M+bVnr@VKUF+g#rg zFW1*Myg+`tsNvgQdx?Lx;==!%;`f9b5ERS=B6bS8o|bPZvk)p>xyQ9bq<=G2)6T#R z0WVqZ9p0zwnZu#2&ZfoiLZ3QxRrF`b-dyY`RPIQE0FQCY9$d1p+Fp4ZML9#@XT(k! zmvl!hpoPgr{JuGjT6$VL_W zLXF69zdgYq^~_vH&pp>Z$_IcU5Ot1A8}_<&OYqBYE-6*o-)ZHz- zV>{kHFn4>n459xpUbSD6I!7i~v5tFsDozohZ*XGRu4|Dq`%_Jythh19NsPa{)wI;v zSNWmv1@B$zs2=ocF(HxDJG~Wt8^AN5+pi56I`ThfB5VHge`xz#RKZ2Vk6>swHl|59 zPTXd3Sm4sEAq~CJ5vje;-)nfW(x);=6+N8idNgIwZLD&d)b%{2`kD+J-lNRYbtbjIEm) zh$dhBuLWezqfo?$DP3*zlmmEU{YlWn@SY?iMX5--vu@uUF02 z8dq%V+kDBcsvKOC=7lB9FFC&&=XP|xgx`2G$H7YQ*BoK)gbWm5b_beziu+P6BUAPp zHN`(>vPt+|ng3Z*6~FisXQ^tpjehB?ZkF2F(H7MfW~mlip8)Xj!`A1nzAT$qwf^a8 z$XW1m$X(Az5=1l4y`GEyHcZYrFlBW$8E1^wXSiWo0edNosF^4&gO^+f`WCsMYIriJ zE$1UAE5bx;d@XMZ8s+V1VJSq8h zY*ckbKMUs(Z>Hyhr*CcJBP(I7Yx6-vYmD;6E?p97r`xO41^IqWFGNk*M3o2LR~@H{ zNUbqUDS5R%298_^|6WXMo8;m8g_#+=nVqfmr?zlzWiOn^;kh1i&rBGfi1sMp$EU!z zOsz_eDm?s~l2H@oqmG^avC2Sy@6(*9)LLc-RKU>LdQA$8F9PVRL5-#9<9=zMe&h}|c#iDiN9zgCZS1(# zan;WAz6cG4)9pHM1gzRMrg_NTH^L5Dp}Cd~z36^46BFvonu}dso-c9cW$}R!oX!w8 zw#_{5XO~|t=xpk!drk@a(qpXwI6kyeeaQKE^QMIcSFu)l2iUj55C(AZ_kHopM(GG9 zJ2mL`#L9UqLk&oW^I@U%Nek}i(X;sG4_t|LGsrrI?>A0chf$;7|3w}Mk)t~0W$!HH zm`zv9bn;C7w$FW|rwa_L-+vZ&~sRTbIoxW6N*&R&>73#lwpI+HnX}R2N zZi`Ai=P20UCTXaMDih*rT`Wg>65U={?SFKJlPMhMwfvP?y_RykKC?IMwYyPDwBa~M zEhfKwFa%B%DqSU`PdQy`1Svs%GMtf?s|(1yF}CqdSU+$W1n|4pC64RN5ozK&Dw|zK zU-6UiA9q9mnO}kGZJ^<^gKg8$D|Zj$3L`2`RkxRd%I?>+Zmf;2X%5shmqH>Q)TL=p zJXN#g+w7jMNiOm5)iq1RjJ&7CGDXD~m(lhDblVgm*P+*==jx6Q>LL!a{H0tS8wyus z5a$?*U@Tl8GhhGo4pcEar+=usl17xqMfS0L0=yrfG}ksgR403!vLIkE#KnuRE?9U3 zpKlJTJp%-~9aUYC2OoA~B&D;*7wD!U&NB_JZTL%oPP(0rt2b92{R5&8?*l+4;?RGA zsIjd;Dqt`jXP4Gl31z)leg>*!IAVJ=4p9h;{0MADm#DD?gRcrzFA7tn7}(}h>w)I= z49>dkQ#JrEnR~8FVh#wkZp}`G)fl(EUFkK%hax}79oG)4XUsl$_Ay!p?o?c!;Tt*x z9wBA;1i+#`zGLG)xgj1F!)c(9o1un#}QI5 z#^fu!SFrzsQWCdnX;P)hm}ed+vSobc)70y*Os@1bJzPTMG3Zx3wV675uM$sxo9`;6 zAC38mZ!_FqgJYEe`Qv9uNu%(u`9?vjJ34P1`Ft(=)N<_cfwq3PL9%iZNL3~$w&sda z8}Mnax|l8;9mJNH8>P*z?TE(5^R>N9K671W|0NT7Xl$2^fEY0|07q|PAg(t+l(M;njoKqd z-lqfegNLxx3m0hqI2<6orm4j$cCvLTvQL9e<<5OSn01YLGh6a7faf3rqGT+Da|%m? z8l~UZOYinh0j?PRn{^YIg>m;x#^oUjoiJ*Q5MiL;D5y(!^%+xg6{T+=~kA|PDhe3 z;||(%!?igHIRFRpi?hPEq1s8fjO&pT^E$EAoo2C6Q}v-WZAVWhgibiN7RGu8kr>!> zOZ;||O7ThWlzOg&t{H6 zp9|NbEBz(?nTtQuI7^68^_A#M0Yr7<9NIl~TJuD4l2>j+?{In%4eced9ej;wE}&9i{0~4u(YAmu$x3Yh zHWKB|FpCExn^N^m`0MXjkDwUI= zZL>!lkq$U)3My5-jM!1esGFLSnJZg{!kB#nu7^T!kxLXDdr;+eXAAwHPDBhJ8d@H= z_!2LqX@(p$!ase1+L3-4h3XD5e)cv&9Wkhy!f^-FqQ>A4W4m{03A4KALsu~S|OF&r* z^$B|kGpHGhz)+xO{^zKgP^ zd3hJJ4V?aqU8gfL=|$?8@U8FJjm9uy{p?;v{SUsDG0YaX&pgv%-J_T1Cko-_S8LC7 z7+7& z2YtQ#VIAktmE(4a_yM+C>Do=riZd_-s?-u4&G7@E@P( ziVrp<wH8kpCgY5AO&EHGjXI>%aB6%(Mm@TyqVDfo9qvq5}+%9!dkr!wFG+0UNwI_Gr&y8vd8sV_rHo^zzReuc zbUl|}cHPaQ)TuiN1wvbym>4m;f`0=LXJGfPbP+O$^b8sWO)-NI6HTetsroO zn;1hShQRtHpgGw%J5d9>0&IW>7b_rhF_kXAY+qvB4x;7A=6)d*aUZOueWwoJJ0-P%*qN zZo3go)u=dK4F#AZ8PfWsZ*)ckaXsnh9oA=np65lZx+RC&R0y_#W&#p7IHJo4KOy%Y z{|Eq`JpTyXuC=Rh zpl?+qms@!QObq~m@EL;&tq9>yfXqD#-o2k2Yd1peY>Nnf_kgp_lpTiUdy768Og%j` zRz7oB-18*m^h{i;^aII|)PCd^9(<8K{!~-S=VbfDX4A+SL;Y3=V9lOoYLJhx25=bf ztg882vi0UKz;v*VvzC_&IHek&MgX4tOZfRYzhHUwZ9fox$KJgn$>`+^+Ap_WUi&oX zL#cNAlZ`az`c-2Jwa|$V#G!0dyUsj$AsHXobO<(@2=Cmx^75L(wd>4T*wpQYwF@&7 zlL~VSje9NV<+g)wA}*(i{9=}t7ACJHLF*@jk=N*$CW}sxC}-;jPuOjCji3X{ueqHe z>9TYj161)W4`EjheB8k00)>eEhp!4n1Y}QS?$CTPwI+|vF$ZrPy?Q*@8g`p?VP~BL z^d;o`&MlpZDcr4I$~jGnmAX8xMq;Q6D;)){6s&~*m3&G`IkC(Oo-%)SucZTOBzxKn zyUn-93VODhj?ZA>V9bm+BpgLKxg%uW)zt`bH%^8Qeq(%$l$4n~4z!|_Bw3jlSU3#b zbG)%b48vUX_l$hQQHqFWt`(x_#t1!Zd|m2vmK(Ci=HmgE16TZX4c?#u1WNEvx}2^X z%01|d$P=gip??+}nHn)PTtOhPobu(FC@)CEmiIwn@pwZECDBj$cSng_#9FG)F*b42QlLx4!&H?u9{_Tu4 zDY5+m4~^FoU`~572+Q3?)hm~+=Jxe^=kFLyK#{PO7n~GJduq5ag*O+{J4}^U8mbZc zA7O*Jrmwt(9#)e*v4?T@%kK|!v2`m3DjHpeR^ML7kI}z0oDmr<(nKsKUKpqAbIHdk zMm{%~6AY47Jt1Lve@hS1p_|})i(2uCdVYZ{8C1=88baHc#U12qP2uT`U7Hj%xg8Ik z4>GG$_!4@5a_{);i^$6~1gi9K2KqD+`hmsk!CkZ6*!l&;&tcC8&H{(wCVo98woUG| z;1t5!sn2z1uzJU$buRHRx#EsAJVT{!&2j!RvrBE$^v?Ps*;ic)Cu4562ZBOV%ups{ADznGZUgnvWX#4qe{2(BPRpnbg|@xtv3bv3LPc0d&*{ae*uq(@*4s z4y_~aAlFNwxD<_uTVM@k?PcbKGwsPFHq>a~(3q|qKeQPuj)^+z@=v%G)i7dRBgfs^ zGZ>n+S4!9YX*!_r+mjlU=fe}IS;{kS4Stquaj!mKyLD#Z*!3-i)K=sWf5n9HEY#?` z&N$lz^jyouT#A)~HS7HD6Ac6F<9WgUF zw(@AG5|oZ163+Nk9ed*$tY1`MX6myb1<^3Bf0pHLqZG+U=do8W-*g%nSCmb_s%8Y& z`-Xq^sEK{at-6a@cT(PQilJK(tHRWvlyiQz9>w@rtmY@Xcq0_bW!Y`7xmJl}D6KI=tS9m4LC=G0XYjjr?CM$coL657NnWVHwKt+u) zMYylZMYO{ALaMwZcxO2guZ`Fno{0)0>ZAi2$e!rdDuUZ-5fSW8)2OIj56S$Mh(srQ)f;)wIR zA^T2(_7d7IgZ#?^e|qnGjPsb?!cojiScOR@`|>C9sIJOCytEIYuNO{NBxTzldfqtm zC7_(tqoxt9*&cMqu71r#o@5pu`ED%7mTPjO>!OuSw%k|5N>HvHf=RqbBZ04^85YP8 zK2Mts9N@WYE%+NlD~V((@XRoD%?p*ecG{X!5yOyrhPJj&LNYX<;Y;r(yl#HK@_1S`&;8KurxB+g%gX-4H7@?E49YomY&w$>Gb1rroR~& z>ziTY6FTN79_z}=;uFQ3kzKNR`Siw{g;0du?qo8XhnrmHBnJpYr0eEztyujep>q^AB~F5$>TTUy{MOU$9kHqlTv@*}uj#*3%e^Ya?v1UxLf2m$P zT58bMWXY0#F;8n+oK(J$wo#s{JW<-Oulf6-5^24*i317l@fuN@$Lo7Kw&TBkmc*Yf zNN1W9@d<@OGAlBlFO+}N<+i7@j4ala{bMRy@mc@kr6JR7ynov=xLCvaxAQh!ZE9S` zY-(H}Qkc5YK}ZVg3f9x{O5CcXPeRTbdsuAAm18Vm%w103&>arGEgdF&Tpo8u3%64= zax850p1+}ic=vN++78?;?iF;U)RlZRL2l^+zZ5Pky_AfzEPx1_M+$pz_{d11eIH>qLMXn!kts2zOXl4ZVBpDM_aH> ztDxy6PmW(z{ghy;&{hKY)`+PdCAk=jo0MM|}@X$DZHe1NtQrN^^hT%69`J<6MW3w*)gS+BNUqNOBR4Qf#Dax&4nEa;Y^!Frr? zDlp`Z657Gu5lfOlADP*s!eBdHx1=)2y*}xNP`g!Khe`Vq^slwLA!;p;)~IYlj1U6NXgOQc$43TnJnMw!G*hE*(lEcBha9_iGItn9=JopUv|#I z&j_Ks+&Rr>hfpZrGv1&nxp2PZCHqzKs1JD_l>jT9f_9~@wz#8bc+6%>2B*sIHKrEk zeG%?_g=(VO9ZSxMTH3C=Sp_i_;(Z=rohUBw8xL@(?j|Ag7e;MYJ!o@BPklD?IlViJ z{fx(}7Gw2^VWTw2x!UIQXFrcO+FyEvUH9uZUR_O8gLE=5#3Q+JLBPKooY*K%Z$ZE< zKrg@L?qR=eJt`#3^ACeZy}tKA+2E?nKGUx~jy6)&UAs2S1dO}7_$Q*Tm7w0G<7(Eq zWHDWj{ZD=J3I)s`=R<75;1O>`@%6nXV|bfh6j>Gt7@M1j?^|ZQCIcqvNn;bZkss+4tr(+{3zW8m(@G-`jkJ6Ekgg{>Z-Z-e-r zP!#dMpv5(L2*ofNykFpq`50jZtY=x$PN#O$kN#ALgIy7IgIw!K;iTW95lsH#3$!JL z!==Te-wm{1JmwwzX+3KiZe2(pWpXiFhi$MrIF+Wp*byi{TdR{@1AN7reO#a8=vhpe z)Ib@zpn_@1!|C;1j*i27^WGuO&jve}N0W!T1{opc`ijBy z)OOzTdT?tfX%SgW6DbXh3=|N%B;vX{1j#Dl4Qo%mOlq2#XCVY_K2jZ{&TGkam-w7O zma=;X+a6|1CCmsKvhIHW4Kv7D{{DCw`(zu=Vm`I}uG4u@{n+jaW?>V>jY82m)qflD z2bqGKCOGHxa0^k`Tban)HkXeG^l>+pEFw{SbQDBv6tDc1eGGg^e(Ymi&dSgOH%na9 z-oM3n)4+T#gRjya-2LRhxGh0jEIEy%R5aQXbUzRCL~5;O%t!tJueS-lWt4Vaz|Wa1 zXgQG#Z-4P}p@s;ET0Gip6!MdTgk^4A&+bQ_u4P={DP-gMu`8#BOmD+GBjKGDEScDA zB=95xa=&YVn2c+ng!)p2u0Jh+r)9NmehHG(`13U4z_L^qV$?+gKVkT6k489}m0VP_ zT@A=WY&nife3A7X9_YqN#>btmCh^&7HbfV{@kVmzH#q&yOrZ17P9>bx^@soz9F-nc zk*=1lJJBq^eX}fquuca85OVX~6IP=x(dPGHS%4u(Q{Qbv;wkMSI~5{JIdEQotx zP8u6jL$gY0Bv0M;u3@+pS!|6&7A`H_WgT8{_3>a=Bev!crm=WshrUnA{N6;70<;(HX9Of36t$Y9>c}snw`j!KhY8!@wv6$+VO8tLUTtYuXf3^5VKJf4c%> zgNVUpoI>qy>NwMuArXQQJ*z7C=IcJeefm|Fz=QZR^Y<>|cX|d<0*3 z?T=jNtP{4qCF`;bix(RcGV%zTu{B?^PoZGibXNz;)@`VqlKqS$5tV9URrTw>E!=j*Xbk_V>DR(^G3(1o%;c1L zkZT$}WOt%>?oRFzD#smAS9d|Sz7eeRytBt5kws2P?oo{}M-Kg?0; z%v*m9Y~mXM?6s6-__-;}bT_pd{nvdz%%ou1_}lQxZAV`vw0&HR#*m#kiNZT@u?t+8~mFIQX>>BC}r#*9P2gg}6II_JJy3i9yHLj8@+$HninH zS<%#uX=Ac6JT8-yHdDSS8F`i|`g|OsPj*&@{F$kR7jvCIuFzifTK3R#NTde8 z@^J2lO%$3Z!p$X>mYdU3ZNwn_&GlA%fKErCKkWOp2Eq_u6*Wj|^B2 zj%=*ZGp+f4*8?f`Li^?F%|)_wC)h3F`Vxr#8`8ho`%=gRzzh1w(F+htZ*2xk;Vy8+n$7#Z5(vA55~X=@PiTKX+JC= z`<8txYbt)A3^*u6(H7OYn-$kGnIi`oH*-$p*l=`^!( zMSq0jqZD*I6R7t=UR5Z;G9jWp;Cd)vq0@=SAi z4NhtWg95Rp(aw>NF)Dn)g}qoaox~amxn=gw(vJD1;Q`d;_={?*w)z}~Ld0r~e+7t* z1M|Gqac$5YLky~a_%7RqB%$>WSjWXAb72q5)}QZPQgfiw7KAQ+x9p<+mL<~p4%Fgk zORckX=9qocJ@ivn$?qGpf}kr-xZI&zl-=fNbDecTHvp8#VBB-OF6-8#r&N+tkqNeX-&I zDxy3#SRT4j8)G;YC*7qDl}MCF*72i?wC*gALM9&R;%Y1QiQG*d_lj6t1N9avl%`oG zX?iWx!ko^ajLG7Hk9N%RMwh!U<0R_1Z$_qOzDKN7w+g=fHh$}IiA(b_^7gZD6pvi! zH|d?!tHXmmypFGNsY$(j+=7J;u*?GI|4aG_k6!v2afGeUk5 z1e~^(D~7R|mhp#x%dsQ*m{BZ{h}iEPu)Yf#Yh!sV%#bxn&m6*2Q;PQxD%Odg92-~e z0uVk!JcZc>MRGGGRz!4&%iUha6_~l&GFwvZ)#rL@2gA3R zG50lz%gkp#2cBQ24Jxc7dSC>W8|v@+f_z(WiWg8?hKQ?Lxx-y_^BPG1-0vEEAm{PH z@7jWTwP2a1iB=LOMzTG?)AV!* zV!9J1+V`> zY(~^MnPwtaSB#d1>-gD2)#c`@4t7;%)wVyzT*`!9aFK$a&CE>S;U$D!huCQP4Q)L5 z^=u}LC4oFUNEu`rP8+DXEQZjy9Ik2<-dj`!o)M<1kSNE|GRfc_X=mCj?yN>nYsa)q z%YUXJ$1uEYq;|5P%LA+dJcqTDGFq!=02~?XdW1F*O|(FFydvOUp;2bx@9Z-=1HD^Z zj>x;Rs>u~L7sE>ip{~HYBdDz@|!8ODs#xt5BN1Ju8}`C^p-cjbKkwcZ+B+Y zaj`fG>F*yNC!9A$lO4h779!YAZz^OOKxiSkfxO1s`!PCw%5p%20&|M_dJ2_W1tkY) zP&}3}^n0}4*^@cE)e}>k6vN9{D(hd@SW3_XX$opPpwAdRJ9tc-o>_-!;VnHF9ol)M zg7m)sQnVws#*5?47z4!ux+>xTS)K%@DLKA)&m47Sf+pIMCqDddGUPWeQJMGcTux(( z&kn%O;_>2wKtdG3c2}~w1AHC86h-VBYnIx^Fk4hLykUr@I`AxLMLNd#+ z%$xK5U8+x_2WZcqmk5)}VrI3X9Kj{nr8fEX& zu;@2a{dfaz3Uz$ailUnW3sRI|(}z5|dAp;9F&D;0d%o-NJ6ay6ci+E#47%p@4S8EO zE@#N|jC#SUR1~KqQ%y+&h;|y@L0X`*mYdiSPZjuO?lV6Ca7+sS#KNYy{u!7^1*oq4 z?rI>w7z`JV0;oUr2E^-jdgjH==n`3%_own*#0M+r85$vE<4R|3mhi>9@vBqn{$rf@ z3$^0R_UT(dn$(dS^-fDao;Xl0d{JI-=0mcQS}_Z#;xldNA(!lvU46?eot~wI5-y*H zx(rW0qb|bNH3@kqy{4hl)C$4(`j|EQ5X*==T5h%14HKEKUyCghBro>$ zGT$UjGCP0$>5tk+#e;T5?GlC8nR=TtJ7-evK7+gAqwpV#ojvR~&KyJh-?7J{^^>0Y z71ZCrtUp;CJLUuhB*feef=7KUCqHjBo!n52+vaS|_8d@z4lC|12OM&JT$&_(Eg6~u z703bT4Y_TBz%i4L0)wHf>wTP&7r(2ICbN;N&U+}4>>t-Bi|osOz}BSJ0hqBCFk|qI zNMV1qs2@tcfZJ%8M?8CfCf49mrJx%jo&#x*4N&>BiSCvWVDg?yM>`PB#H5D>m?kjX zH8cGhG6iLB*%ai1o3vAD>^qaI;qsg=Db%6LtKg(m2j@bRks8i?a&D!l3<1aN%R|BA zF|q6KTv{GKQFn?E3t}FSdP1Gq6l{{}EpaqPTcf&Z8WBc!3a|x%Y~^)CR=xDx?({-= z%BtREpVxG0DJi_65n+W4G_J?*`eLL>Fsu{%$+_{DFF7W{$~7^cUo*fw+WyrKMO>1Z zRM596xR8b2M}t>7V{k(h{|EmjhP8U$m7QxC|42{VT>fc3N`~{4qkp;DHS8;A`toY; z{b%{PO9=a(eM({KlkF$B#De!LytRJludi%;;pqM)@bT4VfXg6AeNSQxnE(%-Q{w_N ze7p)~0v2@k-L;AAv`-90$uPVm?4L+X%wCbg2j*Co4PT&wXWL|PGMhkyw@3WQ1SG=3 zxn{rjFNPsB7!;fU=I@q2gJ<~UHrL;)vsB(?o5isIt=zW@v>gup%dr2z|E|RFpIaG% zW2wWb9huolNZjey8U;di&wu+}^$LwFrfy3y4Z}F2EOBYrsS8czH<_r)9)u>^ow~#U zSJN}vXtf#9XCW zzJv57PfPSvD;LCc55DCMQkl$kFQy;uS*{4u*#Aqz?_8aD2=e$Tzl)~&!&edEVhYzy!kMq@>xO}U7Az`1S zG+*~R`A-s%TVSK)VJv494}KOk|H*+{oClKwi^TW#^Kplt@J(QeFdKVLzuky~*&~f~ zK_H1n3%`WiS&DvbSY8Ecgn2WSnee_q=%1F`H`D8SM)baHES`wRn6KtPBfaUYYF7_d z3_Eg0+=NZ8Y?y99)GSe9!ZPvVuqZTQwmF5lm_0P-QVlN8>H09#Z2IiB+W?yE-`?no z*tixLppV}Erlx}3F?nfi5)hOlA}M`FHba_eS1E0bagJ*5!E4gCT-s%L>p55dxT*G0 z1vY9pe%txECF)$`bT)abLS_0`7Kqh9ngWo*B{tk|`<*FR->*6vVuaC2Vh&2kBn^DE z?)3Wuz$CFEZi-!HTAX^9%h3jjF<1}O_%ufE_WtIPDxp`!yQN58ikm`f zG3KCv92R5S_XfWTc(s?OlxdET=XifwRpWVGUoSmY`KB(o#d7Hn`u5>RC+wa88PVn% zsXiptb#|Ty$Dgdm8>ej$bdGxObk<-9thG{v82{LG>x=f)#Mk~%jps?grM3%i>_o%z zxHDDQgS7b87LH`cM|P55WCYQ0JZ+vIrUS9w7M;JFQ&Ns$3*>Dm0D>)TBQGl1^rvFn zX!G$DY!47H@|1L$kNxfokPCfzvT3Mo=qcYvQOiRoa#_+nme>$i?DgKjme*(Gg z2JQ4zD}eC>>Ix&iN@o-ns_l2dO3?W3#tU-DU9*{(_|>)sYR7%*5^S6|fdvq1rd>W# zx|Ffy6j<;=`;JPbT(NNBKLp6zKaw`fz~Bc0XbC1$bIdSs>;eO#Ky+}c$l&p3nDH$E z%cz_9;dZv=y2A1xPr&Abv3gp{aJu_vN?lj`8cw8QbVzLl(kiaDB@D~mKm4l z!14IcO4<`x5cLi<*j@S!8T$%6ni)&+$%^`X?S+2)rxa*s7LU}ml526B7u!A(msJ~7 z)m7X~TfR+l-aaH_l~#w_LKO4)(4d?ma!}g}UYsU>SJa&ytuHk+lr+vK-;Q{t6)z3d z1rdjkIA4?}iQgp!*K24Jy^{ZU))>|8qzKwc51f=)pW72 zOw43zUW|$6)*$=TUz)~*X>o?yzqWazZb%a2(I|1L$=dJ%ZDcGu)i!2C~ zOFQ1Joi@YWkKd<%>NVP0%;K0!1?5x1h5wjya6LWQs2gkd>W;sWc{s!e0%~m zsdw4o_n01lQ9^%@C4Gm_?b*)n30ux}Rgu8<3?wq_*ygi^rSH2h<*iA$`6dHcwX zt1QcHnj#W&zYEF69J#dEN@+YKG#04*>P8a?lOajCaq8fs%}2EctF(Dh3hOG@BWcz6bt^EmO@tl+63 z^i-^-nUveU-E82|bX43AK4XMWxKx_ye1TJ!An+!Uzuo;lacYRIBb zrUx)XvB7=nwt(1Nklvs z{J`rx)*>}W>eLd7o+Yz)q#QUQDVTL)U6GSLp_h?XG#NgRBI<5n;!i4*l|4cXBrT2{ zOls@@3IIY>AaWgE8fN`jC@LW&NVaXr|FV+a;lqBg@WASGMK%gI$bd9@-}~kKPkaz} zktl6bjnwtas%2dd-)$h6J*BSHh>@8@2uV+oGe=Xdc$DlIm0;~1u!VJRzg^gi_PUL- zQ9N#LgOb+C9y2xsks!JPMGvwRVP!QQSZ8Y;jCECK38g150m(d^I zuX|d0RT>WXIA;u6GaIytnaT9@-WA<_>Ru*{1_DlpnZQK#Y~Awjb*dA-2tSYF-_5kx z4*}tqJg{x#Qgsy^i(={DCcLy~TX#}o9vazS>iYf;X26O#-q0Uz)zgu>Z zU6@zTmvjLF`qi@YyXjB4c>QM)7$3%Z*JGOUJ$xF^vTsw*)r$%(C8Iv48;Hi4pw~nb zPRL=CpAvsCTLQeT$5Ot&!O3s7&ck3cY)me;F&LoMqc%@>Hwouc>Z<1WGD9a0YB6Tz zK=5d7b8GZfqUyjx%zSs=zL`16#nH)om_Tks=Uv5^st=b@Uu5xy=&zs!g%WI>x3|rXhej5Q5<(`{CKE|!Q z_wYCcr|9W+J^D=Vfr4w60{t4KHBG5W-b-KUQiXndtq!$0{_WtgHw1}XGG2+{g_N9a z@W6AQJC`9VM^j9T%z-al5yZODTM~=gV52=V{jVKl0wh+c%1u_lkg4k}qyZXQ_{R3B zLst=Ho^FppCpM7}aY&yRr(b3Qtv!x#ZW)g8DgEA;wBezK>9avExH&v?){8BjePd)f z8&d=sJ65goO(K+PJQnuAOd00=60ojRqU$^asPd}`?}Vwnh$*|1N%p%4TeYs~J5t@L z2Z(6E`j^M)kc-kW7yxFsYv3-4fd+-$P4FX(Fn6UcE?gpx_$!@NZIymwxvJ z2SpU7Pv9P^6_XM9w<&eG{{uDLa?51TT#^L59|_C}S|4RqhALyw5F)^zpkZLJWkk4{}B41Xe?5=^F@_)S=&Kp+Mef|VQ-JU*BSFih-K9&vq5GX zrQ}|^Q4u|(U$6D6Y$l5=>1Iz2e|3mGXfkf8l4Wre{?*i2K3F7}@SDp;-LJA)KWVaE@qbYVuD8VtAc_E;=Ezge=F z1~(X6{qCPu{=B4Chqwuk&xq>C7tD^y6sIN+R|rqrs`izS`v3w-7SoS+)Vd%@75oiH zWgrsE>y8sV=>(HS5fsboVLBHD_b*=-QKit%kjE^bJw|q-omruJ>y|EZoIluwe`xH7 zpS%rR1|INQIJiZyHx*LB?> z3L#~fU}FBjAmGmg0HnFKw}zKqizFI53l;)xluJw{?SU$_RP&rNALX44ZOM-W~BG{T&_7K^% z1RsJdZdY<{Z@=2!$@*ovH zrM0LCich(=;(qr5?22|&k(FX5(#&i>70e1iYFut#3{r}LQedRxzu@TRL({;;KtbAr zks5@+uOZ=gF7AUgMD#*bpx8U*w;c&!Z<3OWQL~aw$UL}~@d}V2yY<6Jvwme+X1 z4mxl0r`MpM@vkUoLpd&}Fz*H%2bTP^DuQNQ>BrF?q_b zj}sMx0D^uuox$u)LrOnI_F>6iMFw*NZCq`|iAw|hWSFj{-U1V?9{a`3)!rRc!%m9L z(&U0m`h3#?EhFwiXW_K|4*$%fxZ7&Jk9dr|cJyp{J?kFW7g4}0nZCH|9^NFu8{Ns) z6`vR6PXy?B1GE{p{sj97FRf2!)==S}GX|!)ehaib_BK+$j^!y30+xNhsn6p!+^9lTe(v{-Xu`m zHtakgHb$MxVK_bGqc*Iv>2b4T`WJBxH9HRl_L z-ucfJ4xjRm}wZgZfIGQG_Cs5F`3uQ82O3GA`_^WF)yi;xGWpB=R zJr4?lNJZGyUg9gV-leB;M1C>z>bjJ%Dq$Y7>xca4m_Rm!0J(X1k9o^syy{_3DyRAa zRTP~`s}KhdiADBOE8BWZqV23BMJr17I*5BfRY~KRuKw8Nu4I;iuD$T?UW%DelcOe@ z!+{mFsBk38*z;^P-9t*>%)N-;8uJ^=-(NIinJg8to@qpUI^O7>=D|4$@ zNrT`qp@4X00P1_21N=-#cEwllXb)`vwGbC<@c>9U0UcLD!)jf&!zoJNMCT?^2sO<% z;Nm|E>?uxe=o_df@G=H;9IcEM@}IoLe>twysdNh{CI}GjZXktMNn8eJNea@LipLD1 zykfw-E0ff+Yj=o(ZN(i3W=PYn75}EDyKHJrb-uqCM`h6Y9(fXzdp5~asQr~X3X3=g z2^pi^eO*b({@hYHPi_j6T`WGovyKbhe zZw4ghL*2Y=9>=A1EO4O8eh0`K(ZLvJd^uem5^S-vPJ8tM32lJq-Rl<`tMKjf))2p%G6cq0n7INpRa*@4)vWb#51 zHDXxeM~+6<><{A}TkQR8qGjB)FOx0_)Swj-q%_KZs%TIUI;L~|Qv_`rwdaPPa2bF{ znGUK~Ju_yMSgEf_%HDp;t_&M9QA7>g7#TZc4)@SHx*Czu*lJQ0jlo1E%rqv_Tjj#S_pm zuZE@H3A220`Pwhdiz-6X>|yA55{*1`6c4n`qvmo!1fxlrFGx>gDSYW(^D3Sg#I5^M zv5UlReLP9NX!089c&E4Q?DvNlJ%?KA2yJ z@KiF|+=3qSz>B-=`7n2myohPcE{=?{{+OUxY<|!w2eOknT(XwAvO|;Vr+yGZqX8;;%$60>x4a zCi>CGk*`1jzY8gL*HhN+WO(jF(=fbUYyG$SQ2>N2aqQ0-E%5nzy|?k)1F%0Y5EL0S z#;)8Xy@%|+3>8q-G%8 zF95Yd-l&3hM#LYEqW-h;iKfV{+kia%Va%^UU}CnvzF2K{2#7EvTwyoa{5h>MCv>Yf zEk?k0n@8)b&mTT=`z`=hFS#IGlx<2=Q0yBFD@G_<4jw!|x&VPzJ5ouTa=zzI#0;YU zC|^;GUw$wK0)Y`o%XN>hWZxhKU#+ z`)T9mxBq1!xc|xUry5g;$g~CGZ^Tyd5`Ml(^>Up44YNRieb${H8KFmauup`Rv1vDz zQkS;y+=~g6KCM}=xf~_4;fx=g7!p{m?bXKd`Xk%LRM30$s-q;C(8R>IoanFD8qdx) zSSMMze!i{Xepc{ktXu(K&p9x+3`mKZ&w#_kVX#|CoJBLZE=>^aVgjGphUInRS~JYF zk`kPdev8~8Mb)q#6G4#6%E*JCRPIBCx)LyZ83o^{M+-8eQ#{E@06SwRO_Vr!1O(G!x?fEq{mbYfNV7(UCnFBw9U-v32;WjU7~ znLj>uAOo2-sPihJf*gFGMS(B|)IcG8J+s|$J^d`l(bsaOCGqOn!#LV#c40{$g5@09 z!RE;xrt%!-pz@%*g3KuKF(3Z9_J`^bw9)>X-9>($K{hHZ?Evos1k8ZNI3F<#0^zc& zQ~xLcJkbhZmuOGU{{sIGh%Q}^S`*~Nv8b{VIz5ugo<$jbtt6PAY99K9a zBfl*DyOq_!&6CwGy}m9gvR5qNdDB-xt6+G`l4sjB5LSjO8=+GT_PTNQfga%OiNS-x zg?Y39OdK5PgQpO;L}%HwGH8f3uIb$v^?n2>W^cGFZ2>agSZ{*tgB{4%A1&kHsu>ur zVP0jSfdT-7LbWzQG&rJ@wEF%ZAMRRBOEmou2enBVI(^{np)!MxE{@S~T+35NpX+4T zU%X1_9;RDq>JiOr$%il$mhE+ogZ+TOZ3sveSG$~pG&hE=myAz0zJhB7yXn`i>iS{c)e+kh}f4wbPsRJgs!BsPTX ze*}7>jwYges1KCxQTi0$wBRBSj?QpA+h_jYjPCg2%9}NpnB8d5Q7d7YMEk=gH31&_ z2OR#fuH^bd%{Eu_Ehi288sK1Br;()xGN73aG`V2b|KRqyB26<0;@UrX;*59!M6)>E zYD&V1weB*-OpPe`I*AuAB{9sJ^#Wor#N&SW>3vtXrq5iQKlh9DClV(E-kYL6;UKt2|-xAnyYdP4vG0wp%~_gJXTI0Oj0N zVrtkO&8Wbl)qObc$P}9Vmp5U0sK%2t?wuGyIRE>6QoBb4p?|j7zdW$d8nXi!(g$mg zxs&wGRpeG11(*w+jN5w#`N79RCqb|3&5~62b)sHn4#=MJeso07km^g+!emG=M*e#w zZWfTX@LXbR^XJ+S`>pDeiwmbO2j;Y9=Qj_q^_no)kAF!0efQh@_J013(xcg4b|ZCMiQ*O$#Xem?0aF+~NAcWxCe&8A)|zEV@ojP3Lp8YF)SRv@xV!LwhG&u6y?<>)_07wP#h$YkkFLb-Z?`EH?v$AN_iH`;r_H=!3mQkD zy4Ygv;$?*Se=1yu$7 znVusdBEuI6S0{pr8e#1?n|h^!a`(hZpg zfvikKpQ@V$H*0(#@lK+84KKt`IUa^mJPyAG@@XV9N^XigdZ*Xi(ML10`Z5FrBBXrw zME>Rf%`q4mkN)k_>a~&Ydd$&pXe_p-IbRltdNmp;|JkIpZqn3XD;%dUSI$|+VwriA z`0qDf;?Y`4lv`CkL#9m1iehmKx(M}F<3`L99mU7FFA^1dl0=|b$eOgYQFTy6vLNX7 zbk@G@%64RCyok%Ae2R!m&yG@7`27O$zbmBjfq(tz=hZa$N;B`x8J9Y?YBdZOb8xaF zmK_JX17rT&2E?n8v+wCe9}co8!Fq6nWn;uZ5;pUMw1O8`>L0@@g8g}P@CTVgv?JAt ztj- zN;$VsR@FenUdHil&PY@OC#H?3^);Qq%8_d9v*BGcO?j7>kaElo&sF=JpMP~EY*8Z? z%rRdXsYwJ2Ze)IY*1BpkoHBfmMC5xbEA@h@{!C)(Eg8#{yVfY%FJm1{hLx0Wm6$jm zZV;>qy2WOhoU?VShKB}C-FB=a3+`SzlX~}3QpR6JwM#P@+M>K3UYUckaAB2U{`(q> z*!5wH{fcV=OY;6xk6k71SCV&Df6^~Qp4>|~+@q`ATwnR5j27sz;FTh*M7rev{K{eU_k{1A48ke%)WCw|SIl_H|dgdBtnR{}@87_4xNI zWxLXDKnEu05HWS_&^?~Mn(NC;ppdC}`c}9zowU1bq1tijX+pBg_BoYxgn*wHsv563 zD_*~ix3uxuD|;I{v1o?y^GlDw1jUG2`A>hLUI}^r zGb9QHL)QQ48R#2qMO-(C)u)*pMWuO{ILZ9ao2EUyb?K`7jw#*Z2gM%Q|MOFXra{z> z0?B&pIll=stH`UQN}jAo1{`L%oF3b&O#JOR8##VagqY1OwX$Qs!j96vRDISwoutYS zTI8R!!$W5q{RY7m9hat`bNlFjy0@=Pb}ByhQxu8v#V`*{8T2Ayfo!Pf!!`!Qs zMVj$m=N^!Exz0|q3!XB*aWXw5{q*RQr|ll$Po6&nAnu()VG9)d4UcWh?($!tOFjPP zFERch-SQ-$p&j?Bx)ZC&%<}63rcK=ccNwqV`~MndXislf+^zzjOj!c$QLB4VK1Jh)tsm zt1=-3QaI?hFq<6@m!o5R5Ff)BlcRC^k&YWd^!i;3S6m4#_3CVR;hn#&R~UD8yKIgE>|s3>0tGL ze1WIH|KSHuC!k8=0Ym7v>x7ODSWrwD9|;9Y9s0y2nCB zT!fQs29dj`@bv!XE&)7tKxGPc8#o@03t#-`*sZD;GRJf-qeAXBPW82S#yE&rhMN Date: Thu, 7 Nov 2024 17:34:40 -0500 Subject: [PATCH 09/10] pass session object to ByTaskIdHandler (required by new sqlalchemy) --- luigi/server.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/luigi/server.py b/luigi/server.py index a10d668dbc..974e3f2cf8 100644 --- a/luigi/server.py +++ b/luigi/server.py @@ -266,8 +266,9 @@ def get(self, id): class ByTaskIdHandler(BaseTaskHistoryHandler): def get(self, task_id): - task = self._scheduler.task_history.find_task_by_task_id(task_id) - self.render("show.html", task=task) + with self._scheduler.task_history._session(None) as session: + task = self._scheduler.task_history.find_task_by_task_id(task_id, session) + self.render("show.html", task=task) class ByParamsHandler(BaseTaskHistoryHandler): From a0c6604f5887536f92ba5781c3cedcf29ace8391 Mon Sep 17 00:00:00 2001 From: Tashrif Billah <35086881+tashrifbillah@users.noreply.github.com> Date: Sun, 10 Nov 2024 11:14:23 -0500 Subject: [PATCH 10/10] put w/ space around == operator as advised by flake8 test Reference: https://github.com/spotify/luigi/pull/3321#discussion_r1835554906 --- luigi/db_task_history.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luigi/db_task_history.py b/luigi/db_task_history.py index e818526701..6847c71f6d 100644 --- a/luigi/db_task_history.py +++ b/luigi/db_task_history.py @@ -192,7 +192,7 @@ def find_task_by_task_id(self, task_id, session=None): Find task with the given task ID. """ with self._session(session) as session: - return session.query(TaskRecord).filter(TaskRecord.task_id==task_id).all()[-1] + return session.query(TaskRecord).filter(TaskRecord.task_id == task_id).all()[-1] class TaskParameter(Base): # type: ignore