From 82cae766aba40dc3966b491a5bfcc2b2bb23353e Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 15 May 2023 19:03:48 +0300 Subject: [PATCH 01/13] Print-pages limit. --- .../versions/d63e9f7661dd_page_count.py | 28 +++++++++++++++ print_service/models/__init__.py | 2 ++ print_service/routes/file.py | 34 +++++++++++++++++-- print_service/settings.py | 1 + print_service/utils/__init__.py | 25 +++++++++++++- 5 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 migrations/versions/d63e9f7661dd_page_count.py diff --git a/migrations/versions/d63e9f7661dd_page_count.py b/migrations/versions/d63e9f7661dd_page_count.py new file mode 100644 index 0000000..89d823a --- /dev/null +++ b/migrations/versions/d63e9f7661dd_page_count.py @@ -0,0 +1,28 @@ +"""page_count + +Revision ID: d63e9f7661dd +Revises: f6fb6304fb74 +Create Date: 2023-05-15 18:38:40.964981 + +""" +import sqlalchemy as sa +from alembic import op + + +# revision identifiers, used by Alembic. +revision = 'd63e9f7661dd' +down_revision = 'f6fb6304fb74' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('print_fact', sa.Column('sheet_used', sa.Integer(), nullable=False)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('print_fact', 'sheet_used') + # ### end Alembic commands ### diff --git a/print_service/models/__init__.py b/print_service/models/__init__.py index 7df12c5..102cbfd 100644 --- a/print_service/models/__init__.py +++ b/print_service/models/__init__.py @@ -56,3 +56,5 @@ class PrintFact(Model): owner: Mapped[UnionMember] = relationship('UnionMember', back_populates='print_facts') file: Mapped[File] = relationship('File', back_populates='print_facts') + + sheet_used: Mapped[int] = Column(Integer, nullable=False) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index 7da7ae0..c87610c 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -15,7 +15,13 @@ from print_service.models import UnionMember from print_service.schema import BaseModel from print_service.settings import Settings, get_settings -from print_service.utils import checking_for_pdf, generate_filename, generate_pin, get_file +from print_service.utils import ( + checking_for_page_count, + checking_for_pdf, + generate_filename, + generate_pin, + get_file, +) logger = logging.getLogger(__name__) @@ -157,7 +163,6 @@ async def upload_file( ) if not file_model: raise HTTPException(404, f'Pin {pin} not found') - if file.content_type not in settings.CONTENT_TYPES: raise HTTPException( 415, @@ -179,6 +184,19 @@ async def upload_file( if not pdf_ok: await aiofiles.os.remove(path) raise HTTPException(415, 'File corrupted') + + if ( + checking_for_page_count( + file_model.option_pages, + file_model.option_two_sided, + file_model.option_copies, + file_model.number_of_pages, + ) + > settings.MAX_PAGE_COUNT + ): + raise HTTPException( + 413, f'Content too large, count of page: {settings.MAX_PAGE_COUNT} is allowed' + ) await file.close() return { @@ -221,6 +239,18 @@ async def update_file_options( v if (v := options.get('two_sided')) is not None else file_model.option_two_sided ) db.session.commit() + if ( + checking_for_page_count( + file_model.option_pages, + file_model.option_two_sided, + file_model.option_copies, + file_model.number_of_pages, + ) + > settings.MAX_PAGE_COUNT + ): + raise HTTPException( + 413, f'Content too large, count of page: {settings.MAX_PAGE_COUNT} is allowed' + ) return { 'pin': file_model.pin, 'options': { diff --git a/print_service/settings.py b/print_service/settings.py index ab62952..c870006 100644 --- a/print_service/settings.py +++ b/print_service/settings.py @@ -16,6 +16,7 @@ class Settings(UnionAuthSettings, BaseSettings): CONTENT_TYPES: List[str] = ['application/pdf'] MAX_SIZE: int = 5000000 # Максимальный размер файла в байтах + MAX_PAGE_COUNT: int = 5 STORAGE_TIME: int = 7 * 24 # Время хранения файла в часах STATIC_FOLDER: DirectoryPath | None diff --git a/print_service/utils/__init__.py b/print_service/utils/__init__.py index 9f32af1..14bbcaa 100644 --- a/print_service/utils/__init__.py +++ b/print_service/utils/__init__.py @@ -73,7 +73,14 @@ def get_file(dbsession, pin: str or list[str]): }, } ) - file_model = PrintFact(file_id=f.id, owner_id=f.owner_id) + _, number_of_pages = checking_for_pdf(f) + file_model = PrintFact( + file_id=f.id, + owner_id=f.owner_id, + sheet_used=checking_for_page_count( + f.option_pages, f.option_two_sided, f.option_copies, number_of_pages + ), + ) dbsession.add(file_model) dbsession.commit() return result @@ -94,3 +101,19 @@ def checking_for_pdf(f: bytes) -> tuple[bool, int]: return True, pdf_file.getNumPages() except Exception: return False, 0 + + +def checking_for_page_count(page: str, two_side_print: bool, copy_count: int, num_of_page: int) -> int: + if page == '': + if two_side_print: + return (num_of_page // 2 + 1) * copy_count + else: + return num_of_page * copy_count + result = set() + for part in page.split(','): + x = part.split('-') + result.update(range(int(x[0]), int(x[-1]) + 1)) + if two_side_print: + return (len(result) // 2 + 1) * copy_count + else: + return len(result) * copy_count From a89001356c0f0bf20435a38ce24dc66257fc1a16 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 15 May 2023 20:08:54 +0300 Subject: [PATCH 02/13] Print-pages limit. --- print_service/routes/file.py | 1 + print_service/utils/__init__.py | 3 ++- tests/test_routes/test_file.py | 28 ++++++++++++++++++++ tests/test_routes/test_files/many_pages.pdf | Bin 0 -> 183317 bytes 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/test_routes/test_files/many_pages.pdf diff --git a/print_service/routes/file.py b/print_service/routes/file.py index c87610c..fc1c892 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -194,6 +194,7 @@ async def upload_file( ) > settings.MAX_PAGE_COUNT ): + await aiofiles.os.remove(path) raise HTTPException( 413, f'Content too large, count of page: {settings.MAX_PAGE_COUNT} is allowed' ) diff --git a/print_service/utils/__init__.py b/print_service/utils/__init__.py index 14bbcaa..8de8bb3 100644 --- a/print_service/utils/__init__.py +++ b/print_service/utils/__init__.py @@ -1,4 +1,5 @@ import io +import math import random import re from datetime import date, datetime, timedelta @@ -114,6 +115,6 @@ def checking_for_page_count(page: str, two_side_print: bool, copy_count: int, nu x = part.split('-') result.update(range(int(x[0]), int(x[-1]) + 1)) if two_side_print: - return (len(result) // 2 + 1) * copy_count + return math.ceil(len(result) / 2) * copy_count else: return len(result) * copy_count diff --git a/tests/test_routes/test_file.py b/tests/test_routes/test_file.py index 9a93245..eaf9e21 100644 --- a/tests/test_routes/test_file.py +++ b/tests/test_routes/test_file.py @@ -164,3 +164,31 @@ def test_incorrect_filename(union_member_user, client, dbsession): assert res3.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY res4 = client.post(url, data=json.dumps(body4)) assert res4.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + + +def test_upload_big_file(pin_pdf, client): + fileName = 'tests/test_routes/test_files/many_pages.pdf' + files = {'file': (f"{fileName}", open(f"{fileName}", 'rb'), "application/pdf")} + max_page = get_settings().MAX_PAGE_COUNT + get_settings().MAX_PAGE_COUNT = 9 + res2 = client.post(f"{url}/{pin_pdf}", files=files) + assert res2.status_code == status.HTTP_413_REQUEST_ENTITY_TOO_LARGE + get_settings().MAX_PAGE_COUNT = 10 + res3 = client.post(f"{url}/{pin_pdf}", files=files) + assert res3.status_code == status.HTTP_200_OK + get_settings().MAX_PAGE_COUNT = 3 + payload = {"options": {"pages": "2-4,6", "copies": 1, "two_sided": False}} + res4 = client.patch(f"{url}/{pin_pdf}", json=payload) + assert res4.status_code == status.HTTP_413_REQUEST_ENTITY_TOO_LARGE + payload2 = {"options": {"pages": "1-3, 7", "copies": 2, "two_sided": False}} + get_settings().MAX_PAGE_COUNT = 7 + res5 = client.patch(f"{url}/{pin_pdf}", json=payload2) + assert res5.status_code == status.HTTP_413_REQUEST_ENTITY_TOO_LARGE + payload3 = {"options": {"pages": "1-3, 7", "copies": 2, "two_sided": True}} + get_settings().MAX_PAGE_COUNT = 3 + res6 = client.patch(f"{url}/{pin_pdf}", json=payload3) + assert res6.status_code == status.HTTP_413_REQUEST_ENTITY_TOO_LARGE + get_settings().MAX_PAGE_COUNT = 4 + res7 = client.patch(f"{url}/{pin_pdf}", json=payload3) + assert res7.status_code == status.HTTP_200_OK + get_settings().MAX_PAGE_COUNT = max_page diff --git a/tests/test_routes/test_files/many_pages.pdf b/tests/test_routes/test_files/many_pages.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d4c44c84ffc7ae085ff41d9aa27f60e164b34e92 GIT binary patch literal 183317 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

R{6Xd3edS#MIzrViO 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�JmP=t%WHIi`?dh-YB-tnr6X0 zo|7yaZ^0X;9!0L;Cp+!e+CJ{qEYin^O?i7LXDunt>y&oHT_aN;_c2%}GcezItiIsY z(|MimQP)e#3geIyOKz*?P7@vJgWmXh)34dsS)as)DzXP|fvhC(b3pIN;4YYfCpXrd z^esK-_-8b}$+Xrjo8tA>Wb`NSDonu=C|N7K&isab6FkUrx8vA+L3{)C_2%tyMeYV} zsf&a?%D(D?A2&uaF4@JbF^ zvzu(!%-g@1ucfe2Pla=>-N!AnQ(Rp&#h|z6SPcN#M=uUGqISuH;nI!MPe~%v5>Hof z)&q`9*BqPgf6NU;bLM<~CMxo(J|2C%B(f-KXq#pSAvhBrEKa(i#rLjou#ZK@E)eB$ z0wxdr8JuG>;Hv;!PNxUK|GMVRVu&TD({GZygGRikR7E|3bh%~DjD{9H6OZj->xz16 z(=UVL!u!`3|E@9R2$3BS{fm624c{=C>!@tN^v{>~{g+ApIY}1BBvBKS!mI?k^O(Uuk^s@3xZx z`OGZ(FXsMDA-5!ur}XO&2tCL(Alk57rxpray1>{txbDY)bMlyu90tuZ0Py7qA;#p{V$ z4IGi~WT&H5l^|dv*6XKg4Gmk%D~6#-8W0QGSc-sOEgD{#JfBDgJ<&^VB>M|c&guc#@Sxf za*lD-WmLkM=PoUhCrh{$R(; z=k9{w+12C~0G7el!4($0TZZ7UdI&Q$go=@j5Vq`uRdeTMoR2dl?aZTmv9aDA4<<2QND?s8@04{G(CEZBHej1`+JuP;W26kPvwBaTi_LsmeHm|9N~8I3 z6reNn+tH73aGH9;C%csQoagtIyt>~sK4HGx*b}>c?W@voqXsf=H)Y^?vzdjHL>OL2 zCyE0}HeNDe_k?o~Ne`AEn4Xrg`GLYc)_!I#;r?kDo_XA2AFI}W2d1B~;c4`7x8!wj z2 z?K_jb%}yuJ$mt_~1`i<1ZX0v$PaIBqh(CG4$}gTy;QAlEu|senJc#`q#OQ5rk&X*W za~sO8`!c0^|L^S4)LPkQZtNDovLpvMY(FE~03qSWE)VElrd)h_P9r)fD_$>ae zx)~~m1M|9bx;yGYH1iU+7g*M|1}eYp3BV=;nMThh{jxsNS6>o6iGQ#9{{ssD+@Qoe z^xyV2ayQ%p@PmNaWcQ1HuZTe&EVbTeE$_M){?}Y??>ebKN)6ksr!A+ECdCj#FUox# z*HL9Dp3HWdl(QTDG{?5j3jycap*OW~r&^Ou(l`rT&TL}mzy@uTsXrdaQmcapcWpV5 zv-nLFkt5Sv5nwfhaZl6C-7SIshixE(95=}M3R`LpwEn9ovDV70 zmi3C85VT~0F3e;sd6t)+lsa<0RH>E$oT|(|8Lc9OZMBKUhyS?CzOheQ2{8eSSH4UJ=C3uDJ#B^pBFGY&SFB7JFoQ-q6vI(h&0<~j)Uz^d5^^PX zknJLJJ1o)&Ma!ggI*VBiHeFEZ`9JR~nDei~5qVZ=kbL1YBy5VHqV8I^@2iK@opdgL z=s^j_A-pCbyjwNf8b7fZK(N*HY1@m=r@Z7<<5Z26dVs3&lKNb|%C*JrMQP_ccZZ*m zEAIQ*E>+J5W;zSpWgXlLFN0P#>RZ`a)qk^`tJJ-m`5wpo(94SQ4uCwZy4~D|B>oA# z>>{o7oo{;K^fS2#~DV%(_Wm@OI9VClLc9tqh#tk77JPpoH%$Z(M%736dGVqRdg)B_y{xk%XmbOhNHZI4fc|_a8(=i zGdyQdrb+&SK4wt$MJArD>(XG9=v;mVo;3u?YPics*LT?bGq38T{-M3W$;Nf`)dg!8 z(lh<53o2jKQuTAD$3|sc1UCev(_ z&OVxdMcZ>mv5$O^#|Cax;8x()P@<7z{SQX8McB0=xTC<>G4rky;wO>>?dFv76u?ew z%1O$}4eJD)gqw{y3MR^$b%KN_ikc0bgenTnPFG5I$qV;W$q8|WwwRiZtTj+&XFIM| z3s-B2x{Wiq#oF#-K%-{z+u0|*8B}9X7>}~3#x!w7$<(bPp zYQf4GO*@Bcx{1#&w~^1zVE&}p6H%jVlEK<_wF~1vzzPBY5KvV)avEX4Sv7aC&;aT9 z9RhO9A-+4O6oob;JN>?YQt4ZO5k%^2+=F$Rvm1o?y3x)M_!Ax=K*rlZ4Cg}1sgeaDX#IXX3 z$F}4^&*dT)(1wu3o$6OZbW({FR%AG}FSPhjBwQ3<1e!k%cjVsD@Nn2L@!67orE5|w zsXt;t+5i3?u{1Y1pKK2m$^{d;iFR=LNeHM4Jdu$&Hui~B=JvwkeE8g73S-P^&Qp*i zmGK(-Gc^eXB={v=7m+O`XIyQd;$L>;W2J(6a1~S(J6@Cxbd>IZ1B|#(+MO7Cw%eb5 zo#=@cyfhn_v`$Dc=!Rp#@tMb0$-^;vVA^3Mr)VLkXeuWh z#`fkidtfpH zMSrvpcrrhHvUkNxf4GY@lXaG%HbauOx??Qv&(E4>w{@T+L&T#zg|ZHOdpLDh_6<2} zdmwZ$8>SLA=yS@prdt&m?g31t#Uad|^$}O_)~H=@mHayO<+RJRI05L(B^x){aF2~I zNw1BsP_H4RHiXow8_+l6ihOh4An!~f5DpCO7~#>E0`{(gO;(vZgX9m>w6BRYW`8ZA(3nCNSqh9?kXL<6I&AUuN&|7&319U z@aHS1U8= z)-q`YC>0TM$q`aP+B5H(?irC?R*kgRr4uN{)5+S&6tbgR@P%W zqq@3_)OJ9?A7FiC`d(ZIwvHr z^u5MMloVK2kg0A{yOsNQuN`IL6-Q~5CX%kDi#=t8LUjIoqMZPIs)T}LjXxO`b^5yS zTi_Sq4@~I46IR}6z`iU74_Vm6&b(G^Jmt?;$%)y^k9jQc{;Gv( zB&`qgl{D zQeGn~gMgqP&klRs;ZGWVQOR3lqzTtFPnfGWO|P(42cx`}J9SRXs{)EsMRR*Tym==R zuuf3dfkk9X810{_SW;vYY-03+{w|ISC-`;i#og-eD-^F#x$oGYrFPE#7QFssu0`^_ zrO#9>7*id+vPeaZ-n@cCJ^Q4>MLqDODzOq};qyd=c#OKadI+;pS!LzCl)CD|SLaN= zoXm29N;sMF3Tp~;CUs;h>#Ef@9mzho&)j@LCzYX<S}~t)(9q{a7V6v^+r7Xb#Qfs zwM&6ZN6-_^UtvlmlqZ_EgRJ`C=K|46Vg2>%Q>Ku9!>%b!+#B(aL!A~9q`H#ZLYsa( zXapavhhsX@4ggrkpC7GV&Bd6hr8F=wtbO2_Pxz9GtO8Gjcr&73h}a=;Xl#l?0V=sMhaz>!?gn ztwCt^@TBXgLT$u8KlvZG-7fpiw}aOD;Qy~9wlH;VR(snmP1))8`e^@Kk*0W^$m94? z3W6baH_}d3ksaM6KzLAqm{^g5kNlasf7>4+=!5*rBkA8W`JYnX!h_}bMjAz|zs}j$ zGsXv-2VC|+?-*9ql_Wm%`4Xo<@{jV<7uGE;sap94^#qKc-ggM5%yFL(jxBH>>!M%e z^ON~XZlGJ)&$W_I<~%C|ga77~2lnW0#c(_vc_$qB`3lzx<@2l3u}*}2-BNd#5O}0| zz3AY7C3#k+FYrDYDX+dL@uuA0eReGN5fhFecsT;1&nXJWCH9FbPml>Byc@ki|3#Vo zK6_y7g*Wag{QNkyad2VG3-H={yQU`JTeQ`;;C|=b#;5KtQg(uN$1y0kG=~n;gG}m! z`wo0|=9BO*08&gczEP>q8y?riU)#KKT0bd#gs11-ve07M;_Xk*-E2=UA;()3yc28U z9!t;y8w>(3Rl1W;eo?VVS~1)rRhqQ}QlK?2=w^x?633$xKLZu);4NrV4I-x~hQ;nw>pGAx3n&EImPw0aLs z7Qt4N&w_SZy)>9|f>2$&E@B5q_-adIE`YuQCRK+|rJI=q0Nh?sdw)CJRcaKs6CV%p zpL$XklHjeOW4O(A;^;0RJWo<d#_F7RF`lf@=r$Z|J?Q!F~vZJw3o~Z`GuS=!THTVTVT6_bZ`m z;L(pGeV0ftGVCXMLz&eS_zu)D_wNvxnrC9Eqo`IFVR{l4_v0@ zBDcMZp^vOFA?(-KFK=9CK_#Nt$AMSA=9A znDs0DTm8og=*5N&TsP45p~5}E6yP!OUe&qZ_pa#95csAEyf+*WToAVg~vJA7ZLQ;Or6)LE-Avht3yszt>&!-EmSx@y7q6hciYV8x#pZ72& z3Xcyd8ROx+sc7LSe18}RBs_mg*7uD0!K{5>NgzAeAy+nO3@BgvZP84|T)vdc7O~k( zHXr|#y~V^kpZqL<_uC4b(z`=F)VH-yk#@htEj}Vw{5yKb4PjG1!g}G@QXgb3UWYQS zTFr*@`lE$&@cl!32ezQLoStz&$Jox#SO>RE>2t_*eaF~MoDoI>1hlH`^TUO-Ct1y7by#Uqg2jUSO@=@{xNpNRtMeQnF$uR>UF_3T|(4KKuy@r zr#Bh8t!DN){p-(S2a7}Ly0}35oT+ubpcUuPGn$tGRUw)@n5^crc5?QEVW)7SK#z&^ zQ-G;Gwd8ohc0ww{Qj%$33L(2DJ2M0>bVwJUL_J@+S2QjweH|=@- z4>QjAq-Qbax^L2sr^zH7%eLF$6to_QHxWn3Dr`Uc`UvopB7y$i0%~Jp-=#Jh9zy?} z-A3p9&!V!LF9Z^_UeC_BQU^s(8| zS{ODFPt{bZgY+iS)f5L!ky^>>gUlA#YrjgeY} z8t4;d*bQsPVQ;vyosUF2|6ScK@ zOQ(&s9pO@c9}IzBi6jWLotpO#Z#@nt+(2subJ#(IMf6tOX#UsN&d@+Q+$l4yF6z{>2^UoTP`K<__gSEN63P(?$D{ zfGh)bM`*`S1R_J(kD1!)fh50dgfyqbV1Iz$%40a?~5I+Nfz z@-DtEf^5lwxI*^;w{g646eI@(he2iN8y5s&d_N4=TvP|B4Y<7|bRmp)gxl#q0{GFM z9c%}5U;K&R37C)}pC7$5zY_nTVO4}P&9%Y5aj^iY_FI;P&nmDLQCwMG}}p>2Cg00A9BltJg8y?cXg)M(8ROIMnu7^of~KrJp~A<5T4QY_yitfN~ck%oY7u_?@W@MwYE1f(|{*sIDyppIQ{z85wXH6H}N9a5~j13qcm9M^R&lECfpE8;)v3xOo0_0YId{91(N6YC*#{GyZ zGz?H&Wff}w_NMgm4npMFXB9qotnMnu%0YGi+_b&I?=_U4V3?yP6@r|`84uUg0V@Xf5vdG*H*N4lxVGjBN*Z}d-Vtao%xG@Ow>{>E%-n6Ngwy?KgmKlnL z5WA3Rd6vI52{dIBuwmFBeRIR5WLy4z(4FxBU9bUvyO2DqsXMIy_Nz0Mte3-?x5eTX z5(SnxK-wFc3i0f6-jV2XHWmWwEoZwkgLZR})f1a3McBl1j{GXVR(!6IJD~xRpAZ#+ zlplV@Dx;N$T?$o_sK!yMTfHQ+t!7Dqt-+Pv^Me0quPR7n=OvCiDXg(as4?0Kza+#~ zj#S0@H+7_#swt8lcOQ3GqoOFSj8B~I;HfU(y#7QqUE;dkC zG`$$^5=>n1`eZj{@dENq%gH$hdBl6x`45N(JTY7ZoT*uJj^gC@7}6Dtr_}tD1KBr7 zt461d_>y>=ULBFA^h({?bEXp+w_n8!;VF89k5x+1n)Vnng!-@ROgb{-^aos+mh?tk z1mpG{Q~hC_xd0o3F6EjEC-z9a!1jau0|yjeuW;Sn8<}Wu8*% zUWkZBgy-G&G9j&-x^)j_(8XfO^YFDq+i$BcEsr1WGvtAV0&&+rag>mOJ8kYnK+zdC z5dOr|e{T%!yC`BN?h{g}YC3z$F~`BW40@!<4TW&fu^e;G&@J-;$lQy2&Qs4{=%MWw zFLL{V$rOumNAj_CZByv6&Ox0aAwZdEO=?a2Uu;PLE&M1QsB5}t7n8|9W7Frm&l{tTj}Hi#W`Sn?N;qHwQjF$Z`Qx( z?q`_G`QBiCj=zTk%mk;%cM|jBhJ`F4H9`~z89ky~Vo%RpzWmrH)5p`w2|cn~@LP?f zhv!J!kGUp8h&4!(qX)o$eqCuQO>2-CrQ8gxS0!necbO#(CREnbu3 z63j+W*ZmK1(X?+vWQgyd?;cqA0sMZm+%kGDxGfl;JmQUkXfU+4e~z(><5${oM*QLK z*yk&eb)ygrjNMg~8d3HC{!f2j|1M~l+ThZ>EA{cbta$eQj9VM3#GUnrVk zfc!rG=Od@jv0*^YBrao+g~i4{$M;bE%4`p9J%!onpe{_{>REPDwYiIQ^`-2MQd51h zx50Dk(Oa(OW^q{CXp`XckvzgerXArYc3zs_ufGf(N0TE` z&b@e^2?sMv(dHygISH%cN*Jq+u#;=H3a2R~^J3JigfwbOw9-;fPwOcJOFts{Ze$i< z85V>(GBwM{EgOQD#%T>*r}wbgqv|?<*Bu!lLVlrlu5CiuSk>v2_4cuY9Tg|s$3^vC zv7w)-WsSrF9mC0oPcfDFl=GyHpTAXCqWc2Av6HVb<wzzhWRWa{K$79M~>(k=ixnChS4~wN3u#CSgR4D{Lo7R)pdhMB(s{v zE>#VsRnIz>OduWhf)@F0+r>O_enrtBbjzQFdt0&ChI4rf?jlYN7lh9WzBI9`C1A0) zjpwL%9~Kv4Q~e1kV(lgLMOU~}zVVJJBYnx~8CTl;Q;t|QlttG}gW4?=#Nc7m>MM># zk95x5DFVg0vLn?#bOMO384!*mcbEXJY1nnqgU?1FhBJ2v;syuRnpWGyxI)GrnJPTx zSaeNy%|X>?fjxA23x$4`pIf5T;kq5U8(~YOxuuzDoN*;M#yjU z#$|di<3p(_kFUl`L_{PI3Cx2Q6e<^%ioqP2sF6;M+QSgKr_KvQ(3?u(FTLz99@TcT zX*Z8&@Re?K5o4CwAtsl2)M6X~Y>OJe1ZgsVYCEUv?1r?9gnnb{mN zCt&3$GxoW;NiCCpQgH|M2fw=v_qHHq$QI%&o0NXZ4&Cd4WiOfv)TW?{Orw&@;8>y# zyzG$;lJuQ;VN$+=%!+q>%C3oNl&R-n9)PBQoDR1t-PF-8_ zbnVzwHawH1f^<~eO5qnf92j6%I`jV8@u!tQg4}wBtLpw5Iz3~}93HB>WNS^6gS%Ux zK`_vuzmb%`Y%+o%4xpcKB-sa2l}X`UAEC`#BC-SvmWX7;_jCSwzo%>;-zGB@idZe~ zsw9%x@rz!K+MiBl8jr<#C(oC>ihFRNn@CZoqtZ3L<4?h+>r%JuY<*34Qbc+XYTi(= zqM25uF1e&Jj+IlDNhVZjTPko9Cn?>d+faQhDIPPVaMf%~UZkVK>(wLkubG$KF?qfA zTS4HF~$@i^_jtU^t|5xK!{y3QtvJR@CiG3G29cH_<_iw(LDsJI_AL)`? zMbc#JWau=$EB2kV4%mR=HA*kj3hQc{RXn~}*~^SE-lnkZ&k@aBs6_f%;^`1l9n&7? z^@C&Ey~PB8FmWo0Dk{I)y+2oc1t+Q4yJmcA@48QzmIg`Sv$H6|yUpmH)UZ;r%(C<$ z`B(VSEgp(>f2~sS?iSQoihah`3X)-?VZSX%k5SHz(dH2rtz*d0xe|xQ|<>AH1P@#&_nzsCG5@t94(swB1PY>QxcL0Nzb# zTC?VXntf-N?_?I<`Ae!${B-y_%B()5w_+tK@DXaRhLB;5_| zcY$$)IKX%j=s@{IKqgD__>$JyBiYq6`L1&00WS_rl}$tLuG&raOgrnyd^hEFc%rqB z+=a<*6+O)xc-IK;o7nIDxywJkllZXfTSyb?h=nwhs>jWxCr0YO;-5QXZ+BE< z_^=t9{a)C6cLRq}Qj)4|h0_Cc*{M8kbSJQ$s6vNicDL;m7}k|(dSo$qYpH{ED#f5h zITmbZc$;)_{i}<~zp>^9LRU>bx9P&6pEZw^_58CXqkQfE{!QHNRAN8SYZB9XWkaWv zdh>~5!Cjgv26&N5C-T9y(NknX^Zoi}l1-dF0>N@`31^bggFV#EylP!0}@ng$XD-B zRP~#ErEkHs-#AkCn!9H1GoP)rSJMc5fR?nI3{_8+9?Y`dhC$OvP&FY3a9)ohYh`_z zVwai)Xkz;TruSj@Hm981h__U`x_OyJ%`e}pILP47ZIY|eu;F68l(MigtK`4qAE=cp zxJKYqBB)!!eBUQ9o4YTFhL-#?ANjqT(}U_sRzVsJrDmCE+g^F}#9pPjSl>G&wf}V<=FMj;d|C*F&vA#r~)OYA_#56uzJ~*FG z5Ii*#ucEq!bikR@k8l3nL?&tx%c&77Iw_-w%k+jGnOwA}8c_G}y89{vEb@^T83x$Z zBh42Jg)|zkGTJF@j{;iSH41U^UC6zNN@FT#!x!~zAeup;^zj9JUrNk%;{GI{@268U zXtm7uS#lTdTRm}(ROVIXF@!C|VQ*7lOXo4iIRIMf2;Nj(0{kdzD$Bl$b&l&)qd1?q|9 zc6n<=F{05+>x>cK`4jDTxSkVITFUJ}%)da|(@D#^+`r7MZdYCMUL$&4~Kw#eyLJsj#iihBI%R4Uj7`8K?u|=m`BNdT#vgvRmaK=C#dyujrb&ZuPM0u@ zTvopQXUcG)%g0PSLV)%WwqTGL1taM5s|EKR4ZV=jmy8>QsL60Oj?;p@?!K|v5Osk_ z;z71bN{=_-BWV%&izewEnLPAjz{hU-zn?K~#Yh!_aL}hBT(@+!d-Ft`@sTB)M2>wQ z(l9010lSeUCY3BL=Een%96zjblK)UhT|V`}sK>>w z&YPEv!I(hzaPSGiWtx|J&mz5!=5#qPTZu)+=0e(!oi?38?h+50gO_gy8;a0i8CwbI zO~&5t3n3OO+(T#IyVts5d$W#+qUl)M7;L{T&WwFh*!IEfZt_3ajwi;c9Ao?+ex3DG z%!~Xv`!c`FozG#T?mDi@fBY5m(Y=VP4D|GUjNDnrGC-U>xWV7!JY?tM2mxN*4O}dA z-7Kj*STjX9Xev+M-Be|4YDKN9LeAvNFgYn!NL+k&;4wryH<;x2Z=X=v>q)fIEbX55 z?6I-XP`n_tfw7)HXhJfEIuDScJgX@@t7%-;HE;3{f5Vide+OYTxd=@-BHs+Ih!lrT zYeUtFd>@F%RFsKEy2NzW-tT;K^?CK35dPKF!IpzU?{?)0?I3?#bxWlJ7g5zW?qM$Q zFK}$!Y!Hb(8DB($Q%A14QtY65`Fq2Y_^|x&31BzhQdO1wkY<#ToCP05byW7o)d{uUXX%zLT4 zSD)wx#JdzzOO1g~-@aYHKi!ELgs=UONq~7Z<6R4=!*qzra}lmVEDnnwJoJ_N*A%NM zd89Tvy;b0FHFh2OI~YaOmsApi4;K)z>-VR9&sk%w9qYNa#_skhXbrBW^_w?TQLLahWSfrWn zlnLsQM|$L<K*`c^tz7MpI%7 z*+XBq;`bJF?2?C@)5a z_v3i+rwz*WT+K@UgAQ5%`&MS$tC$Vj5dc|5JF9vUt0A}X_b>aF-+@97=djpb(b^v) zVl0cTi>>9_R_cLXsghQ144v2|O=vA=7@eQ9W8EZY6x?WLR0t1;nVTH#&uZN?XGq-8 zW(?d|W_sKV6VLtbKkd~uIgkbU`i}PC_Za*hSqncuN4)=>tnj-mPzVW3`kNaP18n79 zaMg;L6J8FmDMC31)hx zTJm9XMDxFAljjS&`XPB0Ia40V0MT^5R*AWFX?LZcJ#t>{xKF&ZS<c({RCv$%)_os1x689%_e-ig6yo~ctc$qMJ4Vk@w!t-3?{?d3B zsoY;WTdl@c8)2)Bu+>J`I#sr_5XtgU*pMuLp_Jm=_dYlH^*o%2dcE#1|2cFCrXYMA);Wb9@nD{}SamBEqpl1X066 z;HE{^BE(mV5j&{X5^D)%SWB&?$S<>&fxjHlglauwJp;ao9kQ$w)(PalwN8TnoplOz zDy=HYu*oJ+$(C>qWLrUAwKe2JHdZw|%?=~q)-LpYs?PC6gyV|{#}^TfFCrXYL^!^P zaC{Nr_#$H8fS4kieWJ+`M8uwD&qB+IIN}={QrX|y-@+zN+NY4Ov@4OXvW0A(?Ew{v zA4I5*E-l7zPHmC`F>76)VUUsj^^}t`h!2f8G!siXCU~4 z5c_D(U}rG+L!9f7zup-N{!g77z!~NY1O1uvGw_EyBak2IAkKA0Iirvt?UW(4hzVCbpD%Pq@UaMlf zR>gR&ig65;%`sFq$57cELuGRemBuktHpfue97APu43*7mTa;s{7{^fA97APu43*6> zR5o8D5ZA|&*G7q^<9mo#e&RJhvBE37wkKBdG+x8g#Z?6N4W_gCDuQ^fZ&LL=^IQ3@ zNJ}aJcPL_=Ah#a5;C2<)V*DpGZxz>LFb`p3W)rh1R&{}SRA88{6vE5_G68z|PpsSf zfl|a>M%l0)c9HIoW}EbgUC7+JIin%G2_T2EU~Qybuj=c%o= z7igl8$90+Ysr4!S#QNO&3$>Qiw=frbd zYLHVmrye!RX^_)^8s{|1$)zSaO>&x29*Lc5;en-TQWc_9`}?Ab;Hy%pJW(~HYEotI z%Cf3Y5wT45KCkRuH3KnITd%xoz1JL=p`ADTY{yp}IkRSES>+Q|4Xd0gxpEI$nhnG< z8?EzI7~};;>3PnYZ}YXHWX*D}Ij-_>)zGSbRihy94!)wbvT|J2a)EHXQpRNWiGR5e zcfc^SU7Y(mW*zv6i_D8iGaHxYDbp-43*Zl0o2{`9 zifBm3+V?2A_OI+;QI7q%{W#SDay?FUtHR4#QslX_FMM5%N^e1zFGWREOe-ig6 zqrW`lo1s^kdzHCYiF=i}R}q6Hqb-G_EiDmku^ckXA+sDZ%OSBG3dE23w>Gi;R$xlL5Pouw9z4 z%WPn56V{o@)@i~zOgraJXKSNw6KXaa9ZZ4!; zo}1!+XxeFWa{_cDu84#aD2_c}gs(J+du!=DdSXdcoI zd~Rj-GYX$ojn8UYO1p`tHE*wOSH@~J0^=QRjpknxh1@UPFVNyi_as_8f0NK%;x209H!8C^QV>@JD1rHTRZtlzXp9j;j1JO-e|P^1&D6vSiC@qp z&cPi#R)GV=wTg-U6$D}N3fn9B_9`q-;nb4a@I9cUjosYde z=ZTK@2aKeySV4u-8=r*dX|;LXjfA{QHS$>kN-AhKs!J>HN7Jsb?Vh z$0omX{$8YHUR?V-;~GLOGEDUU(d2C90UZYQpDe599PpE$udW}+r?h(*>8#@q@cnyH z-1e|QO19fBkvP8^DcH_g+N^bKe%)k0r}tl7=BH|2U!()Ir(hqa+hXf;GFXBrOOTl&!RxWtajcLdi{;4ny{Yi9hbiGr=Wyg6Gh$dBEP)P;IM9JW ze|cDCGTlt9GPOyfwc&;_cnnXE_>grhQtaVh^dd_-|>M@?X2zYKE)n`1{ zka21*-@|Dl)>k*pO@ps*>^Ae)-jZxPz z5O*4_jn-HzyBXa{H3k{OG4?DsiwrmB#>jLX*CETzck{`1JGxhpb%bIDzn#p6$G(ST#|HxSm{;pym>uoLte^=4nzowDkCVy8^O!+=n#3OIABw~Fg ztj`N6?nfzN4Zq91n@bnFyRafR&uIY^mTV~>CHMO+iCPL`+<}OyUa>x*CLGsx1vlH! z4IN`L4HIK>3GCNcI;hN2kQmse-8PCJG^{8$%J_&bkJkD7q(MXV6KTz%xbn zoZbo}qYz_`EPqsGJgRqKWnxr~f87Ex=yL)?b%2N&}7n#=hfa53KlZqN5w zOZYx(XTDll%2y)0@D-Udr?1nGuH^fy-T3OvReYbd2j6GC+VSEN^^7ZVg|3NfagF-K z)8Y~88;{1bX+RuPf_GW?7o8Iyqa@DBePWh~XNCS{(lp_DpOEGkjB2J^Gcbq6btr)y zG-I?e8WK!4CIf#98D*ByVi}uW5E%tlO8z?Penv}2jgQddC&nk3b)OlZp_gOEF$$U6 z%x7WC&zZY;?|^@ePFwnZG$HQ;zP~7Ce^FY^J-5G*%`4dpz6&pCTrf|Ow8{tnzo$s? z6c_w#_}3c}XXBUEKH|d5A-qGOFUP!Eyu*c;sDz)TO-S_6dH8}0D{0~ykGK*wk0qTi z=6lc^@iq0v?31n((zsDK3cY5#*@&797ZSR0*CoZR@771;*2rxH?@-_tAaZNtwn5}} znOj8Z?&a>~l;M`RB@}f#xt%G~EpyAzS~s^l>F#yz^*mOI@6u8&axM7R%Efnv$@iM# z$@TsInO*36&8JBG_T{N+t{BTiL);saDbDw~$yjVG0ax6~R`?#aYOFL?3D1=a#Y;ft-Mh{9J`E8vwLu~sAU7Wb7KStqSih_Yn!nRy*!7}rt@ec{KP>9k2Y$p z#%MEnoLM~17{)1Keu$?DEPjr_;W4{B=DHZOLG^6gcBsDXV*Cwx{JB3mc9BiRw1|K< zU#r#gEa6CF32cCjjX2j5KVu=|Y(Bzv^{bco)F*b2`7G=A_G0k6L?3OgqIb+nN0kqQjBt$ z;K@hv?oN^tuI9;dq1YEj#?1DA1Gx;X^-GDoM9dX39y6Z6cs3cEApNt(vylF%@h8gS zRWHWtond@wd`+ft!Z<;WDK<5Y^BsEE9An;0bObG5manwXE8zoKS* zhrXrxyt#++IgTsfIIgw%2lFUhYJOyXL~Rkxouopu()8#je7C-s3c+48t%CgBk{7h9LxFEhbtm##)A9Q1|=m_t!r(P5;p}P1AG}4l83! zSgk@ZQ3xg&W5UXej4{SqqR28P7|VoJWUSR{b+j^3WP)|HIz-Xx5Lt(#C>SdWMrd!< zYY;+=Ju~*;oSdc3{a#V8-mQ97)phTERrkH$LB)xmN-RJJ6W>aF3(;gpAzt?1@3HJ#l;Dkeg_H9-{G85?#+vbiFFj^(-hrbiHb#>(vllFQlu}9YSHj8)I;3mUwV_Yz{#e(68g!kyPSmLD)^(%LlC}IMq6z+9(o0D%q5qQf zYSOFdNYY1=($McGy^-_=`W#v5Z%g`}r2Xg*lRlaBN%Y4_ZzjEoI+6@Y4ElVMG0BL& zK=uK2CzU0+&=-@+lgiPbCRHU>p}wTwO{z!#HR;nypGNPz@74DYbNqvz`PxUxuV9;% ztk)1($%=yUPgb&Cd*QVg(C*hh3RjTzG-4MZvZ5PBR&+IFEq51Lzl|pAw=cZwy4&Mt ze_?peBCEV;PwAdAq~7BM>u49TjaPn(WMyx**w$~%s2b%pny*Y~7D z-G7+;H&E-jk0W-*~_giGYQYOrCVX$QJ?3P7lw~vw8Ej#fYnAbi|_ABj8{7&L`(7#LkZsK>r z!o~C2C&=!kTr#iigL&;`^zX@Dr2jznBIS|2NS`Eok@9uPx@7bz-6wRPKnHXMy0_4O zB=g-{WR5E$`;y+){jRPa>|Z>u(PS=TU@rS2*t~eZl9B9J;&t=7d9ZnZs{1Jt$s8w< zc}*sBnTgC_W-@14$UJ2wdzVVc-X&YoSkf3+#NSK$9hX$3UVe_ zBv&B!rXEtp#rp1muR;62NcO@b@|;{no|8wB-DJDS-n8B1$@UB6$@Yt6$JR?Q@3o=0 zJ%75V4=e_}TP~DUjKEL`s`T$IvH=D!@ts3{^6A;o2;u8wC+be zyiFcl_cW4I;q#46XO-NWpRtoS#>1Ht+j7zo?Ozumg#Oz$yrRe(xRrcLi6h&VxcT1x zjHH*7d^4{sMDA^Kj*}#Z?-%6wbCRQSOO9vT=hU|4Je%j6+m`ffp3~cuwY8nUwdt%< z>hpOFiyUt`O ze%<{)@O(fY*4qozFsI`87I2^$VeM!0-wK5H>XERXPZjZ2RD2VOS7O8mk$4{x3+0Ez zcR@|w)}aASYz*QV=-2Y6N=AjM9Mq+X!*5-MkOLtZC2#1aePC89S*6OB;id#cs<0BogZ<;ig=mq{CI^}5edZW;Z)~}`_r1R1NxcR=iM3f3@p?!n<7F4wX}gPf zJtPuKV>huhb`wiuH?cH!6R(GLU*>iHWiRnu9stBv#BSpCu$y>2>?T&k%fx<&CzeAz z@p{-rEQj61a@bA09(EJ2huy?-c!})VOebCsDa7j`nT(=0h}XkQ#OooIcs)cBuZK5? z2hPjH11FyNKDRq->90>0~h#!(x-#UY4?p$ru%1OHM!`Wx6UkA2ejyx(2(ul@FGzm4|b=dolY zw7?9ZLDA3mHkpMlK&xX3wHVo}>5F)(cdef%IcG@EyuUr{G4G{M$n}aZcNDo^MXtx~ z{Ss+o6={zs(jIEk9=l0AAZZ^yE_3SKnS3B*})#k^<%I@zYX|{a|MWR^Skj<-oJz` z!e@67l5}W??b21Muc7Dn`Qd$X0?}(e+^5q}ueG9`DCLQEM@o5pM@sp^4wRzWky6x; zZ|ukz8~(Rb$`kj8UJCsBpM2rT%ubYpKJx@WoBA+!r6}bbds6$MmxIT^p&jX+@9seF z?9@!72I;sHzs?W8XLd%;;QoJotq46`uf%tU--wM@HI&gFc%t3>zsmdgr_cQV=Z}A| z`G3%k|8NsOoZ{Y^0u~Ro`I;^N@A{W7KR*7;Sw&r?-X2%)aSWBn%pMs-t%dzwr$d4-doz*rESsO;?!;oByycT3s_Yo(n``4xIZovOy)Lx@EM_|0hIb)?=z_U+eOAMS5C9C9!q9%xNx-TtDD>9O`a;%&nC(CJa zro30)C+EwBvR>w7_>=mejH|LucF8_DDA&miaEt0uK6+7uVL-_3Wu>E0DIC7M!9=}J48vP?Oq z{mNZKz0ynvOhqQj#7EMVb|7dno9re}q)j%pjL9!KAg_W7=glqC1{_1CdQ+q6aHM6P zYZFtesom5SX&Hh_N(6gN{iZ>s#en0u34bAN`|lR+#Cx76@f+J=RO+z($?FN3r2|rt zL`l44mh6&8@=GD9Uh?pZQloTOYL(grM!X_*Nxee1)Gv%ngVG7(aODk%-I5l7ALfX8nx#eHy9AscNo&#)zsN6&^S~Rpi}_-{w1~M2@v=th$Gqhj zIUcx=$+&rR(is`AX|8{1aVOenf~*C`5?P3hY0y6Ef87D?r-7 z2*V`(q%ca-Cxj_sTDT}&5v~c>g?Zu5(|#uT;5yRN&}-!X%>>ure%UB%Gk<&?zGl6C z>vdeO=lV53c+}v!;NHdcCI7GIS+945HyK$#r2gx5U#~Z&t@YkYc=X|V0WY-uSKWRC zGc+|s$jrC!NBK^^hd;&-a3}a-R%S#vo@8S9QGSA-g7`GMkH5%Y;ji)6nRC=dexAR> z%JiTT;LJV#0dw_+vu4kR{|8b;coKKR;m9@hAC{!T}~m zDB?#2N}wPwa2I&NEZEn1uLr>+_=TPQ0vz6}e&A^v8IBN&<#|4i(erT-%n-Np9^MaR z-c+{_{9Ai=)-%K)Gq=bsagVq)qsAD+CK%)Cv(ywEbyTx)#h78thIlSLXv{Mf7>kVz zony!|ibgBsid6!faTvV@t1)1#H6AiH8IKq;xJSk|;Mf5?yN!Lu2k~~Ui|ggO^w^j3SN%rJ2fw># ze*MM6gv{)Hc9~t_5U1s0xdbk`c#KPfVvvDrNdCtcL zxjL>P5;(4zYvGRS5u|o)FHfGTVA^jcqSF!`xwFnJKo5?PdGf zL6(n%cJ>5&iXCImuxAf0u;#3lYH9!5YBrWlPy%xoMr0bB$?k>Gn9t<0 zg{&U<0Y}V}YAzaOF0dSBV`bLHa=`a0>tg0GcNRj?DCS#IpSF1O#jKq&U$J$;wHi^*dOm|{3Gg+)x>Tei5Nb7uL zDHXpJFgB_a{T=AaHXx8c1|Lums1B%M5$`0gF>PxN}R_>AV1BHOO``rcf79 zuM&rH)l`2ZeK0~NB6JF94CoBdS)lWgyq8FRM9l!rD(ytw*l2Sl?=6xKQ42teKubW6 zBKNSSlt*ind!=K5;(>I^c{(+6J|jZ#OQmyxp!ewlpyG{tA@@u(Kq8P8$N>a%G93V_ z1v&)O6geK*bX?Eh2GkKb)<&-D*mS-ds1N8k5LnCf2+--LN8D%hIMC#KKC0<+Py348 z8%QepveMu0>zMQG5sz>Bs!|RaOObR^?q-?;y7}}-##>HgyqTd+w;}y5(EZ5x!+e&X z9_bbQ(G$%p`VM`!zE6K#KSXeZ;Ay~d{UqQy{RP0w`m2C*`kR2a^>+dBRrmGF`V|8* zXbrK31VgeR&5&u>YuHCHew)0Gu*R1LCVL0$zdmHN$noyy1@F9^eDRL%>x^4G8H}G!;iBQYlnA zl?9kX?WYbBvyYzi} z84z<@QBoMhXx9;^fG(fFBr|DDCbO5|zKu9e&u0o5J;O0FV*|u-7oZQ~L8gvrV49g0 zf=4&volFnlF=ha8m^leJ%1i)GG1DY|5fEQ{g}KIDXXZiQzsEda9x|)z$f}uDHX7`a zM2M%b>1-C8!|um*U=I*1T9307%LAIh#_(W^WdpHQ;b9N6tzea4TLNQ0!NG`~(oQUu zcJ?e-D(%=-0i0!T0OG4|u?xiRc*L%88ZL&5=X6{umjRf~M$kpj2N*Qg0X7($0b7hm z0XvO7fX9pjfcUCm<4NPFal$xdoHkxGUNK$+yl$K~-XVC;_`vwkxXP>fXuvo=(YT6J z_!K2QayFgM;&b@@`~m8W(Zv_7BTw->Af)r=2rAFuLVP{J#*O%4z7?>Y?*i=Q`vC{} z6M(1qF~BqYS^hkKiJvhbewM$%-{KeeMSh8JdlX4o6EyrSAqFE(5#j}%kSb&d*+MSC zyp1?cFA$0aMi2$7-~hyNuMiMwg+oGr00OG6ei4Vkw z;;N*UqNO+~QA&~0r7S52a6iEV1o6sWIyt+({%4l_1aTa%1V&Z?@d_Zp{w;C59@tJ+ z1l!4)U^`h2Y$sRYHNhKXJ#bN4Qr7=ujT{4r*Y=j=R5=4MTh5gl83hUgQ;2H7m2r+j+#16J*Hy>2R3lnbP{mXGyyneng+aRx&nC3bRBTsbjNhh^uYAc zv})3u)#hk9+Z<<(hIpbm+MHremmTITa}MBsf;eT!e85~}rp&zAyajQ(-Rv>@O`YbD zx!&ApK5T9^x0}1ny?{904>$<%6XsL+zRY6;&zR3Dar1feCBPZ;EZ`0EEx-lyBH)tw z5#X9d0|?ie>MSvqc#F=GYRRxWu3-tV!bFeDtBtV zV!Z}<-8ydxV2NYBW4&j6z_#O=-}=zHTB7EfN}@~R02516l=-RMJ>-xTLkDy`-z8x1_&h zu;fI^sgkjhGbLwB&KojIE|ts}TqUz5H%e|no(0IWSh7^|sASEivBlWpZ8}@3EyI>= z%eCd%3JmkiHCr(=Z)0qt&1!SlytV+FVyk7dY=>-3wj*?&tarJ6yq&Ux;G<95&2+8ZZubEC z?IHTEz24pkI@qZFFw}N_daSPbb+RxiBDP!As z&pujnl56HWZ1E5Il{4 zUuEM;OJaSvY?9zPT&uDRWtYpYmR(Td1n0_bmffav%kGxl2Ync{;#;PP@~i%@mR3_0tajplZX!+F@*s?3DWc4wEf*V*qJbe?dY zk|&*G&NI%l&hv^6AbXvcKsFI66803=IoE~K zOni5)%dV@gIc27mW?VO2w}H=H*L_O>%Usv8YsJL55tdVKtvlA8;7)d@xij5+-TU16 z?n2ydZawDX=G?N|=61P#?jRG3=WusjMB4$hPDF5BtFgNqFe)kTW`Zra4(_7_JKa6* zW6~}6fO}Y4a-SsH2xunO3HPXbLW!H|FuGf?EO1ZZS=T+~o_1eU^a}SC1@T>2kGZe8 zuY>iIIN({Z13cq73(~pIa~@S6)zF49Jv=#?^9bxr5V{d&>jVLV0cZ zq4Flka|F(|m3NePm-m$)hqFWFBju;d$IB_NMW6Zzk{e?)C2T=6eghdN1ddy*95aVjUEFeS+u>dh5Im z-e#fJ+u}Xy?ez9|k9h~UfVkH?ysn3PPkKka6W%HBG{i4@uXwL{uY2dccf9w!54;b( zs}<^s=!&?C#EO)P^op#CoQnMw2P%pb3)CoAP)1I%bQGJSg0C=F*cB_U!XtD8`YS@l zJ6P6N)bqU+jTQA`UB%&w){6Fuu8Q7@{)$2GL+&=tX^gEnVN9+#RWVi(v9s8&inHtX ztYTwUoX2*hQ5HI|#aD4@y>x!CVg``dN)@veU^hi1 zk1E!D8h#14fG@@u@6#!|3U|Sm>dWB$zHDEvnD5K;75IvMj8F7g6?@R<@Oga!U#;(u zuL8U)X*qD_An{XIwag`?tjw)C=Q8@*cBiN6X)0G!1uZRd+k(JjfuUF2C znU!}c?*Trjd?@BuuKLy93EVIKXo7LZSbw5#&Y$8>7es%SKSxCV{r&@DzQ4#%vF(1| zZ}!`FTzzzicRNV@;~ygRcWeXs^Y73RjE}ORoPX!ReAn)Jbz*| z)m0T#6+5%=Y+1z+6y=dBuUh-+-Y^Q-Pw-LG1%S_z~1v2rR z8Q4p3Um!nF7|;W9(yf3Tuz9ZqTmhf=nj%vI!9ZQ0Aiu6R|3}p*8}r`JAr$F2Z4u{)WE7GyINfxZP8W7RVNA=iiE;g zonmQojo^57x|>rpx3bjgtm>TV{nZDmi=@PAs+zAhSKF&S)&A;`-|oLuUGJZ*Zmd4+ zU#o7dZm;gD?yc^x9;`l5eX4q_`b_m%<7)MJe^>RTXSmH&&sN{4zE!~Z|F9a_KuLkFWH-oo>cZ2tX%fXczRHLnltx2d!u1TxO#Qj^d zw`QNkQIlU&Sfj7us?XHO#?=~IjjP6|^j%G`rmm);rn#oYmRfVPrn9D}=2*=D;Bd{! zn$enxnyH%Unu|48oV})&nro)cn(H<5fOl%{)jX(qShE^ZhoVDqfQbQHC?%90%5q!@ z<%ITA3!wv{q7W70L*|e@h1S9v$y_}ndBQQ__^{5jFPv&B3}=M1 z!@1$Sa6z~@%!I|THS7qEhppxVVXv7A2g0@CLzcF1lchU+B-|G62zQ73!pFly;gRs^ z@OXGKe9nI(e8HK8F??CE`omYlbK#re+u^(6`&fGkFJmnwyn>&i)FR~d- z7D_Wpit=2gRxhR0a@G55Qma-}KSvtX z6SWFy)w|SM^n&_Dbu4;O9j|@`y`Z5e-$M~ zaZyH;yo=ezqLf_?yFPpmxchMr(Hzvqf;4zX2Z}>4qZiOC$cA1-cH~DU6hME1Jm?Fk8y!VG=trm>{Vn=? zbQ%3$RSf#EDpvIpdZKz+wMV5=rKqx1(JHgbrb<$|R5hwpRan)o+N1 zQq^}=f30#yeJko)swPdN=Ci8b)3j>ZRR3Aiq4^Wl5zUu0UsAPdzN~pi^*PPgG~ZAi z)r@M!RG-(J(fp;VOY?or_f6 z{!#Ofsv*tKH2+O?)SsokZ`RLyEXru~>|S^IHquIgvn zPiYHOKi3v&i&amw1}&x5Xc?`f)@n^!k2+3UsST)8wLxuzI$ir&ZHxL7+Rtmd)t}P# zXb049X}_i&QS;hwYQL$rYDcyITV0}^(axwpt-Y$fu5QrY)ZYAm?45hOk5v}`_p_hp z`F>AssZQv)3@V9kE|sJsMH1(Gj^p5vN-87WbW^F3uA`6?Ozcin*pW$-tZqw^M<$Q9IJH~;xco`^Q}bu$&&r?M`P|M= z<}bK#M*iZ~x13?}m*ua{|1^I?{^rh4wr-iiEErw;~f6((fW3hon(xC*}iN7JKat<*3PuAIO$SbYGV7Iec!E=<#xHrvMcRM zw_ZNBt4$TV&aN}n?3eaSw`#t!Uzr+qll{9}J3H(Sw{~{hAI*_r5C$eYbpJC)hjExN zwZdv)HB%?771lDxgmuC?CMT>L)-!d(reRZ4KWq`UG!4RbVLQ_>%nfr*qww6YgK4ap zH^)_buG(|vcsHVI!I1~PZ%Dmr?)ur8s!mkP9A?f^51gldrt{SNW(Uqqb!wX5SLdbv zq;&rYsXrxsmXlGPi|SN#;lKTsayqKB(abM%M!Nq;&a2@v*>0El4*oSP$jSdsXQl-$ zU7PeT{mk8l-$exl`I`!QIa&AcR4^cOQtEW(WKK)<-Na$nrgKW^0uzp+q%8-o6} zy~s2%Cz#lr)mSk-2F~6U%TJQ<{S4r z#gv!L7ki zQxN@m ztF5^uD>p0G+?v%PtAiPu)h#Q}+?Lfp>vD5P))iS-m^UztBRe@OmN_q!|q-dg-iVDW(XYPVHhQsYwoq;!}6 zYjK|Eeuoq7HHr2ki1wq1_H3g4XrjFq(O!pW&mr3D67BVf_69`zZ;1AWM0;bR{aB*? zIHLV{qP+>xege^cqFL&G&4~Ht#QaIb{3*ozsl@zg#C!{4z7;Wlx{G;h&IqC)GG`L) zZHV@^LH(eCi~oi}Lvs$%o=dd1C)&?-(SC{P5L^~qX3itd&nM1166c+W^9x*@|IS<( z+#TF)x&#loIKPNE?@FBK1y2M|xOJgu&v()OhFceJ25*|~M0+98UKA{Kao#If7A!Np zvwCLrG{sqcv-+AoSyyLWt-qJL=7^dP^QVFI=S_oddtF?*Y0OKw%hf`8N2Ymo+||Hc z$GNMSc+nB*6SMz)N#?*C#Flw&4!Okhe}=Fl=WPf6B;o(QBy->m6U+);7cGrPF zZ}`72$;{pVClQzN-toY@$L*YQI$G}^_4ZNk9(9VP_m2B7{r>}RApiH}-%k!s4M`2< z(pyQrlYBCLIa*^&jX7}f|NVQ)$^2KB-&=qAlH7qE_}?$>#~Hl`U%c%+aP8l#f9YZ` zPw(Xa>C*0=+2J$0{I9t(mB68wDuaWogI{xHs)tMkk*Ojwm4yC#pn~v~!=YEEe)y#; z+f@@zhpQ@@aJj02TH@eKZ(k3+3S510@YT=N8Nc?*ytzH}%Dl-v^m@8r+`$*){uP&= z=n7`)-EUsSf4p>WLBV3Z4Tk=-V8gGvHWzHy`{JKn(os<`t9z7wcl>Lv%=_ic)w+Az z{g>{a>n^=z7QO#XbN3O(KJeaFAC=3TY^ zyRrM0|76d9ySkU@y>_8F^zv`F3+w#sYEXFGzg^7=Puri{56;EuT$#yng=ZAD%j6)v z6F)eQ?2nOy=5_y^qsRZl@b-cl+BX#M zg~Q!-f8oQKcrF}O@VNTX{lY)_ckYEV^rk(3IPY=h6)qHCW7E5Ky=hl|)q8g3$-?ja zTXyXMde2U7cVkw(>y3LRKlf_b@eFl@7wjZ{m{4U_}BTA zJ;C{~$0WB;ruVZRQ}Z@t{M=)v)1!CsP6ziE=#6}j)qMAo*=G-)ql`{nnLQ=F7cf@0 zH}WoDwr%dQJu}b9ySZcTwJ&SW)7Z*;>=Ca=h1jwUt{=$JZ=JH3;xd(saP&636Tf^Evv~IPIw4VHT z4@LJX7Zr^x`lHrGW*zL$i!QdLM|rO3Ntc^4YeZjxxV)wInH+fN+B$SyW%A4ZwdHgu zZx)RynxHw?*A|)f^x@W<|N5ecyp#F%LOERHVGQXnFlhHnIVf#c(cW|(&+sb_%28>X z8SA0>I5Qr7<&(btYp(k*`Lw4=|2N_C=aK{0&+_C!xsv>t$&m-;L&>5?GRjTP2R*BG zf3N3}J?r#r(DOK5s%X*zHDbyjZ?$DPhswb4wGGC}x>z7P>ql zRSZ1UjhQP`CmwuEeRWjbPSAD>1%7ye;_k)Wt+*8^?s{=|m*Vbj7kBsK?(XjHcF_ym zkN185`A%kYCdrfJoXsYg-JN-cPz%x2vOBP*QQuE(*@SV?Dg8Vy!`3hQk=U|9ul3_~ zaP4=~a_>W`W%ch(7yIZ#>!K=SRzV(To7RVtnjjQi_0FtuRt~iq-&f1h<%cnG+*Z97 z5MJ@WrDf3pWvW;n+$y@koR5m@2v31cD+1@&3Nl@|8ZICGLV{TWJX}tB?+&{}1ryEFFr%prqM;DFx~sC=YSxGH=r9)d^H@X=Tel8`yCa#MzwBy>sa@il;o zZqIOKedp4=+|G4Z+W$Qjow&XfJSBII_TqZ@ z-9VS|k3zZ!(&`u>z1?mhCBY?ZsR-rE;1B%5Ju!!-J@UhvJ>EfNP;fjD1H=*kR%jPR zQBxBIa#3`E?D>~}O@^?wuKLNT@Mn#m&I=Z-EV+r_wL{8F-ShV<-DPf(UKH;&-aK!$ zH|C$j=IR>VlO0>TsA#tiy2)ujXzpQV{jWn0^nFCdh@AG9Tg2X4aut{cMRR=9Yr;S< ziaBs>w*`1Q55v9N=)DTZ8x!i{b2Tn=W)3+f>7ReKVap>Pl1|C+BQTkdS!0Ppu={If zjU~SZAc+M6c^`*}Uh9LpNe=Xl>rnrL{0gRcUN!XMN(c+Y;JzIbAO_MiMEBiEuO z*H&2W{H*4jG*@?af$Hv=a87OlE6|y@zgAHB;c%@RV)ERIX6aA2=+Tn*=3W}Y+q>5AgMl1~Zf{xjX zJp+HDeGBV=PJoirTC2PBhS`CdzJ7zFSMMu9-xxcc81IcHo8|z1B+@TRI2(VLK>8p&#)wtm88=i3cT?GOI1Hevy-NFcU#3_QL`tDSTy z&x{SF(Q*X{c)OByo@fAY1bgETIvML_9nwHaVVQHRjk-+K{>pa)zW=ALYeOe+9z zw|>Hn-$?UlgqVE--;_~Oc8eTqk@S-TP24L9==<#s4RE*UJ|Tvm5bE(yh~_6`(eV$6 zb#^MzFXvj87cD@0qkclkOVn^9VN&0tCto5)6iJ?4h5DeYNh?Zft|O;~SiHi6Hb z(bMpjO>ly@xHn8@a8+s83rMLHYASQWa|Tvwl3GVUBZz-%H4l;KROscbKTI>G4f+(_)NYc zNdw_W7nkO-150{)6CZ84b@Qe}9vxIsy5K_H5$}K9*^G3A8kdaBN6}fsB@Bz~F}Fcy zR1$gG9Ta$cV`s4o4~=U@@nIZH%-c@&(Kel#3N$4~T2&T#Jh8`g3onf$BHt6D53>Ct z7bG?!sUkW1>v_WcAHKZbjUM+i4+wLLYeq~~D)>7`z!tocaPUL?2JGu*kTvd{*I&EK z#6FptoYzU)9Y(L9DiX(=K%ZniUXoFHn|DExjgSR*Qd~Z3SWmC8-5cWEX?PXZM_2CX z(@2lTi#yVGZ*Fu7fc8>G(Gk*H*EEqKBy6INgs;FPh1`gS>@lBy=K8J@6nBC=%1V%b{OYVyRJZ~Ii~JOt&2CJ8=U#{=B~xvibgyp*+=1Py1{aiPt5=)kA;X>M5$Hj359nFvCq8&suEBoX&R(F6q0Q;pd!9$)sg=!5pYg+cpYeSMd!sd=@Vb9J@hkgD zilX*&VBYjEHt$+YH*LqK38^h^wk}w{buyYZRgIXaoM6crPV99YY_vIAqS%g`1#^T1 zwB%2F0YPV*f|@UQbIo zW2B93Z6$K8dt$}zOrEz21E;XoB5cI>ipE-c7V9#sZI z$c>$D!Yh%zXz{=0>?|tWOn2~|uaMBs%B7lgRR9kJf>yN(lK+pe21hnN3C)1c;z}KV1O}u+A4|;&|aZ%FW1>`5X z0L-TqV@F@%Cm-fl-kdXpFn#N+GNXZ7C!>!AiyHz8tG~Lqr!w|vfQvC4Y?h(wD2M-5AtA`wCZe^0 zE^858uo5xE96z+Wwczr*k-T8btJbmc=pa&}3t5Ut#y>9Eu@wP%Hj?YEjqgFtG*>a< zw%Aqerd&>3O6IO!D35Gd>oENC=B`#(7l9&@?GCF%B9f^hsdH*-*_6)SX4*Gqd8^Sj zi{U9eAU(osU9s!TQ=iV`nSB!LXX?9avU`QAk3_($ zg(DS<8>!%F0I`-oH8|cN`atj=H1k-wQsqOyr;e_x54aQsnnvN@4(*hNo7=_K>)&wPgXsa=Fuu{L z#Re}eeFg}4#UvhBDH!X$KPgJ)mknMsVh)@soZ{1CCK^XB2Y0jk4DdSLhP zrr9O^%=qUCrk#h_CU1ZLpK8jGw3|Lv`NW!6a9FhEZt=5IeNLUwv?GCj`L}aExuC@n z&l%S&%aW5A+r!}rm_YXo5aqz|%NH*T2G}oU2W!T<1yi|^Ub(?_GZE~5gnY35%kfKs zU9B&Z@w;uL?Vm1m*!8##EGA624q2QFsFp#%Zd5Q4l)$%F)|2tv?NDE0Pd?A)NGhOJ zMXDI4XJzzp`=Fl-$X$SM#TL{h>Ehz<&%CnFqu~h8Y5k?8_?Ad|s3bz+fO^l3@YpI( zuGGfcyJKXQ=N4*s8*LgpdJ4fBXS9@#KUD7nsao6*2B0&JLx;1kHKfstv&=e#V672} zj5+cA*FF6FP{8mHH6i4RhFs?-5~mtF#@x7w=W1AUu=)D`u5h}GTqv9$$7L}ND4#|; zqub5}hF=g}Ov&rFIh&9_ezLF65u8G@XE?u1f3=%O!ZV%W{PDR0QaXcVBtN4$ks3^! z#ZzV3{(VKXE2u%ni+uU&N%sD+!(;J+x1kz~Z7^yo;ecJR5>=xn!|E-U&^y*RDNp78 z%eG-|H8MtNuWY*A_1U?M(t zQsx@PJi3yI90i0MEJHCv$vP{q*i0m!*58B66plPFj@=W}j>{qFzLZcOt4y|U32JX} z=GyAby85xL+TBpob&U4H zL_y3DDe=8x@3=>w$=7~f?X)qU$(d#xKCyO9=#Icjt{-PmD@HojL|_TOUtTv>MPckEVgPC!Z5 zTWiPAlG&SoOYL3>i(60Jbx&@_?h}o_N;hA&&Nvmb|2}E4n-mnWzG&fV}(lE z&I{!&T-78!`R|P(z3Ekvw;xVip|cOmW6^I!oeCZ#{)f_2#OTX;#}u1#-an&KrG{b- z(j5?|KeRpWvit6j@IQ>9U!DDIdz3j7dX==~o)j{Yr)QQcruwjXdebg#VoXPlPQK1Q z8xoRdL<+$<>D^KtW5T~M+?la%VpN3N3*ZMZCWdv<`lyk=ni@A3Dp2z?e4z0+s0aJ; zzm@OMLw@8Gt7CX=L27uW3ZkwYF4Cg~V%cIxL2S>1941 zuCO-`gN|USbuumLmdCH$)BPU52%emorWpDRs0nf`R$BuU1*;!V2|f-6c!%{9-2brS z8vK0M3q}?dDCrA8CR~DD4_vg+7FmC)y+NiYhzYqh$B7Bq&7$QW!yU2r!u!6o`2wU?=t$;_4C7Ym|$h6!hQ5 z*!G1gVfDy+d>XJld^upB9qn@0%dmRY{ADIR$oA^}ur$~_TuXtE z+*C`7FVwgv2BJ0wQuMizdbFK2mPX6~ry}^2lA9}blM@x9omR*RhL`fL>MzVy25(*K zx8oO>+kfcxjye03BGi)dI+bFM_Sj06R#4}<*O}+Elobe;U|EWI$6yosAe-^C?)wA> zer)k$|HhOsQ&iW1hqzpR7@ArBU9Pi9u9vwJIg3_3(exJ(O(xzeK8WBrNLe(FYA6e< zFD0<7IFeQgui!&TA2U^kT%)a7m&X@TCyr?Ice@vQmLPOWnY%MKOqLCF{W?O_(hZ(Kv8=6#TTQB78qoX| z`+hSK5aGl@zVgPyN$s)rs)+M@D3L$#AFfKL3aTfE0vuf_>@jm&UevkT(TSQ?G-ily zA@$ZTjax;DgovA&Vuq6ZP+~F9d zFAp7`?M|g}tGHE0aQlSDE~kJ=^3G8rLzGC$;Ki}LX;sB)yzZEdK1(6FJwnZ?&Wu}N zs>qZ`da?uRgMdPaR83z5$dC1dGK24DVtPN6FR`dRiq1HIv6^PUjjM~SGTix$2-ji7`5hj4QGaD;x{;Yhf# zljqyi;;*+cr)-u__BGE~?JC@{C(LtWXN0^Dp5TT9jo9`7B2U&?eg<(%h$?F-j(*$j zX@#Delkxz!Nws>?xX1&tSt+p{suyvlRAx14xRqCFVCTn)YN@hJ%IWs3Mk=1-LvM}u zcsmBXdIsd`)>{+cEt_FAym*ea-klk-b9zp*wh2R?6E&_FZ_R)zR)jqBU1K?cs)FaB z@1&#Rc(VB+Eox1F)MQ+=bb5IV5%c%x^YiQXQ04n`LFuhiU)JrF*5Vs(Yk2Uzu{?it zO+Fqsnwt+>yT*qY02*hcyXcXy`c}tVb^PQ9y&Oe={kWS@*1*$kjsaePwHV5VEQcx% zmxCJ@_?encKGv!NOWc$<%gm$uk1}g-(T5M*Vp7rYE=VJqe)N)axTSF# z-%joHe$`1uYYwA%r`8azNM8O}#6&(O z=br9;DZTsIS!U=rkw=y>YWu;(ej(~hytwek^^DeDFE4d#q(cPud|>lcit~m&0eLl8 z=nKB%Qj6lY)=Ges*$>J8Y`!LpJHKK(hG5VGh_~~Z40VohNqDo*VdEfhVG_lpE`xg@ zi{l@XIg!nLvrcSa7XjMQ%-vXjC)O+$`wt{D0#);DjS|NFQc*1_QL;!33LvN->*gJN zPEekU(F!K#I0zqMS9y$tkbNdK=!MHtMTr5W9N?ZE2;CJzkRGoKFCR3#Fdx0c1(pH3 zsT)26+sPf8=X3>Y%)W)ZF)8jEXR%A1PZt@#Bz!pgxi@{lb6V|D1g7x%XP z5MN@aJIBZqQm@+M$$#=m)j1Xa)M5jI>nAVKQX8h*hzcTkr1|i@GIl>*64&Vk#`m6A zH6?7jw{sp&GqKd+H~O|{)A4s81@*}Vv$%SpO`0dT!K!8ki|C(`D1OR4dXLNsmCEi$ zJ~%H`@y17DO)etiIzMi#@1lWn7j>YKmu3M@LhAB*-tW3DZ_4n%izsUKKANJ%vR$2} zDHpL|*R$BB0Cb<*q5p#={NmeJd|6KuC)iGVGs@C>dyrdzv(t_tm5wT?rX;wj9i06fRs1CKhyWId zHxlj*YDL)<%?^KI<<sskF<3hT8SzNn*H_{I^_ot%)kBopv^a@VRHqKRB zW8%YMkH^+4Jo1W$k)S~>cCrmpyqEkN?cr9wg{eE^h0$5S+ zfwsBXR7BmVTh3lVaxI)nQ)g7Rw#C!6GGZdE<4pEpunqthbz7(tI7M3_@7)|lCb2u? z%Mf+!j#r^oP8$aPPq)|+06&tm+uc*htT;XodM4x45z}YtYlV-s335u*w>o%Xh?j=} zBL?C&^5Wr6LHE0jjLPj^i-;=I`yq@&{0|j+rAhB;SzA6^oB-~%TDNvxHGX}yT^_7e z1obq)Z1jQM6Slt0kSg`KMYbL}{9o_QG*Q8pT3T2F4+Lc~Z zPv(cY*dKTn^GQ9aZ&TY-;lCGT8%&SVcI#fuxu~tyYZ_dW>@%HRJQMKT+U1{ZrhnZ! z$;1sc^k82-LF$#xm=5YC(bD}HRf16P&0WSB+v?uZbqEzC_BSNQnM+ZuLZp@hyiCMQ zH^+Em;a+0Oxq!bYGV2=j0m|xB!$E=X{*{@?9vLhQ*hZM5HEh&9ks!^&5iD2CEg|;+ zmdq3uR(!LM zEGGps&B}^+-qP1zRqIaKyAcsa+HibUmPHz>*UHu+9DxEGhJ0QDKnDuq!k#OU`#@%- zS$ono&ow}j>V>0o#FkCB8fOSF#F&d+W#*A0AM`lI)`3%py%eDeuzt$H((A;=fh?YToK&y!X(J&Y2yMLErRu?g7$5pO z+{m*|;nIBws&dnmxbg!B_un&dw)9HTSQgnDJ%Fa3}8tX^Vww^H;U+ zI&;qthF65gRCr`G3(Y=KH@;KIdo!{gM*zrYIq%r-V#y)gS(2^b(vsHoq;|Q}cl6iJ zfq4zq9`Y>G4MLIb)VVXI*>HuMerk;sB-soPy!8b81p78&w|jQC``v>AGdNGz+-{av zd~%*IxYl72yVzc9V1$h*o6I^Vwv5^DUdYk7r~QpS8d=8Bv!k%Uqbv9gfv?Ed`Iov1 z1%B9By5{GhN4_h6TgW>IeZwX~Z)yVkFhMpmEu?Hv>1Z=BGcY3?krSOWEuz~f0$84v zCx3q;c>h52LaQ@#N}tzp_We7Bx?}gZ`zszq;|S^*IYDn+qp` z8U#cTzhf^xO)CAiSyX_#r~H&5wAEtNR6KeB!97$c^#A z$86YE>5)xRQ=*PUZ&f!feSSnA_j-DGI!)y74?8n@Fm?8x_3iOyy#Pa?PJjQnR|vHYmfgpsv(mT0JaZ7I0S7>4Y$^(JmQXOW zcE`Zq3YrR;lIW_QK7O``=anq5VNW=Cq3{sYlDn>$^(M%O1^h7Hi9;e_bt84celY0< ze|taGIdh`&=?pork^+Vt&DVxLBp7tApgh+?XXs0QxE!pak#&>TZUMTt;7Hm28(&RM zxR8OrbIteH*I&6o!xIb$Z2oTZNb2bwrq@i`fQ+n=y9;mbIux{x8%`|y7Q~fzOqGLy z10Y|zMk2fSdZkns6I4$k)tAsG?uX!bqJt=mSA0ZVbL^=>@}QQ&?UWVh?7uM(RIg)b z3`y7Hm$PC+oRCu*j1cCa?;@Y?`i3b^$j;SSF=QbJg*3=wUUktgL<8lPcR)65UtBMQ z8|A!#J_pr(?);)Gsc4at@Z|5S^8TItUkDeb0sPj$XTJzXPCkO!|xfO!uEEbob; zA(HGL#PRa&9MP`l_zOqKmH=|P`gqJD*SQ8~C9epa`JYCO@hvT%GTS~UaXt3K)30a- zO!q+8_DE=%C~i|PRpQndy){d7Ft0RHQZ%!oWNxh%kx?nJAjTq!Fo;yF=j|!8?-_F@;auTB4f_NB$pLg}l2T^*x`m(4EKWCwj=HA}Bg7+r=L3ZGkZOh2{se z2DXKDq%+f9Kj&S4*#gyK7>2p7^-$Ye1V~>|2zNmN_Q5aZRY=xm#BCL6n?vOFza~^g z@b^=X!sB>(r%aJgsWUv>vp`nonQlpH-zhq<=B5AX4Dew34n>VS$=mF7B5%{oC!7zpCMtJ{o;L-?cJi6Z@%G zS!=6nM6>l3LVcX=m)YR7ExaajoNYGiajc(vKec_h;&IHgp;w&@CTl^ZiIo?Cpl5r2 znD9Ql(K(-akbdf_pSsnj&hn`Xeij$rhmNFA++TSCrUK>ZmbtRy!wo{)EGK&mDdNwK zWaqON$ojv65L1DwRuJdDS=9FMfQNwiSry4sY_%y$IoL|(V)FYiD zB1=mBxrLDJL-YylmNv^-o?SiO&Tp7LKfSoO`#gl~{P^NVFVyt;Ssb`?8lP^Z;sx{n zHp{8_yq0_kP?8?9d8e+kaECa~^iSb*;og+@!5cf%2YLf)^x7m7p+Ca5|m}~ES!~y(}4`wouD-Lyvw5FygR0PULrnUjcmy}bh%BX+N zjLqt2Up$-xw$4sHE@~X=*@r&Rslj|%Nk=EtV5=3AKAfOFoT-n@wm)H2`uVyS;RD+`X0} z!)5Dsf7V!vl@82a?3uHnjX+Yz%$<`&I`dWUXlGmmf?u@+9!`?6v^ke#oKHh%Ok<211UJppaAUCce*;u)lRDt=2 zRz3rs&B8gOft&KTG7KjJSN$7e*UY-z)8=WPHn*W_`YY(!7O)voTiG zO?onBO<&oNEmPx(CEBWyYaSX>8Z*xtIomQAt@gu>r#|A=rZ2SHWmCLV+e;>y@#jq~ zsEF9WGg!F{v-1dR5w<4eb5#rNvl#T^3MCw8vzMNn^B{gsuqWwcqdrsb7Eci-U^{Dh zd@)Whd`l9Paf7^B5LtV~(}}VK%;PE_Z$pr+w#=B_*GkkXimXlaZrrT8UR+-=d;Qv} zYzB^B^-K0m0y?75r4%2XQ-e4`?lRZ?TZT3#;iW}&>MLhQp~E1jHQ@*O=UQK)!y@x# zY~TEpGwi(VxfIan+?MKlh_5X1JT-`BZ5$vmcYWTd|G@JOKbQZ(Z%uKb`Yt{o;ntr` zhHL2?Wah=15D3f>yCWBmp9>>bD)Jn}6~wgp zQ&J$eX3mb_)iD8NXrpU`dm;!4j%hfKyi(RK02jcqFzL>U?h0yH@L5+&R7DVl6NO^` zC$7+^;4FDyZU?gdr(=WKBA!wJJuBQ?W5||Pb#i!O5Aqa?-HM9o6WQf4h-YBuBYiFh zNFai^i8>>@(ptz7i&G9vMgqhieuIE#(Nm?K&R87d=F2g+{1Jj7OL%gTjHSA3y8KT{ z&XlInMTyw#0-6&j-QN_jJqk< zxjq+85@y)#!YYz|SF6170@-P}W5>zFKr) zk3*|%dV$fPGoy=I-XEtiPs2*Zc3A-_Jq7;US2P7NG<6_C) zZ(p938-1~+!B7<34ap4w>99DS)1V|tCFaa*Rg&bjSV{Q zGI>vNG5cO-Xa)_|TiG&zpj`FNm*B?;Zfcxj$RP}NaK4Hq%H$Z${XFss6dWv^FG=G% zO&r$-jZ!8W>G2JAT>qIEpEpZk09hO&W(C{ruAihMtWXEcI834Q!mlEFEHzU)vo3(O zvS6SMZZLH?aXDK*GB&;yWHQ@2VsCiKnf6qU0uo^oDV3{(Jl(W}d28)NI7hsY5rpA? za+Q7KIL|X%?~$K|9oP=wo%siUM)l6RhrjZkaRFnq(?fT{&SUKe;^6rzZzGa3%47e* z(fVI?nhr;+q2qWGzyRvEKREN|`$Q+K!h|4}954|3+@jt_WC-?oJAfdr8(uuu8H3bsQGeHqJMJTHJ0hf+JK<4#3gptZd*&&&voGxA^wVzua??w1 zvh#Pakoem80~fi879L4MTbqg9#s`4b1NEpNNuA$h=inADd?u<{$kMuVq$2SYRBLX} z4cf&!IwR-UDqHaQui#z%{zcNeM8mJo(Qd!Eaag_iy!2MQ{*gAG<@C#uSn}Jsr?Q~# z3WRhU`=En+eC@vzKuPvE#HDQyct;$0vEHJ1b#P8EDAdftRUj7Vy7%BL%bqtHMyqYp z9P!RJ>}}!@u@Ad?TzXnwv)l&`@x=mdR_O7i_U@>xy_sU|`Z^1rtnT=hg0`yQIlJ^R zuE)0z1vIg>AdD)aR@Xg+Pn+e_M$I0ZN!F8+la9}^%$bq{IEMVn?nCs%tXss5b~$)p zny56gx0M_5T^J{Qibvr-CN2=ypvWXa@zw(Uj((pkxEkVYga<5xFRhUWEzkJWrL&3Cz>ao#eyBk-y0Te0}Jt%FQ(B{q8AvLc=%Itx?>G-$8NT%lYQT$wgRO`d-7 z7XsPdOHP?qn|@?c?iE*9`6j)xf^%7bTgL^Cw`DoXr>Iv03 zY{1YvxCx&CGv%5L6B}t~+rA-@AnMYJ zy9StX|9v?3{5ytu*jElL=z8!Ij_cS~FrJYR@_p_D{(TW?^Zd=mg;M~h@kFBQq zKWWK}0>B0D9swa(P13u7yn2={>SeJ)PAKGf8AkaP*=q)E`y|Z5d4ScEebiS(f!a;4Ym?^n3w+gc!Yd{oc{O2z3s^5oBU5EshXrCY>KhXeRI9 z*?QD$P!Y%Rh4$MAm*!i_`vx1vj3no>s>D z^Sdv_qrPY@4G!`Z!WHQw%+r4M4ba5@J(zG@NGpZA!esTXn|^W&Sy09dbjscZTJAYV^h3t@R;0F#2J|0!HZUO>XvEg;HZrqRz(fnIb+I6W*t{CgG1xZ)c>&g;sSu5Ie zmDZ_5qWvg|5|aW$uA0%#sO^>LPYsUOg=1w1!$lvw56fALdIn58N*BqW6PBi_7p$q4 zkmC3C4g5z5udMM#zvV9c^BZU|YAe(F)4E?D<{ICn&|$>I=A+QA%mvp4*FPn&{yHQB z-19N;5kv=uY_tbg99S;-g3ZAeSA=C6w28FMPg08sU*42%`Z>#X@mmBtXgQ=6A1BF) z`%1T@eApi3V)p%dAYUkjj{GJxUxfA`VY0iZcW^xT5ao{&9op^wC&vrO7=FXl9}p$^ z>s~V-w-q|Q-Rc)Q1?hlfj)?xfQf|gA%gP-{>V*|^$fqgnRB}?v zs;YB7r+Mtu0`XWy$8(6QRA$~Qr1y?7SxnfYMfIZ93EB1PDTkgs6zBg#1HGB5{TcBr zdX>tTWLdHa+l~Gs4mg-0yS9OSRI;lO}L*J=IlO3`c?y~n{z}qhC$w04`S%a($KKJmt(K(}cE5Ks+(ThR?4^7I-&%AU4*i_W>>D4;9gl_&0`X2aOoiQ!(C%ma z&bVKySEi4;dV=kb|SvPe%5zV1*KkA*Idq5Dg2YL z=yv|YOFGOd?jR`hkm^4Dx2r111sWAop(LX{?7$TmP7_cFF1jkqA4YyZ{-Wh`IE&_XF}}GLE15$6H-+7))5EGieqBzgy8@*`CKa&(LGZFr3$jo~xDVT0Xp4B5gtn#6Km4TZi-W;?~s!foF|a&_04Q{t=o=Ps-I z{eRafwUIALCC)XnzwAb7?AxIU%t4=`-H2p93B>_rrhDp{YVJDRe;pmL$I(OxwrfzE z@pvB6^Qc#@+hXGr20Ho!YTs&CPVh1A2?`upeij^$r_dF;w)T0$s#d4K?1W;0V!YT6 zVP_5qpY+l14@x^^V~jXfTxxQ(KZBhep37)$kFGFCS)B7V)38Q^p3iS7Pe}z3tWuy%m6YirOt$;|)8v z}Nenwp*0tQ(l&JNiR;F#pNT@>+#Wz8@1mjBuRw({4o=*D{MALq1$;W*bXu(MtbQ zymSo3)q+L$)GJy)?KedBj+(@C2(Q6z{ih?3AC4&v8P=vZiiCI~jxCU<_bt_iS>phQ zA!ls^Hn6C+m)$fl$?01~fP4y~XSxrp$trQ>cJptSyj&t{`2`r+mg*6U$|*h~YxrhZ z?Su0Pgtx?A*VeD>Fnn*Rg|^$f2B{18yY!jx?$cZ^PafVP2jkCveCx^P zu8ZGeo8iF6X$0&W-(g4OvF&}=rB8LOEw$AW)xpGvdXjbs`%Z)^?smM$6u1Uk$0Q^fUCS;3OkMMs~!yY zL)yeAs5UHz((Srjj=WsQWE|e~G`@)lrY*C4Bt7 zgOL`iKN^ej1iI6ExdsVVq)C^TQEMtf%q$bEtmz=sgnr zb{5-PR{Rz>B?41`8FMzN9=2V**)3Lhfrh_xR~pk$gkO)}U(D?x@|Yu`qwHFIuIr)9 zrE#yiJ-(N0_wAwQm2QoTy+f4<-K-0{?|xMQ`$6|swH+0n0+j@FXWd8L&5UQ3%ms|D z=+T%8=mjI@Ktb*2TmF>%cCiR2SJjqhFDWf)p-D|ktkxeV1ki0h!~7lM=U~~m%MUfb z;UmZMsPyYsf>oO_Kuw%(jYiqoVzOtV8f~E38G}~Yg!%yR0&;Y!2_|f-kw?QyB-pOK zZo4kFOTu}K24B5iy_kA8bPdNLc2ORaZzIq>X}_P=1aG>{ zVXh;l&t#u~534?_?DLdIUWRlME!o>K3hTssmvItyp-7&5#&^CQgcl$^_s}gwZQoEj z1|1@Gv1!@vz}Mu?puu$+FU5TqtlR!njY_s96AjT~mkj(qr;y((PF#tN?%ES?cxs;m z$)1j@ribV2Ej4EszD)D}ZPkTV?OZy3*7J28Q`|x|n-xP-9$r1Cg>UH;tKDChmOl;p ztmPxW0;eqR%OM`3*Uof6B)ANm?uDCTH!jmpby%NNi8YmMHHrC8s+yW>C|iD|JG((W zPq+AiAoMAX&p5#AU#46uQDpmr)5AgiS=~u; zWeE-UbNiGR$>V=|IXXVoPCFgvWG7C#U)5>+pf6u_T6%EO?B!ao+KJkZdcL_sVM+VN z++hbqpNfR^;G-YpUj8udI`4{O`T<`wLnwl|$oH+pO6CTk{tr{oH$rz|HgnQW%)?6& zxKmvbu2DcPoQ=uIe5nva7TRl`{&z;j_c(iG7xGVfUX;5;gKxhB;R=OBUOH})KxTcc ziMA+(d6zaLzjtH!=Cco{g7tP7i(gsYg6-FJFR?a!-DWnwlnY~oC3GPkdToHy7!TT? zlvjoA|FeM^Auko$6TA|H?_BmtIrG|tF2#4&rwZwHv7et{lSl*^KK%pRDghm)lPbN3 z1Q3bZv3t-pzOoU~NjyAGC27MR|yeQEYsu z3n+iU~~2#m;&_afjD_gnHC0=7VKwFdm-|-CIUh3*fq%OomCOFbBmZv_lYaf`fJtC z3bUuj7PdFSE_lDt?nsa=ge5^>r?DIH(CqD<>i;{{uh(x>=v%cvntiX|y5BItI7J$) z8#55@$cNb9zqrV*I2+M|PDr$mTv7GYfd1q?`-aaI)W z>S^H0e0?$v$B0>Yri^!Z|KV~Y`mi$-{X@L+pY1_9E%0CM+3$hUU^QW-V@eHIi<@$u z{WK&!jPf*~()1YBY;#RjpThDr;PCtr_>Hp0aN2wIW?)hNbR~}Agbo(qbJvyUpo0gT z{*K=7LA%AbweHlJ?vjzK|g&Ha#|YlU6HQ&t_WUfM7j-T~E;Go%# zeLKOvljsF!!GNhV2Ek=8Z0gs+O)v_^!CkZ6J$Xi+l^-X*ZD1%?$XN#ap25^vdA5=V z3Y8M*!&zvM2RDo3b~6BU)=$dEY6}BD_7ZVNUCFT8rD_Wi}E&>R}Q!>2IKupTlCCSDOu)b6fH|H)ffBzcu zn9Rm`-2MA9kJit2ENsi%v9x1lTg8qQrxm0-?apkF?#y!*LY6qoot2=(S%Z8z$~{ie zS?6p7sx$7~{n0MxUeM+|;Oqp4okyJ~z$wrN4m;0*^WY-5;=GEo8{pPz{ZZ!_m;h5O z|KXzZKIB8^obw4-1kX*K@xnRhvVja!=Rpq02SuRNXjgH>-fx<-&^Pl^J{%dYty9LozF`j}_e?YItZQdt_v+_oZQLFR%2Q0z#j@-mc{IqHN8 z=+!`Q>=n|GXHa{y&hLmrt_T&lj^%@(g34ImXjii=RP5j=-+(?U*mXOugPYLXgeDMm zbPBs5_kew1zvD2KA4K^<$1ULy^dsQ7;~~m#5k`BX?xbT1vJ)Jpd@ndeWvp+s+mS0A z+EGCHv*_axyKcuQ7#9u+1K(&92DU8;gAS{384Q47aGmr#lotv&NiVO?B3T1G!ev}D z;1E$S3Zsrj=<1Gfs^2Y)qiz)Xs3}>0qv!{HP}{r6-(ziSo(i}I*EOP_M%=%V?mqxI zV@RrF<6zg$LVwKiJJJMJ&iYD}EeK1(3i@JWU2s_4R*=qgw_R9qXS?%AFLalXEC-cX zgC)os)YrH@ZV`H&yOHWu#|dG{?Li+NQ?mX%?riDol@r$}{d9PHY?$hT4cfa3&o^tD?TM%^=9KaaNaxQ^usDns9_o%=BK$1E>!0xM_N&90WEflSy&7Gy3c0L8*( zDlZcT!KhFHy&4F@ILb!}qrFk*$MqFxTY>9XJ_stP41H6(S?G@`-ypDZc3q-uL1+R| zVMW*lxd-e6`>|fE{2F~Xk&w_3iI9+JA|)hJBvc|IBtk+Y zLPW#~kqk+3G9+F?B=X10i$sJ(L`Xn5^3pW--gm9fK7;5}+VlSE`8_|+v%lwi*IIj@ z{b%ic_Bm%{Y1wKwL4Hr>_cAHtUd`7cyQ;2dW4{L_&6BjS-;#dIdp2HG*KbvLUZVO7 zZLX^8){)<9!?a#xbNX$Rw7K6F`Mq7zE=hZo_uJp^5a*-ec|ZF1+MM9`nJ`It{m%8v z^gCDU_uEq2`l_Wp#?)RcseO+zS1s*XSX;=sJUkbw{(Uyx^mpYHn`)DK?s>JOfwkrG zyIXZrZH=TplDhRA+4Ew~qr>w^^zXG9$M36c>Z!7;drp*8S39u!*i|cfHr5W2G)($o zMZYDrBRQ`M&r4MQUK{B@mDSrs|J6(X)!Y879W7~`q>0M=?XRuld^9}oNB>@%6Z-po zBDFATp?+7c)l>z{~g%|Nt=}Sp4)pt@5Pdy z3)8aRD{E&-nj>j`@0FFgwTmPztsE}r;c`A*yF$|H%I4a7IdAATxOS5yxj)v*y{%U6 zgYX7yM1N&dZ9{Lv@7=v$5dLy)L$}GbDW>IN&hOplxwJ#l>b}jj zd*!^LUv2GPNh;qVsUb|O(M_mr=r@_)yIXko`Lzcm9hP)V(n(2;lA5~D?{B&{_K$XN z6n&%U8%5tJ`bN<=ioVh6t7i9aQ?tDi%V(QN{vG)fjmiIV{!_-!|7m`M>6gFt(k63F{I>XQ?sVgr-?(oWjVP(n zfR;xhMq};7^xy0z@{p?%_fN>@tK3E#(okteW5ucbR>jEcihegFXZ&3nv4(Q$ke3j7 z=$P{86l}(WgDC$br8N=(Xk-`-sKjV=AC0QA9LWP=#Gq~_j5B23Ar{f#cOwazCSnW4 zh%;0Vj@S4@&MGa<-EE^2Svi)A;Vvbd1gC;)y!raKzVe^eLAX1UxIV)*@{qfYm_Rk~ z8t-{60sAb`fbzn)M1tl`wTV@@xxPz_rgOz4ZCOrRwqrR7`2=b*m#eq7eye3hs?lx%ms0ap z@WI&cr#=&rY_iuSZ+qlhkuW08UixHEc*PEsuW_W>+O|`lqgckN;de4Jb4`PySAN%Ox_J?g(Ngd@Jz~-o;R|`LYd<7o0j;q|uRgTzE0DECSUFBXglHs(m zD$`6%xMuA)aIT_r96W@i5Syd$T;!XOyoKa?un+PrirzK!Kn>%yjk-f^cYAw0*Y zMdj9ivY%E@rarkUY1LjaXQcH~?WJfO`=iPu1F>m?WR&$=&FdH164cY22kE_$8I7+t zi5jkfx6a(G-j&gaWqIKBT?ZelmQEwNs^Dj_+(rot;Pa60rPVu;mmzr@?ZZg+ zQ`*Bw`eS)YQC2iOfwm8#=0j-3o7CZuj(8M5bQfuR{S%7PKQGdj7n$i#QbV=RP(rtG zG+(5Il|-Y_nHys)K7qCmcm$t$oicZaJ!bns>wGP(I7BbCM}84F63a>96`S$HX8idK zzF{r3#}dkA-8jPvpf;ny1xRkjvLn~(h~+MFZNp}1=v}HkhyTn}bTZ*8*8w@RmC^5O zXSZG7@S>BZ9rIK$rw}h<#qf?{KMrJ-^Vieor}bLin#^zU{4;pI`p@ui z?xz0M)8^6}$FX?^`6OyS2>wart7y?)cs=rgnLUi`N_ZW;eMVz2aK-Dxb*5VP5{%Sy zjQDHFX_5Og@@{5)C)-h08<{D@*rRp!-n86~yY`z|tTwXdyhxd9+1{?e;VRvMmcB?! zwan+}tC;d=l3tz4RhCh=Wt1>1oatK5t$1AtIEFf$2v=;yk(9sFu7sH-jAk_}|6*!V zjlJO>p=Hh{UfoGEj@dCzM=*P%@DYsoact`BN=`lJ+1_(sW&Xa1XKK4%ws%G>??XPE zHZEet9)={zy}gUytDEu()mm{iOx$sRUN`bUaVt6@67sQIVt zy@{I4&AdWXX8p@j?zxd!)U621VHx&6AxP(8Z`bKxS)-GXABW0 zZ0s=`@y^D&v+?bSX%|MbBZ8fcU1#If*%);;I-QM3XJgUX_;X?8IpQ|iICD0_oQ*9P zMwPRXGs8~-efd}gDa5$DWCIJ2?MY*aHF$;`$u zv(d|J+%g-n%tk4*@yTptG8>aDj7DbTkP%13#vZd#$85YY8)+mfE;7;(bF2w}tqvvI$|SYI~EmyHN$V|o$I%f|7F5D6xX-9^+c8?Vbo z>asDqY;-Ogmn)3OMXpw8ZTu}8dCSJ!3ZrciXUoRZvXQiG3@sZyD~y|EBW4j{$i~64 z5wL9RD;xF7#=EkSu564e8{NvrwX(6SY!oXSzsg3g3S(B;Swj!l2vs%)m5n|X#+@SK zR2XZD_&{zLQ;O@_NRY&L3FAoF2vRn7l#LoiyeJzf%EpKaqeD?Q8xhLJg0fMdZ2YG% z@{^7EM4TrZ;VF#mWTQISI7viu3S&4Cy~)OHvJsnXtfnwZ6Y-hC$V@gSla1hL<1lgc zF!qv-x@0}gM)a{UmKZ@BS1F9B#HiUQN;ZCyjhtj-CWXIQzZ`x!yoWzXuqJXB^0CMtfzK1Hjyww=1h;uFhYuxh zcfoGRYc#gBl%sj8DgRc#hhpRwBC}2x9@FUQnOH>Q_-?@F2YTH!JpB@Nn1%dKcn^3F zc#W-Xh||F@Vw?e{@G5#Eaukb^zYR-?Vbze+K3CpGDVrScy7Hb!i0 zKg^@F&6G9>{sSx(yZdXfv3Mmo44ZM3zmf8_XKsn?RDX!RrTzeK4Zj?IIlM>YF>PIR zBl0@rYvH%))uVIZzkr{FpHQ9?C+`dD56EjG_fyW(wBj8+LF<2ObdUN&j%ekBR>aEQI3_DQIiqy3ixLz=f4zN<-qaz zR;|$9g5;Z&_EYr`O1Od&E{9(Z?-9KL`(MM`gZbpTjyhLU=dq0PW3==gwA3xS8p&+rYnsFD3+H=DEDPbL`u>?(j!I-U^!U!FjXfP>%T($aAr?7UaFC zc?{&~#wmtB3dR((-{)Gq>u?q#|0Z&t!JV_9eXsQ=khfmu39vJkyp7D-+Va-O@P;t^ z1~?iy&rs%XAkTWvZ^4_9>;^v#o&rBlUfwTdZpZQ_z3(wk`)Bir}gU35whZ?$e&B1$J`yOc~9M5!ifwa{7 z0&?E>IzI(J0Zs#X&+JjYLyO!L64n`aF>>aMxdV>GumU)|g?3p1oC@ms5hRSY&)j#P zMf+=zH*7Bc=J9pOd4Un9e2{)MIkA$_t zWxhD}>k>Zf?m$cHJXU_kzL~Ud9r1P-Pm3_SJ-)5DtT{eo>M_fFTIc=&#D_gr48!{4 z<7qD5$AvW!&L?iKOU40rhqGdjap;|%x8 zH1jCKSY+z3x4SIX-mKlpuzxVD)fsvwL;q(OuQVQ&VMe5}O!HkSgU4nn!J(j)vja)9 z|4cJyv(HezF-_oNaJ%APUxq&ejze-QT%LMlUyh}71GN>N{fk-(E@uC%lHY=V49lFQ zYrFp4h$&u5S-aHgk`1eaaS8 z`@GEW;4gt+04IXalee03N+{tq>}R9>333<7aU^x%m-S7%_`Bmhkoi1Zo&mkbXiW`)%rT5fW+` zNn;a5dkI<>Nh`E}fVTm4ybh$#BB!O95#U%Px54j&uUC{AuM&FCKZN`d@GkHnv>mu^ zCnWQb6u`d(?+jYYk5JBE;EY%10VIEdFCAD~a@`N#n9)AZq4 z)yh6aC8NN8$eStQR`^lMIfLYL^z)TSevQ5KlI#256uc^}U#WaX)7O4;eSI?^_)&d( z8EPkh;$v=^zUguoWlkyTxVUAJLEs#42ih!n3zEm-p9OD6as~X8;0(p|A>_{^S-@2W zQhsaXBf#&0`;d3Uaw?K%;nU#P!N-G-Q1ai9{{qR=wED-i`YW{PLGTRi?GMJK)s3O{ zZtxwE)c89ES7z5LkG!oI75{PG$eaLgKz>+lGS{K~9{4TretkOD-g8!_|BB6xnky|O zyX_)Z>62P^tME#FFXXn1{s2j?qK=(g8PRX+?J{4%<{9t_@KLawTtCJJuKp}|nc!!A z{j0N0neWgKH-THg$tq8uLOWGgo3tH4^|V|(Avf|8_@Cga5lMut9ad_ z$Z#aumRB>=!OqA7@LF&;ScK(jMeqMm!q<@ZM2>$(E&@wIJSyU#eTX`Yq7E@oa(S-* zalyLmc(|^Lb(xoxYmW*45jYI(8RYs6x`Qt(jMpzaL%F^Q7i`k{_?xx8VY}2P7e!@d zb55zmDYvsPt^HiC@9_jTfiAcXRL>mjKdPuBCHIa3Eg>@x$vPyLfEOXZT=0JF4QCTq zxgS5gU*FwH|9=hM75pan0P-Sz=JEsTGf{b@65I}!fiHnS7n`SK|Dx;ISk|j`;8($) zgAakvU~`k+ebl3z`>9V}q+EIC3FM36gWn0*KBL@Ufn+B5mdevyH}W^G*arL|{V*B4kMi4*cRA(gUunMP{Tc~nMs$tp z(yVLd694y#SzWJgkEoyD9{rf$uQHc_kF(AUpl-LZR$rp1ZzhG00NZiJ1T}d@QQy-_ zyW&WG5C1wC#c~}sV~~6UY>#9o+K%`@9Q-Rd~mKSK>$QRlPpPl5U`Gk4X${PY{t=bb!Xzi>Ti$Jf`txVX*F(bYI}mNj_} z_wgLnhIjl?;7#mLI{PAX;IsMxGM^SH0~(ED_6<2)YG z(RrM?Fh(t%UDRicemQb>WuAxs8SOT-cOprmy&EpOLH81G7iIoQc_amXk8#)a^QvrH zTGWg`+=KjCYBdPH2kmL)(XS!-1#Ou^>zd#m{BBAZN?!UZU4^H84*AcJOo1PUms8p! zNZwRW^YyP2qgmZ^{>pz^=cf0RYO|YFu5awcpFJIS{d;Efg#OK#b4u5Ik$ja|_7z<> zJXR9DUyGKtNOwohV(mTeXe=xMd|4r>pXzeIG-)@2tck5($`w=idMG!Gn2J^NG7 zEtI(qFP+VG2O#+-xC{KOA~W%n-kSs`fcJp=z&99u{fjt1a|aUcahV8Zx=233o#k8b zLU1Se1U9GPBS35a2)Gnqbt!qcmg(b%nJ==Jdz)FaQ+v<}+*^C|X+N{uw@u(sac*mDWA& z6J7(jkQz?Xx~26FGT8lZ?6tHf(s!Zl4fa9uJh>jH7@4+MBBv49l?(t;4JGXecUs{;`54>wO-gOMm|30Xz-2L{MMb|y=F7H3p z$Fg5n?!Se+UEshH)H*ZA0PbcZ12w}GF9F9EMs`_M~2O|4uc zpFsO9cp=C>3NPJ+mu|vKH$|-dBcOWeotZy?vLALjv1{#=(Z9gIlbvS`JI_0HXDH(< zzUt)ZmnreUkHB@Wn-@8Shp4YUoc%62$W(JQXqr4`g_%jdTZp4nD(d)i)9cvX>!w1IZ5fX811hk}J)VtooQp zior@Gz2M#8b_K9A^jUBNk{cL{-PCggBm0`RHz$UTt_FF!e=w8vySDJJV@Yr4Tu%Ai z!F4YolE?9uKU2;xk+fsJ$C11O|2oJMeRL-BnMl43>h5K5xGSKIwkA<}BZp`C9DPSR zIPyommR?16JMG|g@YkuW_WTvmKY-uIdtc#NE71M{w0oNf*p_?BtK4(n0naj1a>38i zS9dEmzsa~Trp>H-*^i-B-*}?=SMWTvwP=U%e0n#iPx_0r1i{~fe?+c-A6u%qMDjbM z|4)jp25)FCXQkT9bE3|~eU#IV5?)1nKe!2O)Tb5a2YP2WHD;*(TMwqI$uXw;{`1M{ ze&{{F-R|4F@9MrsnelTk%Dvc_+zz=Ng!jnpVIuMTc)mv7FzzMaxkT=8t=6|Xa>2hL zu{un%B-MxK_a>+NoDby}%Ko1Gz4jX};F~V6X?UOA*1vnrf2KYkX7`WkXu9u^wEKeJ zdoMU2cwf@8-}K|XCgZena-Bk_%&BtvIM+JYJ7b*5 z&P->%v%=ZnY<9LeyPf^c5$B|H&UM{3ZhN=L?dsOJweBEyn0u=`-mP<|yR+T-?h<#U zTkmdkUv_u6d)$NWG53ty>_xqcy^daq*Uh`q8{iG`MtEbqiLxiT*PG)l^p<(6z4hJ; z-d1myx6eE5o$${3#&7M%{DfcbSNnbaf&Nf`lt0d&>`(J&`Sbk6{tADs|D508Z}(sK z5BNv@(|%J#R-;Hfl8gkAUXiOKgCoNuqaza{QzA1W4@MS5mPS@Z)$eLubm;RZ!j&mH<&G~TJ$r6>B0sE zGlE&cNVHQ_Z+y)cJQ&Oi76wa#<-scB*>kWqSRZT@yN2OEM-K|`=L*dY?m!R}yha3DAw95ZfeS87jce{ew9)>Knqg4cz;ka{__E!ZV& zed=iHM6gxZ>QsGdL#jd8y}`y{bFf8f+K^h3TAo@f>;<{%nqZx3Q_pFBVIxut_3ENs zms+9ug{_s`(gtB+&4fKCxnB;p3EL8E*Rq9aEp1-aN!h|SqnBDqKh4or2wM;=4t8pt z>7y;=ofFKL7PsWx7VH!z`GP%xtg-L5JU9{@5B3EIg&hq}i2jVQlR;z9RB41YS89IM zW-9&4)|D3( zgK=82lsh~aMSHgdgM*>Ay>jJ&;dOfjeZ#y#P#u<>49dgn#)CxIqP9UySl7xb8Ku@? z-h+YBys6{T(`Pkr>Re^l)Crjtjj5BVrqp5aD>rDBdOfvI*u_En)b^Bmc5V<)HKewx z*9AqDe(D9uYl38DG__usD_3n!tv;_^hPFI7mRhJD8zh2*sX4-mg0j@&)V;!zL1AiM z>Mp#!Bv_N0DC|(sF<71&BkVwGd$1@qLfF1kLohcrMA#nD?oSP1rXPRYTXLr}@D^~ok|3C9#`J;`=zdiqUbJ3;E zmu5}d_zUs3Om6(o9m>qLy3=y~cXwAZVt+pkF;jw?pigkMtgb_XVZlfpd)DD`vJ%@g zHB9f9&5$%p(wvaL|M&bb>9HtGOC_xc)9NtQOWJV3dDDlahWDkG`nA++Ygmt#b4%JG zX?J+udqFx7ro&-67A7t4q@+ekO~E+vqj8l{No_*8TuWBFakBQjdrrJBmAp5d@4pNC zHLSbL9h<7c)GJI{PT#P9>TO#p2ZU{EDXT{3q;capaT)FSW$|*|51T$0{!44@j@{hP z=YBzU&R@#?iup+HJ-IVX+uTjLFPhxk*K&Vl+UI$B5z`?rKd-$h%qz(&HHo|)c{Qde z@4CE!CYg70-bhoDH!bfTQdbYqug1P=2FAV-`-b^=?4j60W>9QpY^C``?CIFkW^nBJ*z@L-u@_@6njx{D#a=d_ ziv1$C&D;>%8~ZPFW9(S$n7Ju-BKBu9Ja#H}%8bY_$S*KA=XcI8G9&Yo`AIV>zjuCb zb4&iv{2R@!`FG@h(TvWo%m1?ZeE!|}cbhx%r{{moOvt}Kf0mh;|K0pWW>S8Ae!ZD| z>7$oEYQA*oW0yW=>hxc$Gx|lk#+8}YGRMjf|ATbQ^fxnQ*3L5v%@U(eC2P%k^Mcu8 zcA7orpgCfWo73j3X?9%M8@6>~PDiIm_J@H}?Of^9${umBGt?R3-0F;VCdgj#E@!&z z7aw%yISZX7&T?m!v({PfY?Qs@7H7M&%h@CQ$3xCh=Y(^{Ip<__9jF*rA?sSjXmDah z-FeB73b|)i46Km#zG7I#$WY=}j1*h7@G8bvOsW_ol7XU`C>CDD@XJant`~_|TvkXa z@d{b#D{?F3PFK;UBGB^6lH>#vu?sVk`q&HM@QgCLMUD5!Oa>vaWf9ZsIFXB_*u+Lw>S zzKz9Dy^>jJ9E^x zE4i%UX>*aR;oD5R_|EuAqhBS9+$s|>ZJg2iSJLI{C2jn-CFh^A+bn5|r0tUAZd|^H zbfJwGCVm$kHh%g34@ieTME|cyM~z>$$nv6N=jE+Tt|>RQ(z6p~b}lwDuBBC_RbA#t znlEV)zm|%$V`;}Ob0sb4vKYRsi|kvwEG+f)=rUH)1eoley38m!sYjP_T_$p_>mnmx zvae)cmr0U(Nt(hh**%nODcRCxtfVWuOn^`BGFVC&T~e<{m)4R7!rF`U`jW+ZbZOJ2 zFXsVW68Mr6cf^Rf5TS<43yH=wFI>XG3#+1$Yz~p|2{)3YDPua7=tJ$DvK9X@`5&PBSEPufXv^=!y7ThZroE{#!%Ur-FP^f)9CMLPn62DlKv{)pFAWoIjmI9=SnkWvL?%~Eu|-tTO_X>rDrt1 zoHftU^LbZE-c^EYOV^ifl(Sw>_WyFlU8UQT50>sqJ}5Y^bYbZdIWI32OVMr=yNz12 z8hk`VD)OHwQ}C5zeFpwC|#dyE5F+c z%5^y}Q53CSe|hog(pAN$1*OiMrz?tgdg7-G#akD}e{6#IPsC@3;Imue{Ee|Q$(fk^!t7cgQFhM&VOp<-~UyC$c%Rja6fmxyhL1z<*nE|0%m6lEf2| zBPESCUUD3%Meo1QK2j1hPIBT0q`D8$|0~i|6P2?jr{lEq^2^L1Gv3TLE6vNY-)olr z-IcPRyG!t(-o!foxAy93>E?ksnO+u$B>o4mN!%Ny=Z@fLXNyq(^0zm;F+Un~7K zJ2^MGATeK$Q&pf9N~48tx2@Ec{`nJIg-7SeUsy1gF2lPtz5O! z{+2^a5^H74I_a@A#C~iucWLIU$Hk~$$c1m(ur{yh2^7`cPNK|HNam7P+4xRlMJr`>y0+ygo>e?Yw8|EB(taKwdCOW3$s12z z59`{gOtjL%POVxFwH2+f;*p(NS#9C*mZNxS@qy$3SbgDf(RNLm!kvXXlU0hvt+7^C zSh!QPCB=se*A=cyc2z7oA=gd7GKK4mTYNH^TezTbK{Bpbv@4mAvV;{cDwHR?;$y{) zg;NTrB%_K&>yt*x5>`C5aEj(Fo>MqnEQae*JimC6)JIs+s>0!-Jy1Ncu$S2P(xbSp zcxv%{WknAb_7d%m;@ySu;=P4&J&K1(ZyiupG@(#-(#2bgHxx7#?lisRB)i>DC$^LBwA%bf$aW^R~Oe8G_)LQTMR2|ThO4|f)(!`Mf0RD>y>pr zT_8K};zb3s-aSOOLhO~*7tBIC?%ktkXwit`rOG-#S0K+i#j^?qzIzl^7hPFAOj+l} z1+qF7k1QyE_b7@Lbu1pOtn;*ja?uVcX#MU{oGdOc?gpzVXl>k%CoViX@9TW9xCYj@ zqpZjscU^dNexdWrMeAXSjix$F6$MvFJc;S)Q-MP64S>kZVh1^GV z7id`9Uz6tt)1j3+EWGa6YL;@4wI9 zDO~gcY3YaP{}oC0gmTv8#8$p5FIvX$D`ZDFSDxq_%sz9*X(LbVS39F*WuNb?k*Dzk z&RO?jx2t=tJKCM*E_CbNZSEmi-D6%iZ;&_Eo8c|?)_Xg=BVNXj`_=vsf4o1_U+O>S z@A8jD+(==hS7c~pVq|t?d1O=M^@w;-;!xsf;zWF2d|u*A;+&rCA(|tJGcB$n4f>f^y6QNVLbe80~C{`Avid~opoy?@c(nyi7EJ$O!FcFe{((%$jk-aQP zeY-G`JxXzxWQ(*#+EQ;6{V^sBC}o%=S;Q0Zq;4nLlGbuW~1N^(x!S{5YQ zU6?wO{gQ*~T3ta>@&iXHx$0zBkZk&aqm<>shOQt<`GFIp@R}q^cuf{0$v<$EQt~56 z+<)LGWz&x!G5>+1a;(Mo#E*q3!W78>aU=ee1(aeaekd^&h6}?bmf{xtDGO+CTq~{@ zy32yNp$ikDlZf~^%EMe1#BaMWp*c!?329kwf_7ODH*{fwb|edriJuFe z%7Qqh3lls=DLchO1r@R&4)4MQ6(}WBd|pr}3*w3{On_v+);#ek!3J3n7j|KS4Jaj2 zvsExpFi(6C#S)Ck0!s1Kye9}21dDg0xCvvjfNGr}b`!V=T*PxwOu?8epp|wA1p+Nffc|No6MX-N-f7qL<$uxQ@W1fCXzs;O7Enryn8$xC{=k3C zf2_F@Ls>v6^_q?Ri{b|UMgB$21Po;XrBrK{@$+Rt)1?dJ=cAM|v6R0?7BuH|VSJ?f z#ESf+t{_(Xfg_#S#-H33G(Y^nQAz`USXa=j{ecrC-$=8XZzKzv_qs5?5lT_}5l~CN z@qUm(Hk%qG#vlpA~&OKgV~Y1$M*3|HQJQQH<~QoYd_z z`FF9at)AWRzoOmUWA}Dv{%!3xrI*r~C~Tm&(A(*~^g#qm=o3IIqc74|5v)S6hJHvt zrC-r4D14yX5Qd@#sUfeSq9M@GM4$2++9;4fBO#!3718_qFQKXgm+DDTgaRd?goF|$ zqBMyfl!VeDdQ!TS9-&V4q52RsWkQ(|8k7ZPMMxO$j z8cDemeJM|B6w#0Jrh*9*_+51nEl(>EPIM1ig&0Ar(LD)Qnop|}BWVp_Dh3_FnTEML`2ZTX=fsecBRJ= zQ~%-nS^QU}EcE{vthj@OAwkGD|2a_stv?0NKRrJ~ks}JuB6pED`t(O}vM5wEMKnz` zOEgcEhT=T5=UORRC)y;+MR2z$AL1d=G0_>(dGv`x1&Wnur&lXNr#&=AYVg;4e2P!7 zD0NDmASp4WMX)J!#6}~oPw5jp%A7JMk0n^r8pQ0|;%}ksd|u4~!$0>jcR4J_L)+ zVdKAsS0)vS1q2~CtTSq(=+^o9XGO2h&#~QT6T9KTe{y+UF%retZqEtbKIi-{cD38B z8~#`HLHF3b50?LJ?Vcw%BRG#jg`iS!8--dyy`TZnYEf(!v7$^)!Fj^QdOcEvwDun66 zrNT_~yg|4{xCNDn-`+0Vi|SB`C=OB8E@B^Zb7hXlYRl+L#D>{O$D7QADwV)owR#ff)#9@tg`0{wKie&7cE31c4 zPDoZ`iERWD+ZZIaDM)MvB=!)H*v=ra-9TcygT(d(iR}#%+Yco6IFQ)mL1G7h#100D z9SRaV93*xmNbD&fv7KRYldH_>g*v=&#Uo3ko&V2da%vqA1T-;S2bhd~JRo6pX17zBzS*Z;R+83WKN` zG`79|1no17az?WN>mW7IK@{j9KIkAJ=pYg3AR2U#2IwG7&_P3ikS^#TJ~Nknf)xbVr}3~gQ9HJ2CklAy5Ir5Ia(Iwh&c)WY?O>(f2lH@Dv9E3P7UCg; z;qHyzyf@gBFVL$nKe-gs<<9X4@C7f${@=OI*k>+2>9McNO-KCTZ-o`fSwnRCSmANG z?g&oC{OmHhlrAqhhzDDhBx0PS#MQv>;@l8@A;D6djqf{Atiz@Ad@)7Nr{gB(!M0(X z2OVm-{un3wbsWYw8DPH*yjG$PK?6=6qMX4z>?YoD?CZS46qm)p_F5UTcfa)jh<7y& z&?hC}4MZOI20I;F3bDh%UZ@IuB}C)4Bl;PjpTTv;-a}NSC=&`6 zv%j*}gH zhCJ{!hTbB9;)N-=Z&^Fp+CbOGeT!{7c?BJ%fX@MZF63MZIX9z`lE=0#a#kJLfcF9% zwUqY^+t~9mah?cY2RLd4r;PIe=hj&k33Y42{@k$-O13xWD;`1ICoC265yG3WwK=;I z&sCy|JPYH3a^Mugog7;M*TeIlqlfJ?IW^dxoYM$*jnn|e1zR0+`?fzp(3X82#sz5& z&TdX4!e2wJO1Ya6zPcj|YLyN>fa<_2#umA}cx=hTX~WjMyk*$tmeYpk2`3EOSIfZNB33r^zo{C47qlD?4wfN>9&I7;;ap_zQ zjHA)FKyVDU?&c(8n@LVz;7JDiYJco~fSnFGFU9kXEe6~T_aV81lZ@aus81j+k@N?v zPHk*Q$7;p>hA8-^B0EeW`(ZmSaw!kn?KjKv#Jxw}!nWTCVtfbqOtFJJr$C;MzzTFK z@L$0e(QI#=8`}dsFL;A*lq1+@0s9ExcGwD(eZ39)p@_g9`8oCQ?r_|D#0TgZE8Js5 zJ>pm0*}m_75H>xWdc1@hQm!5d|5sKQ)Li%QXzF2lywOx z{BF05n00Ky5Z@aiyR8S+3M`p{4&LHe2Jn^}@VjBJA1D>qkPq~f&QzR(FWgcS4*4YE z90>3oCcA|QQ38Qth_wc$$nFbaUzf>$TrN-MJFHBm1u#^c4O&Ciu6C$f9kwFo%Dj@P z;BsZR-LSY|T`cQo4!-|Gb`KM3DaI3^MDVD^gLcWu0}j5`I8b8eeL|OjAN)_TD)y#r{?*JFu4-f7~M0n+~+HxV3C2 z3<>NNXahM9__4AAvZ}VQXi01Lh&X8!0ys^&*R#jBVq2 zL-2kN@!)nX#rY#TT5CK*!V7ZP0jYkFdJ0NJJ1E`^tTlMc@jT(}Vx#`ymB4K=0yHL= zp9Fq?Tq5onIR&hJoeWj1*Hf|Tvp?Zk_Jn%Q;9M~^GUl(Cb zhd8kholMNh{t3@sPB^X`$_=e7PDLkAPoN{5qmMmza6IsOLHHPqhn~<6kjl9Xb@s|F&oAH;+G zj5K$S>!Yia+&or?khIl;XJ_<)@rf`^aGxsLQLTX z;vBg9G0t&<9-avAeua0PV8p*7{eya&gZ(?$Lp@J}%!$Y2OWp?lWL!E~4EG?u0Uk%( z^K5%OI;d{g=SVHL1h)m3g7U#P7_A2%OsDZ0CwJfxA+Nxix()Bj0sSR-UXx>E4=g+J zxUl8%sfry9eWHWU2&k_zaX-LJAo1v+-BeF#uMT?40DAQe?p3xA?n6#b=*b-1lVm$? z7uuWQ79E7WN)Kp7Cawc&MF~#D^lah2@A(c6hgmR#_^*EdZ|pe~ z84mCoX$tfTz?1Q5kz9jeCnv_QvDzTFY)EwnN(E3FfX5wjbH@~%8-i;90tI{HLY!z{ z+OdTdj&&&Z8HDKABYZ zP#}NO9`K#m8zxRgP?nDt;D-R81<(`VFvwFI_Y$mh0-tUWy%NR_a>Mfny*n6E(}5BV zILsEjW)XyO!7?A=uxG&Y7QvMma(DpMfCqYjgzq0@^}#C+L0?=7>lKtGYlS1gg8K;DCL)d5-p^oCxAnF+f!0?Sy!5buuA*Z~D@UnB4?3#H%)v@jJr{^wo6mA&_)i2QA98j@o_{n5k@4SI0y$ur(0$mK>_Oq$8$BcRku8~%GcLr z6z5ToUvksvP$rF2&ZM#T=dwu_N%FBL)q{A9mf_NZoFw zQF59P;+%cv43#lt$XuKx4w+q!3>lhe&J_((N+qHYWlWPOgb*c_%B+w=A$)6}v%4>6 zotyo=zu*0Rzx%!S-uK=1|Lpy&wby>0wVw4~`<&g{m76XrmteNkI9w?tuRh$y|H-!v z`rip2IJS;-|X5HMp|Izh5)k&3MDHFu1&tQukysVMWGwFys?{fdsEu>4Ul6flWP6r+hWaaLe?M?iqS~HDg2imk$$@ zJrvE-ZOzYlTfdQ?V=OE7#s6Nit7A2@SLWowrYCx~QmuND@wJVt=rRfA#f`Zadc1TVV&}^j+;=w}!{m$M&VTW%gW8Ojge) zC-q6*_WMjL_Dx8uj;7CDE_(fvn1k%ZXUi-#_GBAhe6X>3%1!6`#DZid$+qy|lFky< zU+FTJC-gs9biBo5yM~hb1*g8&q>L|=e2GWNX?Ny+m66SmHf8&hROOFNCLjN!L@Z1} zF>fWZ#QIFY@X(U3@+%}(z3swT^D2X0K9kzezGjuO9LH|`gCj$A`)7tOowoGMi7N+! zyP69x1s66J#i(9Ts4vLmD3NUoc9s4zYxeBn_+2UAg2Ft1$$QjO)htCm#M+eF7?eS% z@j3bXLUkMYfj9G;y^NfWpRE0OYIdT_PKAQ=JC&RV+V=SV_At0mCp9kfrP+7d_BYiY z?ROftOpFm#a6VL#%ye-#kJ!5LWc-=!43D)c(r#@D)FCTV%g2l^i~OXp#LX7xEsM^X zUfr3I-Lu*2+dN;rRli`~mClTfcf9kY zQ?EhCp`pubP`9q^D0RTHaL~YGYuU1aKkl#UchUT9f&SO0u5yVtZhlUC+3h|QQ(WBP z;va1ia0=<@vVQs|b=RE$#3k^LqFiEc*Y$qpz$&xGIxUm+Ot&}4h5i7KoOiQ6JBB?P znsLkfSJ4jVBJl*>-?~`~-(SC26QxyOxP;WJAyFW*_t~;l>--!BxA;xmWo}?>UTI(W zGNT|ycDfgBp)h&6M)wT0;7(Px-GlD%>o&RKA6_WP{Wf(fWyi*M8<(t`YW-5xPC~69 zUvtHi0>eW$tYyQ@k&M)>AODO%=zBGVC#@L@c>kqt>KPZ`a`n)ToNJ^r^eW>^9h|{% zVNuNweqx!uyLz7)x!k$Y95S$bf<{iWQ>Ukj^g8qxk=_Nt6uh}Q&oyHT{;fuA2*X%^lms;)pOOni~Y?jxTtXAiC|S`?V8SG zTSWhOlu}(2N4)eoGA8Zny1;^X(widvngXjhTRY^&;WtNZ(gU^boHKcKA^gPmtA~d5 zhT`>)co%+p;v%=N_Q0p;Ndb9Z?UZs0b-Zeam;w4_Gk*!b>C&oebNuC|sO4KeubJt1 z#Iv$|e|D*4S=2XInLj0_lXPxp_l4y>xaGU9!CEWyVtQ!Qj2lTki(6~EA}s>-EUxN2 z{ivywx_@K7aA?^!FZax8q5+(6#ULs3lw*I!doZ>Sv5Ag~!FuYeY^{avU$!e=ZsaHt zp1oB4!twKSTNu@Z50T1uOXBs)?FTdC6uzkJm^9c}N!E4g9p9sv@rpJ1mHoGjqAuOM z`SOwLIcyDLp65A_{kGGF%GBR~ZSXN(dXi1}Egb!!;1=YHXUJmI$T;jSvT=w~} zfyl)>rp22#D~BmP>Azom{MUnDlS>x2-3 zWrks?venm<&xa*@i>oyJa^nI9pY~E5E;)pTdh}H4l}B5c>6sj{3X&~z)!A1VTrQow zNAfq*vMpDXGPmeee*a=Z&e&x4>p;E?%a7`^^^yLe@0!gbdri|{F(v%kvz+fwObiV7 zj<};twQ^{A<#^uboZXf8wuUbrPL&P2xHh&enlLc9tNz_kzQmxF{}6b)Tg#2<7ID`P zmu7e-4-s=X;!2X4ol)&k1Dik3qVAQS5mC^s?XrL(HY+ zK)2U|ulu*Z*rPY4UD+w(Prda+I%=s)DmBxIJH7O0Ot0)cc<6w7*0z{yE~TdGrjT`N@_QSJ#gA&(NpLvt$t1LB;WKN~rvq`?Y|K7X$ zv)$?Al}bL=$ugVm5ZhD5mnR#SMh(6TIhoNUdNlGw$Bk~68n^wfe!{23R-Rmw{zRws z{+?tb5f7(jjOL)797l=k?LHEPKJ_mqmvriiPg~gU>o4C#&`G&TZ2#2qs{eFKZ|KeU zLJ|defn~wo)eUy6F1Pyf!^*<}cRJ+RlNu$Wd$(Awj=K`$ z-o9J0>vLPfYsW2)_HA+w!GW7>`+L40aPLX&&Z?d`UNUguT-}5-igLy?-NY}~#jcrq zVR58P?ZLMCb1mKu`9p#Jo~P`+DkX<(;ygF&oxkaGm-xBuut;-g;6#($$Z|%Ok**_2A*F2Sue1Df||ilH-s5UO|i{!UWuU%YHc~Rosp9dcdoh`^txyIPHL)h2!nVh?U+}%D}W%YBB`Yg3P!KYOengc{bobnLgN2b|^IT8z7w1516^^qq4Eja!x2D0-x!|AcJS zV8NlX#l`Wi#r7_8^IhYg>kkAd*WdGRXwf+N`EvA;_iH_j48!(iJo4PS#VYL9w}R9e zlcUTfWyt}S&w?5!C=6dY{r!lMeT1C(PG3zE)w`1YiNYofqI9+E#g0Mr^07@p3uIGKIEO`KEmN0lAuK!X@m7aSOI> zQ;RlR(|3Dv`gJ9L$IAD))%2=6O_HUrM09RQT(OmZ>s0qg?z}nH%Ke4)Q-!Nf1#2A3OqH7mbb9$qbSQ`1<+C!grx;dz?k>i)cI?Fysb#z_NT69`^iR!bdA z7HCLV3=By|-4x$^f122eKNqH?hKnt~_OATM{m`JCYVBpiIp94E%7ifGwN9=<#ix9z zt15q`-WaHOrYNg_Tj_mrnoInP?QO+fTLzAGIa8TQl5-~4s$47HeT-|5jlaPd*3W#IcruV3r@11j8ZZn4O>~+{;w|@u~$#+AAj>*SmLCR z^!}P1uGP<*=UivT$L2IQe=4}J#i(r>D`S#u()05iBl`wI=a>D1lRn(AaD5W_bogXP zxI?(Hrh??$prvhkjo}XCzZUPykIS#J(YTXRY!q-V`#beSQP_o2)#w$vs2HRW@#Q=O83-s_!BnwJ%= z7M>Mxj}Ph>ySr+(&g|*agPabnq+7CY7nR#RtI0kevWl7fHZaETl+p0M9&wvBD;x$y zzer9@s-tX=Q18!ukbiMMGy1xykUq0n!`@8kPOeYi*DuDiEB4C|zg^$0I({eysrWXu zXIF!i&YY>@+azXgV9Zn<>bllb_nYJED$Cmkl^jmCaxCxlT-$l8d0v`mwvKFM7ed{C zcca*e4`B*OUQbZB*zcP&wpU%u?`O@PNSr&qsp-N;32&nvZ;s5XuhFfUK3H~4d3fpY z1PL$Eq}wz}>R~O`qsvJ{Z?vvB-_*6822{X&p#*wDqu|2j_k~!=$iXE#JU1BO*34?Gje? zEo&F;qS=`B+SJvYxk7iEwbake^ySkuIopzg7||xP64O#e(Yae46ZjUgl6xCA z47dg=8{AIpPg(xQIo4qD)8f2I5+&sUkIvs!AX~pXR4o&*-u{xOPL*EA_sGQCSt~#5 zTyE{RymVi~Xpp7qw^A+tSlOFT9BZeV1n<(p#pz7r=ybo?i9w$>?OtcpxYt{HqUiLr zR3+m{(zz$BJaWvkn5;UF`wcJmot4?M`fw11%Xj6VITrNJ}D zPpvUGa(5W_#{8kP)TX|7k*<_?!{;4oN2X1Vo!+!_pUjClJ8vgj+*&K6#|Zisy{T-` z(FZ#s^gsVrDs^g~xjkDk`)fy~MbB;BNnUq5iV~coMUaNV30bQSPwJZGOZQPH@0?mX zVWODp)m-q40=|@nd2{lb_FE5%rYSe*zA{jKRqCm%)WNEj3l5WW6gBcQnH3-};_`;- z<8$#@+qSCS_S&W=t%LdOfaF0d&6X>-%leF0_q05|*8iLwP7$@LaXzaX`Z1GrO_ce? z_x`DLcJc|sE$U2>nKoCQw2i*|HLvKQJdgZhcVJuj+vJ_e z9cMW-w=TQ8tu{)mkWVdrWIyCQbyg71qxZwFF!>O~NTv;N2P zw;4VketqaeXz0E*fii`Q7UNWib{iE>XkwTS9CXZW&e8Ox()GX8= zHXO8Y_B-z%?eU@O&h!WGgV&`W+^{{vETW_Uxs#=_GGyOm*=s&GAAWLUzT3`pn0;q^ z%scgYyIa;xIlSDixksyfAWo*%yZ2`1fo~Ta!qNtY_2`}z=4zc!vNGnr@LMnWhe~g$ zm3U8z#~)=;q%Av}f9rLh;he0{YBjS@xUaCe?fNgdaqZxXg{j58p_@7r6t@I>dPKCI zx?bvi%w%P4zscNJYZlMDz0?0Kt17~&S~+^%(rwW%>mxTWjP=bql-S-H{Og`tK~P8^VQwY=a_q7W%b6ZE8e}#J=bZPwXlhjoolQt{^f0; zQczLD^8V^fxB8~0{2@QiP^H)2GMb%mMdh1sN*9YyUAE1gF7~NaJ-pg_;;sB-Gsz={ zFRhBLyh9@q$A_o$rY7p@&~x0(H&J4)-X~PpyU)0llJdLE>n7G@*H@cmjt(}u)Tf?X zcc_MI2M+8pt*bGZC_nBRkEmVFrk%z;O1ZhJ+AhtJO*h%oN&`gN)BoFS!P zrz=8hj@QH-bak=bA2erR@W{1|u0gKf-x)V0$#jrA1HwLJkODeS)CC+3X+GpKj{c>K z6)cwAy;UA;BP%dxav!SVbyb?@*b2~YiG zX5~dA>qJg-@BXqXhZv)Q#f?FVPxbfDSy8d7v~Xi`wOG9Jnyv@(?}YmIce6?(=dcD# zc4_M^V8T^}@2c3kD~mZ=vzpW9~c_cCI1O%-dDUcdcnxMt>*eMg8M zYo?q;=Khj%r=)QI`nyuQ#*I6?{naTUwyUit$AfL{g8t>U%~6O%BM=GbABu`X^2WaI zY=XRon=40+?P=rT;LdUL5aRCZS-XHw)~TqfsjJJVT01*z^Kby4I9uC$63B>#ZaxHyRa7FGTMmJQP>5*pEZ)Z& z4$f?ZK%#?dH55`-{_Ely*u`5Q2-*(+Z~vvxnSa%QOr-wxH-D|jOcLv_D?kr}Z=aC7 zk=Hg3_ih?{c(Kv@DkRUlhZ>-rRjfVP=v{{IsJg3-o2`SZJwe{g!F8Rhr^Al`uO0tG z3j&uoh9C@_D@S#^wFj368?3P%5{W7VFu<+#B#_W%9@XyXg^sSZx(`Rwh-1wG^;FR% z$m_XzxL7+2$=g^HNF#0-g0=;&6IIuZK9MxyM8F0P+XE2Y8I-5S23HJ9-N1IW2Rx(z zk^+KYBJnwU>$Hx}ucY4}bqWuNHN6nJ5?RAQ9GUz&L&ZnlqusME(Gt(CSZ zZ`0@#4wl>QX*a5Ub^hKJmxAK-1!tEK78a*`d^w4oGBF}XLNa82jr*>~v?Eb<8s?q0 zY;*C=t+`Y;@WSeDackdl8hKM!w#(M^)8qUfsIfN4lYfhtoVhG={i%bge^^dyl(G<+ZLv`*FMT3l>*k!arHP+q)@N7ik)Dg(zUm{lWv7~8$Uzi zr#*C+XlGX+Te8sNof+85W+!Cs1>1ep*!aqxURkSiSNCZ5#f3hWUZmMGY3`>=1-Qq9 z6=Ps+4+x;kwso-Pb|Wass7$IHLSRrxa!dqtB8F^FH!lwxwkHAYC%M|;{y`#;P&_WV z<^SR^_aIFpI)Q`|9f(BJh(X|Tmv^9nhntNNn?taWH&D|c$Q!eLfE2Y{Ks8jbttz(F zVxer5R|R4PeW)h^L3xYh#Gr`gALnI zQ-up46a178R0Wj!Zd4Cd+AJ>D85Y&+)#LuNe;ggQ8PTtzzLppbV z-_K0nQ+uwarbI4caliFO*>4-W2#Y<4N}E#hhdU`!QcHK3#hs$qhAVD(<6Eb-l{2xv zYdclp{9Z9udhPUSJCft*-g$)+u6$W=``HO<@2A70-gY-uUXWR9D~Hdv@|>A-Z?x)qOqb)kEC%ZrL^YHpeAq zx07Vdui1?|Puw`KvUq_KdxrP&*{#S%UZrGtauGdV_J;C^Liyoqj9kxTB6mA`#KJGcM?t> zJzTdodq-V+ZIamM3&USdeCYJnY~?s4h<6M*E#MgKTed*-^Hq+`z5vA1K<4!#>v_M~ z+Zwe_ntG`v;VpP~|3B`haNrXlg$@uXWe8&-tNw{BJlDR}YA z-HKZ~Y|Bm7&1l=KFze)#J9^J+!*BZ){36{bzh-Ho`=TmQnX)PaSUw}!z~kP(NIqOH z{}b{7gX-VNhcR-j`>A{=Kb21ukdM5SQg_}(sc$oZdi+v=dhQQ*-t0DT>uB4jVxHQn zyx~m%vWoMS7|HPl3#~6&MeGhU{nL+9d)+UKAm*QHME5-0j@%#0b=e}f^*Jr=j!U-8 z1T~ul{kpXmHl*)Dsu~{tzD)GDr$LWzR~hYVC)7==t(Q8dk(ll)<`QztKP1oL$tCNw z#RYCp>u#19p7hxsb$9j>$=RRIwoLKZEFLH~xj2V;ZxcHuht-)*d>O=2Rt_D`-LR!Y z%5Eu3qNv~xQbc8N>ive#+Bc+)|0L&ZlS&qz^YpU$v^kuZv$jHqV=l^xXkRIkIbj^* ze{#bKGwBa1>V*;V-f>m2@13PDaE^9pshGIxKl94YaJH0=t2nV*5=no5;+m6JZ;iY9 zbJ2J)x1D)CQ`G9tL@l%S zQtfL+8HCn^bK8;}RKPwMbmnPiJ4#AsNxLmrZ`QutOuFBo!bIVUW#xh6NiRuiHZuOP zi92iyP4X8%Gf|jTeeOYCK2VmVc3GxD5U$ zM1%aTXh;Y;3jJuYpR0xr4LT2rV9*I3+RyAj{n~QfwThX67c$>!=I`}+vA3geBJ2Bb zDQeixwM3|_)UAvwtc|Nw@gBc(=WG8RepBu!SY10w^!0t6n;qHFnRox)wCLIbg}a+P z^d>4koF%r-juZU0F~-H!dutVKvT7~o(Ub$FP3sMe*`Psj_usgTuS zopmzWn%U9#H8(sxE9zeN;*hj-=JCbywUdrDk$35z-hOyN3reYM9A4vFnOB>erT zO|FmSHTK}4FJBXv`p(PKHydp4*xP>OTf?D1?H3}_g(vqelzyqQf|F&Yy22u!5UD~n zb`uUhzH)Fq+bG_Axlw%JoUzD}Jp>IM=XVT}(UO z@sXvY&_?j_l{bAtRy7G?k#wt4M`?>&%dB-*E_8mqr9p>iX0TwmE6hB$J^sx&xiuA; zuyB4%(Ec+!{TB&`$KroNIbd@9H^U8yI?~_%TsaIr<&>ayEg#sm8J^A)=?ZCSQLNu* zRL>9*4pdV-uz&GQN#V`khtEv{$|-Hzw{}X+^1H5E-t1h-nU|9Byu?0k|J$4|`HoY= zPd$H~7}YwYyl7GB+boycU!qnt8{bovEuU$tVK!yU;+IW3CY!o=5^w5yAKBHSnD^-g zO=_>wg=t0 zC0=gRVA@<>^e)|YsfC2JT*^Y}7b<-~C07Kf&gy!;@$!}uIX$lwZ=cPs$(G(fsU$peuQHxRKWThUR z@tcEZ$eAMAn)&KxbM&9m)~dvG9XMG;Tc;u|US+1v7G1L2NVoFVp!Sr9a&1=YQg8LX zRX6Pi-$}cEuHVpTM`88Ll~>NB>!erft>eTdPqTGuU#=;Lp;pn<*~NuCk|JHz|tA%JN|V>jYs2u zLOPVcmkwiOZ}U^>P^o;<(M6L4As|U0&Px(3k6POrBR)5OkGRa@hpIDN_2)Ww4J)uj zL}o^{d|aZlo;E=A{ZjhzL5om9eYxWf<;e=!mTq+7i`?ipuck}RK3!`6$tx=mSnNozt*Tz2-F-7YNMT5P8Cbca_kQu9lZarjcz%9MBG+S8s`yrHGk6c?qm z?(E9VxR$to{50{H-1x-cYd$Qq6!VgC%GMXsr%{FQI9I@9XnHnm`Lp6MPuFW8qzqwBPlq*1*IM zoo<>Evj_FvhF1w`c{%y-ot$nd^-NbfI(+4>3f(2qYWaOTj%I5;w4li~8MWHYJZ9_s zIIco>*~jpAd(2y#X6|_RNsV^Gb*Z%oYtBdT?u0)M_J>&}#Outd(3}pYI!^7!RJ95d zKYT=|I?F(UpyS$O>ES70Dq|F`ov;N=VLr!P{PpbD~0CuZ(> z=bm!=sj(y~vASiVVVM zs~&M?tof{RJ=i=Evw$E_MS6o{I`7vvrlhHVi+ub zd(4(^UeguiIib()>rtC5i&bVhjR|F+zsOY9i62Fl%n$PGc3bf&;mfRF&WIdFwG}?W zhGhIKSVha-H}<%6MA`AHpS9Vnc&W(G`3CVhm$<1m@8M6&W2C*QZ5@O+sefEOtL-iP zPOTusL%KTl^N%Ud$K)SVo^6x7@;eZ*(g?%WGp~ccmyesbu{GiKAMvf;UL_p|j>=o@ zxtzGeeuZhH&YzqrkZGgDfc?)gSA@a0%}xBE2?Gp3X2`SY0^~C?=lZW3fp}E@C*(u> zd-+f)xTih*=51824NVsOm23MeTkuz|P4ah@#}dA&10CU77qa%0$8XXrv)>w3T(#rZ zy{|vCf-goZh7^M2yBGVYk}N4?!d(B)Aq3=%TFTCZ#DUo_s;e$1CN@nQUv3`a$}*EW zy6OUjx)Qm$3Ss-g5FSZ&EolXJCf>k-r++@K+ny7S( z3bRnePW4u{fmCEs=hb+j#&BEdyK%?mjAbG}*BHbP(7MiU7$4D*lNY{Ex-NQswlPS+ z^%-XyHm@%T@t0;Lrs;R1dl{hnF2qvlD=IZxKHz`RFmWgF*pG?@3yHCQ?PIm|q`9?W}mW>!iI(9X#D z@4rtwTps@u+M)lwb{Hd*EI)T|U6H-swU}xlWRmSP#y8{C9)DkQf)qcu>0)+D+ zTV;Xscy_#2Sd0r;I&kakK$Txh!;s9gx@L{$X?^FLhE`3|0>A1YGpiTKC(2L}&0j~YRXiB-rDUO( z(E*TcdlFYsvSd-=i$C>aqtsqV=1sg&QL+^1=b*FnYYJH9kv3oVTJim?9;Gbfji;n9 zhYB$cYd?P}w*UAZv*$HpH@f;P{^VSLy(!FOXzp^BQylFCcQvO$RjZu0%5%bsx5^_D zkqcIN<{N2oS9wqYC3CKeZQ_`uO!fk^A02Hl__S*&E82`d@i_?0e$c^Z_o-*z0t7@J z(UboB1jHrtKOrE--wKF4YH{^v0wU3vqXZOtOjmdhy3q6MfcTqBJIuYEtL8l1E3UQM z;O5gMt9{n%PrNlOzBym@oM_1Id5fETXNqkU*=W@%8lS3G^~`6gp<#*5hBK;53TH3K z+kVpb$XC`=_TIP)MM8&mOtZU6`6zWj>Ds-;C$h>PBdffG20mGOmlB!73o4I4IkS4* z^Lx|l-!@Ip*nQV^id)L$b=T=0>l^-Xrxj42@rEkppgT{Pk=~cQk#sI+GBE?jFa1>G09EF zNp8}Z>?Y%6H)%|IlX23UG$y~vIQdN)li=W~vHz?){fq@;GMs{w;iNGsPQgiW(wH2l z;N&j3z@~jLC5-PL7kuNf90Y`uN|53pAe>Bs1P1}(>?|R@K|nbBN=R-H5E}TArvC}G zA+o6Lc+;$*fl{&I5`fxCI|^9$6?pRkHo;qao9CMNH{qT zyCw(;C&yve1R>$%IP97rB%B!f{@Sv4vxdF2|~ijao9CMNH{qTyC!}l zCQfETt_i)Ck*;rwh3zejpMNC$(YQ1ViB^_n7P^5pmKRHcoJ@a1tDLPB0Ws zio@0khQdj5*gL^cIB5=>Cm0Hi;2=8eo?s}PREO;o426^Iuz!M}MmRQj;9xuKqhKhUY=?~$ z426^Ju#VPtc2zJGPPW6Y3Wmblr$ftmFceO$U3!pU~nRl!hb1P9w;R|P}i zWIODtAgKR-O%H~`$#&RP!B9Ba4!bHC3MboPR|P}iWIODtU?`jvg9eLt_nuN$xSFz1ta04CgiGM zB%J*)pKoE(Q;6%2*58zzm-avDyS!?`NBR%ir=U|?4TLE&C79GmELoJ5CR6VPtc2zJGPPW6Y3WmbTcGy+HP&nBR zyDAt8jo_dt)O1MImD)0178XAqfhA!bwrcS_y!{ zNm0mK34p>$QOH~gfWk>p$XyA5!r381_DTR0PPW7T3c^BguPcttcZ7(O@36xXP%oT> zhb@)>ES!voGgktza8e#NSpu+davpYB0-_E`e3aMB(&S^}_e@*Z|t zFcvq0W5j^1mH;fAyobG(04$umhs~A%ES$WDb65hfaPl6uTLQ3f@*ehE0UEEc3lt@-Ze+qb-_?*1P8BR*9Al2 z?3o3)E*J}E&kU!vVCmrg@*uQ+A^-~~;RU!Z_!@CCUV!U@v2apefa`*>aB^ON>w>Xx zl3sx8g0OHeKjNT0?ynN!;62_i6AEx$@HOJ(y#Ut*W8v-Raqu4ZR|;|T^tiuNh@-2= z{k1|IeLe0k7UJmaaeuWCM{kdNArc4gaeuuK2k-HI!BBwfg1CzND~34y&8VO2{K?Z| zaIOm-z(%>QQ9soF6DYV=Fci)n8WtlAg|mZ(wFpDu?4MyNLQr@YBw;1OP$)lem=ais zFcccW0R`(2hQir5!!m@SaCXhG3SlU`jsyqYX?Pt84!+ZH@?Ai#3%*92gcsntU@V-B z7vQ=eEZl38I5>}caS{jV>1a)HkY0f6g0B%L>jmVxU@V-p7m(|Mv2gNUfa`*>aPnS& z>w>Xx@?Jo$3&z69djYvF7z-!w1?0LQEZnP+i!pVDhfsq7b;p8ej451A@%5{x;zsLWT>w=*0E>^;>3x>jJ zN?_LoL!qsQgQu|Tf}zj|4k%cOFceOf!a{_haFP^uT`&|*j>4`BhQir3!>$X4!pU|4 zxh@zBXU{Ak*Ts)T#=TlOHsQ&*S1ZS6JQ?@*AjhUW8N84X7v%-yy5RQ0$$0^}E*J|Z z=>@nh7z-!s1-LF43n%RbxGoqAC+`KgE*J|Z?*+In2#dRpgQFW1;JRQeoE^OY*9BwY z?CAx#E*J}q;JL=J`+717C+`KUFv9i1$$J5=3&z69djYNs#=^;a0j>+i!pVC9t_#M( z$$J5=3&I-pa)6&$CD?VL1Q_MIQ0$THvi9Ko%`cI1mo*Iu+;1&{4SM^*2EB7&gEl(Y zpzQ@V=%pGGxa(D5!%h2vmzwf|+>0S_S7*RyJQVJaDuO*83isy>!5$BVoBuZ?a8vhS z!$aZz{vO!lUJiKGC>NTWVFp1S3OBC{_IN1VY^ouFn+OFP9tt=82=;g=+%FD*J>E4? zdFOG{TZRN0?;2>l^Ju(lpz+S5@k-}rQNWSB(z#DngFPM!H)CK(;7<0zhKEAuq0o6K z+~4Z~pYht0&O@Q|>cV}Uts#Ls{{kCcUAVIzu*XAT@K6}Mx-fVsyx%@1@Lpd*;F@AX z0{1sOz=l@|Chv46?{p^bbSCd~Ca)4qUL}~kOX2~$QT~RU=l`Q62@T? zMq(1iViHDU62@Z^Mr0DkWD-VY62@f`MrIPmW)enc62@l|MraboXc9(g62@r~Mrsnq zY7*~Fjo|I7So>rACSe38VGJi>6enRECt)NfVJs(MG$&y^Ct*Y?DlsB#iFhh1A$_Jg$*2#*;A0lQ7PcFw&DS){`*WlQ745iyAn5Bb9Uzzv5KIRMrUL}i z0fOlO!E}INIzTWTAeasiOa}<20|e6ng6ROkbbw$wKrkI3m<|w32MDGEYlB zfB)#ffAru#y6_);IHm&x(*c6%0Ks&CU^+lB9Uzzv5KIRMrUL}i0fOlOeVsUWjKFk& zU^+lB9Uzzv5KIRMrUL}i0fOlO!E^v#Va~(Dbbw$wKrkI3+;t&vpD-ODm<|w32MDGE z1k(Y6=>WlWfM7a6FdZP64iHQS2&MxB(*c6%0Ks&CU^+lB9Uzzv5KIRM*6|~l4iHQS z2&MxB(*c6%0Ks&CU^+lB9Uzzv5KIRMrUL}){SizD2&MxB(*c6%0Ks&CU^+lB9Uzzv z5KIRMrUL}i0dMXJMr%w5yg47b&+8}2m=1XFVMpV<{+o>HfQ;#YjOl=k>41#sfQ;#Y zjOl>qVF3=N12U!qGNuDErUNpj12S(M;6BvEtr7Zz`#)aDjCMgk%#WUzizoQGbpm*U zJw{NBSG*0c);~nT8*~1ZK8Hmh5iI^c_c|=_?rn?zNx#D)kO>z5|7{<{A}|RSKfDlYga<-rV?QjA zhMOD5)s4d@$m@as7m`)@%=Y1IbMqm{8?kLbl4w2K+LrC{V-G#|KYLoP&JM0@ zqwUu20E~C|I#+;Y&2eyZ{VU?Zaj>(t;r!S)bMtW8=H})^kXLiF@p56ifJ=knRaJfSAhHlPmU2AtR-he3$_jNtIUIulW)*j#j&_fA4 z^^FYaftJ)^`-0@ih~m(GYIJevJ5oIXtb;9Zro8Dg&xZ1*@>pI5EgK;5HoV->j~oh? zs^C@+)JfIN%at>_Q1tlGg{oR}(AGn%3rYt@ihF4rtX=I1Qf${%CPpiTSJ|a@-*yreRAdbesi=Bwz za3Yvg5Xm%U3?EQX%^I*=N^LcmwS$QX$f3~4Od>^wNR$NsfqEEtxY>Hy06t53dwa_{ zIJ@m&yW85y*|@oY4|Uya1)slp<%rwqejItH?FP@RbkG-WXIIP`CH8aOfr@@qtN z3dhK)FnG zmNp8HiqaX1aZ|5+$8pnYd@*jygfGTbBYzB?^7F;u_M;N1XsU+qI2tp7atyIEdChCGV|XfDv6tt9epmy3PbG&xCWI0vbt~?6g2h4het)z8T>Ic zRl^sfq3Kw@7#&Tu@x>Tu8j(K+X^T##LUo}auvV!cn+eqg?eqA{09i=rIzWbzzmK4T z>>*S?AO(KjQ$f}bx;Bu>y76o8B9J-^gS%b;%c_plMnD7}Q^ZF#=5|@*PKm+n!8E(_ehY(b3EY zUyOmKFZp8dxIm>4QR^`JI0_L>CGy3%%LaTgc-#Vtf$L1+ru_KMC8KFgz8D3*zZAI7 zrc!_rfX=0%X;wZwI($DU3^Yy1cN_!muR!Mxahyto`gSVX>G0!GNw5~E+_duOa;ani zcoYG66ajctG)>KiM-zZY7l20>fX5JkCx9)| zj{?_^Muo4JMuX}{p#VF{-&Qo5fHLUtm_lQq%Nu<4W5Qz!jR}t_bRs;afZGA-4H#Xh z3@}tc90!8{q-i<@?*Hh3sQh)NQ_hBv5Oh5-M< z;4TA>t{;QDq{9~@3&5km^-HjPh^{_6JNF zfX5JUy-XMnJZZt-el#%0fyxC>M!?5$msLl%0eGSTK8_6GQK+!Dpn<0n;B%=0>I}~V zzz_hHK?Bni7>^+Uk13$eOc)Pzoe&;aIfvQ`;VzetZWn~R^vM?^LmUUwU&u$$z^XI9 zWL?;5f+df@}`t*Fa7P%9qf< zl!@Qhff$TO;V%1+<_2g2=z1v>0eBPvcvJ!P12yFD>nH*=NTEailtvNImr$5cUreKd zv>1OGV3G~-fXaPrXY}<_xsP7(#el(w@IdknjzRM+a4XSAHTdx0@s|b?dvF=Rgh1yq z&?P@UJSOC?(7YkkM*zs^|s0`p)`OBaH>O$861ScSdK9V%Lel!ZK1z^MA<7fi# zXaewH&kC%q06eAuJSL1shw~~l;8~&eqjMim8hvea?xQArF(7{aHUO3ZYAZUJG(pEv zp?NZm4to$99iHdW=nS}jrZeFFnGOsLf4K}eFF<2(A0HfjZ4B-sVEi$-e`dhGod$+H zh-(Zuw?t!5VXiS~(7b}efb(2{EpVUBV4#oP@YNa4Mba1`3Ce#QlL+I1sStb|_Yu9( zWiYvqUGc?0!UQUVA^?v9Yn4fbwaNq|4TJ|Ww{Q%a`+?~jlrNz%nNa@>mK>n`3y4Ae zGaVep&u2Q3`>5NfHUKjXsDB1AsDB1MBKkNP-?>!C%cJt;Z&Q$}hx%s_gZgJWkpcD3 zbZ}|Vb%3=Ms0{FwFF&8bC<9&Qcn(8TjZ|f0H;c0(uG#6P}kQG F`aggRV_yIO literal 0 HcmV?d00001 From b0532b8c5be2b8606d014ed6746199e854b46da7 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Tue, 16 May 2023 00:06:24 +0300 Subject: [PATCH 03/13] Print-pages limit. Exc handlers was added. --- .../versions/d63e9f7661dd_page_count.py | 8 +- print_service/base.py | 17 +++ print_service/exceptions.py | 71 +++++++++++ print_service/models/__init__.py | 29 ++++- print_service/routes/__init__.py | 4 + print_service/routes/admin.py | 5 +- print_service/routes/exc_handlers.py | 111 ++++++++++++++++++ print_service/routes/file.py | 78 ++++++------ print_service/routes/qrprint.py | 3 +- print_service/routes/user.py | 7 +- print_service/utils/__init__.py | 28 +---- tests/test_routes/test_file.py | 3 +- 12 files changed, 281 insertions(+), 83 deletions(-) create mode 100644 print_service/base.py create mode 100644 print_service/exceptions.py create mode 100644 print_service/routes/exc_handlers.py diff --git a/migrations/versions/d63e9f7661dd_page_count.py b/migrations/versions/d63e9f7661dd_page_count.py index 89d823a..0c56538 100644 --- a/migrations/versions/d63e9f7661dd_page_count.py +++ b/migrations/versions/d63e9f7661dd_page_count.py @@ -17,12 +17,8 @@ def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('print_fact', sa.Column('sheet_used', sa.Integer(), nullable=False)) - # ### end Alembic commands ### + op.add_column('print_fact', sa.Column('sheets_used', sa.Integer(), nullable=True)) def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('print_fact', 'sheet_used') - # ### end Alembic commands ### + op.drop_column('print_fact', 'sheets_used') diff --git a/print_service/base.py b/print_service/base.py new file mode 100644 index 0000000..b600580 --- /dev/null +++ b/print_service/base.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel + + +class Base(BaseModel): + def __repr__(self) -> str: + attrs = [] + for k, v in self.__class__.schema().items(): + attrs.append(f"{k}={v}") + return "{}({})".format(self.__class__.__name__, ', '.join(attrs)) + + class Config: + orm_mode = True + + +class StatusResponseModel(Base): + status: str + message: str diff --git a/print_service/exceptions.py b/print_service/exceptions.py new file mode 100644 index 0000000..b62e2ad --- /dev/null +++ b/print_service/exceptions.py @@ -0,0 +1,71 @@ +from print_service.settings import get_settings + + +settings = get_settings() + + +class TooManyPages(Exception): + def __init__(self): + super().__init__(f'Content too large, count of page: {settings.MAX_PAGE_COUNT} is allowed') + + +class TooLargeSize(Exception): + def __init__(self): + super().__init__(f'Content too large, {settings.MAX_SIZE} bytes allowed') + + +class InvalidPageRequest(Exception): + def __init__(self): + super().__init__(f'Invalid format') + + +class TerminalNotFound(Exception): + def __init__(self, type: str): + super().__init__(f'Terminal is not found by {type}') + + +class UserNotFound(Exception): + def __init__(self): + super().__init__(f'User is not found') + + +class UnionStudentDuplicate(Exception): + def __init__(self): + super().__init__('Duplicates by union_numbers or student_numbers') + + +class NotInUnion(Exception): + def __init__(self): + super().__init__(f'User is not found in trade union list') + + +class PINGenerateError(Exception): + def __init__(self): + super().__init__(f'Can not generate PIN. Too many users?') + + +class FileIsNotReceived(Exception): + def __init__(self): + super().__init__(f'No file was recieved') + + +class PINNotFound(Exception): + def __init__(self, pin: str): + super().__init__(f'Pin {pin} is not found') + + +class InvalidType(Exception): + def __init__(self, content_type: str): + super().__init__( + f'Only {", ".join(settings.CONTENT_TYPES)} files allowed, but {content_type} was recieved' + ) + + +class AlreadyUpload(Exception): + def __init__(self): + super().__init__(f'File has been already uploaded') + + +class IsCorrupt(Exception): + def __init__(self): + super().__init__(f'File is corrupted') diff --git a/print_service/models/__init__.py b/print_service/models/__init__.py index 102cbfd..b48de7b 100644 --- a/print_service/models/__init__.py +++ b/print_service/models/__init__.py @@ -1,5 +1,6 @@ from __future__ import annotations +import math from datetime import datetime from sqlalchemy import Column, DateTime, Integer, String @@ -45,6 +46,32 @@ class File(Model): owner: Mapped[UnionMember] = relationship('UnionMember', back_populates='files') print_facts: Mapped[list[PrintFact]] = relationship('PrintFact', back_populates='file') + @property + def flatten_pages(self) -> list | None: + if self.number_of_pages is None: + return None + result = list() + if self.option_pages == '': + return result + for part in self.option_pages.split(','): + x = part.split('-') + result.extend(range(int(x[0]), int(x[-1]) + 1)) + return result + + @property + def sheets_count(self) -> int | None: + if self.number_of_pages is None: + return None + if not self.flatten_pages: + if self.option_two_sided: + return (self.number_of_pages // 2 + 1) * self.option_copies + else: + return self.number_of_pages * self.option_copies + if self.option_two_sided: + return math.ceil(len(self.flatten_pages) / 2) * self.option_copies + else: + return len(self.flatten_pages) * self.option_copies + class PrintFact(Model): __tablename__ = 'print_fact' @@ -57,4 +84,4 @@ class PrintFact(Model): owner: Mapped[UnionMember] = relationship('UnionMember', back_populates='print_facts') file: Mapped[File] = relationship('File', back_populates='print_facts') - sheet_used: Mapped[int] = Column(Integer, nullable=False) + sheets_used: Mapped[int] = Column(Integer) diff --git a/print_service/routes/__init__.py b/print_service/routes/__init__.py index 9b3a8a0..5e4fcb1 100644 --- a/print_service/routes/__init__.py +++ b/print_service/routes/__init__.py @@ -1 +1,5 @@ +from . import exc_handlers from .base import app + + +__all__ = ["app", "exc_handlers"] diff --git a/print_service/routes/admin.py b/print_service/routes/admin.py index 2a6835c..a2b9edf 100644 --- a/print_service/routes/admin.py +++ b/print_service/routes/admin.py @@ -5,6 +5,7 @@ from fastapi import APIRouter, Depends, HTTPException from redis import Redis +from print_service.exceptions import TerminalNotFound from print_service.schema import BaseModel from print_service.settings import Settings, get_settings @@ -52,7 +53,7 @@ async def manual_update_terminal( sender.redis.close() return {'status': 'ok'} sender.redis.close() - raise HTTPException(400, 'Terminal not found by token') + raise TerminalNotFound('token') @router.post("/reboot") @@ -65,4 +66,4 @@ async def reboot_terminal( sender.redis.close() return {'status': 'ok'} sender.redis.close() - raise HTTPException(400, 'Terminal not found by token') + raise TerminalNotFound('token') diff --git a/print_service/routes/exc_handlers.py b/print_service/routes/exc_handlers.py new file mode 100644 index 0000000..c9384b4 --- /dev/null +++ b/print_service/routes/exc_handlers.py @@ -0,0 +1,111 @@ +import starlette.requests +from starlette.responses import JSONResponse + +from print_service.base import StatusResponseModel +from print_service.exceptions import ( + AlreadyUpload, + FileIsNotReceived, + InvalidPageRequest, + InvalidType, + IsCorrupt, + NotInUnion, + PINGenerateError, + PINNotFound, + TerminalNotFound, + TooLargeSize, + TooManyPages, + UnionStudentDuplicate, + UserNotFound, +) +from print_service.routes.base import app + + +@app.exception_handler(TooLargeSize) +async def too_large_size(req: starlette.requests.Request, exc: TooLargeSize): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=413 + ) + + +@app.exception_handler(TooManyPages) +async def too_many_pages(req: starlette.requests.Request, exc: TooManyPages): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=413 + ) + + +@app.exception_handler(InvalidPageRequest) +async def invalid_format(req: starlette.requests.Request, exc: TooManyPages): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=416 + ) + + +@app.exception_handler(TerminalNotFound) +async def invalid_format(req: starlette.requests.Request, exc: TerminalNotFound): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=400 + ) + + +@app.exception_handler(UserNotFound) +async def invalid_format(req: starlette.requests.Request, exc: UserNotFound): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=404 + ) + + +@app.exception_handler(UnionStudentDuplicate) +async def invalid_format(req: starlette.requests.Request, exc: UnionStudentDuplicate): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=400 + ) + + +@app.exception_handler(NotInUnion) +async def invalid_format(req: starlette.requests.Request, exc: NotInUnion): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=403 + ) + + +@app.exception_handler(PINGenerateError) +async def invalid_format(req: starlette.requests.Request, exc: PINGenerateError): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=500 + ) + + +@app.exception_handler(FileIsNotReceived) +async def invalid_format(req: starlette.requests.Request, exc: FileIsNotReceived): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=400 + ) + + +@app.exception_handler(PINNotFound) +async def invalid_format(req: starlette.requests.Request, exc: PINNotFound): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=404 + ) + + +@app.exception_handler(InvalidType) +async def invalid_format(req: starlette.requests.Request, exc: InvalidType): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 + ) + + +@app.exception_handler(AlreadyUpload) +async def invalid_format(req: starlette.requests.Request, exc: AlreadyUpload): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 + ) + + +@app.exception_handler(IsCorrupt) +async def invalid_format(req: starlette.requests.Request, exc: IsCorrupt): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 + ) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index fc1c892..164835b 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -11,17 +11,23 @@ from pydantic import Field, validator from sqlalchemy import func, or_ +from print_service.exceptions import ( + AlreadyUpload, + FileIsNotReceived, + InvalidPageRequest, + InvalidType, + IsCorrupt, + NotInUnion, + PINGenerateError, + PINNotFound, + TooLargeSize, + TooManyPages, +) from print_service.models import File as FileModel from print_service.models import UnionMember from print_service.schema import BaseModel from print_service.settings import Settings, get_settings -from print_service.utils import ( - checking_for_page_count, - checking_for_pdf, - generate_filename, - generate_pin, - get_file, -) +from print_service.utils import checking_for_pdf, generate_filename, generate_pin, get_file logger = logging.getLogger(__name__) @@ -112,11 +118,11 @@ async def send(inp: SendInput, settings: Settings = Depends(get_settings)): func.upper(UnionMember.surname) == inp.surname.upper(), ).one_or_none() if not user: - raise HTTPException(403, 'User not found in trade union list') + raise NotInUnion try: pin = generate_pin(db.session) except RuntimeError: - raise HTTPException(500, 'Can not generate PIN. Too many users?') + raise PINGenerateError filename = generate_filename(inp.filename) file_model = FileModel(pin=pin, file=filename) file_model.owner = user @@ -154,7 +160,7 @@ async def upload_file( (меняется в настройках сервера). """ if file == ...: - raise HTTPException(400, 'No file recieved') + raise FileIsNotReceived file_model = ( db.session.query(FileModel) .filter(func.upper(FileModel.pin) == pin.upper()) @@ -162,42 +168,31 @@ async def upload_file( .one_or_none() ) if not file_model: - raise HTTPException(404, f'Pin {pin} not found') + raise PINNotFound(pin) if file.content_type not in settings.CONTENT_TYPES: - raise HTTPException( - 415, - f'Only {", ".join(settings.CONTENT_TYPES)} files allowed, but {file.content_type} recieved', - ) - + raise InvalidType path = abspath(settings.STATIC_FOLDER) + '/' + file_model.file if exists(path): - raise HTTPException(415, 'File already uploaded') + raise AlreadyUpload async with aiofiles.open(path, 'wb') as saved_file: memory_file = await file.read() if len(memory_file) > settings.MAX_SIZE: - raise HTTPException(413, f'Content too large, {settings.MAX_SIZE} bytes allowed') + raise TooLargeSize await saved_file.write(memory_file) pdf_ok, number_of_pages = checking_for_pdf(memory_file) file_model.number_of_pages = number_of_pages db.session.commit() if not pdf_ok: await aiofiles.os.remove(path) - raise HTTPException(415, 'File corrupted') - - if ( - checking_for_page_count( - file_model.option_pages, - file_model.option_two_sided, - file_model.option_copies, - file_model.number_of_pages, - ) - > settings.MAX_PAGE_COUNT - ): + raise IsCorrupt + if file_model.flatten_pages: + if number_of_pages < max(file_model.flatten_pages): + await aiofiles.os.remove(path) + raise InvalidPageRequest + if file_model.sheets_count > settings.MAX_PAGE_COUNT: await aiofiles.os.remove(path) - raise HTTPException( - 413, f'Content too large, count of page: {settings.MAX_PAGE_COUNT} is allowed' - ) + raise TooManyPages await file.close() return { @@ -233,25 +228,18 @@ async def update_file_options( ) print(options) if not file_model: - raise HTTPException(404, f'Pin {pin} not found') + raise PINNotFound(pin) file_model.option_pages = options.get('pages') or file_model.option_pages file_model.option_copies = options.get('copies') or file_model.option_copies file_model.option_two_sided = ( v if (v := options.get('two_sided')) is not None else file_model.option_two_sided ) db.session.commit() - if ( - checking_for_page_count( - file_model.option_pages, - file_model.option_two_sided, - file_model.option_copies, - file_model.number_of_pages, - ) - > settings.MAX_PAGE_COUNT - ): - raise HTTPException( - 413, f'Content too large, count of page: {settings.MAX_PAGE_COUNT} is allowed' - ) + if file_model.flatten_pages: + if file_model.number_of_pages < max(file_model.flatten_pages): + raise InvalidPageRequest + if file_model.sheets_count > settings.MAX_PAGE_COUNT: + raise TooManyPages return { 'pin': file_model.pin, 'options': { diff --git a/print_service/routes/qrprint.py b/print_service/routes/qrprint.py index ecac611..792d8da 100644 --- a/print_service/routes/qrprint.py +++ b/print_service/routes/qrprint.py @@ -9,6 +9,7 @@ from pydantic import conlist from redis import Redis +from print_service.exceptions import TerminalNotFound from print_service.schema import BaseModel from print_service.settings import Settings, get_settings from print_service.utils import get_file @@ -92,7 +93,7 @@ async def instant_print(options: InstantPrintCreate): options.qr_token = options.qr_token.removeprefix(settings.QR_TOKEN_PREFIX) if redis_conn.send(**options.dict()): return {'status': 'ok'} - raise HTTPException(400, 'Terminal not found by qr') + raise TerminalNotFound('QR') @router.websocket("") diff --git a/print_service/routes/user.py b/print_service/routes/user.py index f627613..8a5df4c 100644 --- a/print_service/routes/user.py +++ b/print_service/routes/user.py @@ -9,6 +9,7 @@ from sqlalchemy import and_, func, or_ from print_service import __version__ +from print_service.exceptions import UnionStudentDuplicate, UserNotFound from print_service.models import UnionMember from print_service.schema import BaseModel from print_service.settings import get_settings @@ -62,7 +63,7 @@ async def check_union_member( return bool(user) if not user: - raise HTTPException(404, 'User not found') + raise UserNotFound else: return { 'surname': user.surname, @@ -85,9 +86,7 @@ def update_list( if len(union_numbers) != len(set(union_numbers)) or len(student_numbers) != len( set(student_numbers) ): - raise HTTPException( - 400, {"status": "error", "detail": "Duplicates by union_numbers or student_numbers"} - ) + raise UnionStudentDuplicate for user in input.users: db_user: UnionMember = ( diff --git a/print_service/utils/__init__.py b/print_service/utils/__init__.py index 8de8bb3..0dab0b3 100644 --- a/print_service/utils/__init__.py +++ b/print_service/utils/__init__.py @@ -11,6 +11,7 @@ from sqlalchemy import func from sqlalchemy.orm.session import Session +from print_service.exceptions import InvalidPageRequest from print_service.models import File from print_service.models import File as FileModel from print_service.models import PrintFact @@ -75,13 +76,10 @@ def get_file(dbsession, pin: str or list[str]): } ) _, number_of_pages = checking_for_pdf(f) - file_model = PrintFact( - file_id=f.id, - owner_id=f.owner_id, - sheet_used=checking_for_page_count( - f.option_pages, f.option_two_sided, f.option_copies, number_of_pages - ), - ) + if f.flatten_pages: + if number_of_pages > max(f.flatten_pages): + raise InvalidPageRequest + file_model = PrintFact(file_id=f.id, owner_id=f.owner_id, sheets_used=f.sheets_count) dbsession.add(file_model) dbsession.commit() return result @@ -102,19 +100,3 @@ def checking_for_pdf(f: bytes) -> tuple[bool, int]: return True, pdf_file.getNumPages() except Exception: return False, 0 - - -def checking_for_page_count(page: str, two_side_print: bool, copy_count: int, num_of_page: int) -> int: - if page == '': - if two_side_print: - return (num_of_page // 2 + 1) * copy_count - else: - return num_of_page * copy_count - result = set() - for part in page.split(','): - x = part.split('-') - result.update(range(int(x[0]), int(x[-1]) + 1)) - if two_side_print: - return math.ceil(len(result) / 2) * copy_count - else: - return len(result) * copy_count diff --git a/tests/test_routes/test_file.py b/tests/test_routes/test_file.py index eaf9e21..73b10c9 100644 --- a/tests/test_routes/test_file.py +++ b/tests/test_routes/test_file.py @@ -191,4 +191,5 @@ def test_upload_big_file(pin_pdf, client): get_settings().MAX_PAGE_COUNT = 4 res7 = client.patch(f"{url}/{pin_pdf}", json=payload3) assert res7.status_code == status.HTTP_200_OK - get_settings().MAX_PAGE_COUNT = max_page + get_settings().MAX_PAGE_COUNT = 6 + payload4 = {"options": {"pages": "1-5, 3", "copies": 1, "two_sided": False}} From 766fceb24c727b40590c4b4cc3116da24d4e6281 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Tue, 16 May 2023 00:34:27 +0300 Subject: [PATCH 04/13] Print-pages limit. Exc handlers was added. --- tests/test_routes/test_file.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_routes/test_file.py b/tests/test_routes/test_file.py index 73b10c9..54a6eb9 100644 --- a/tests/test_routes/test_file.py +++ b/tests/test_routes/test_file.py @@ -191,5 +191,9 @@ def test_upload_big_file(pin_pdf, client): get_settings().MAX_PAGE_COUNT = 4 res7 = client.patch(f"{url}/{pin_pdf}", json=payload3) assert res7.status_code == status.HTTP_200_OK - get_settings().MAX_PAGE_COUNT = 6 - payload4 = {"options": {"pages": "1-5, 3", "copies": 1, "two_sided": False}} + get_settings().MAX_PAGE_COUNT = 2 + payload4 = {"options": {"pages": "1, 1, 1", "copies": 1, "two_sided": False}} + res8 = client.patch(f"{url}/{pin_pdf}", json=payload4) + assert res8.status_code == status.HTTP_413_REQUEST_ENTITY_TOO_LARGE + get_settings().MAX_PAGE_COUNT = max_page + From 51346a1aec40409cd1786ba5061f150d90b0d203 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Tue, 16 May 2023 00:34:36 +0300 Subject: [PATCH 05/13] Print-pages limit. Exc handlers was added. --- tests/test_routes/test_file.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_routes/test_file.py b/tests/test_routes/test_file.py index 54a6eb9..aaebaab 100644 --- a/tests/test_routes/test_file.py +++ b/tests/test_routes/test_file.py @@ -196,4 +196,3 @@ def test_upload_big_file(pin_pdf, client): res8 = client.patch(f"{url}/{pin_pdf}", json=payload4) assert res8.status_code == status.HTTP_413_REQUEST_ENTITY_TOO_LARGE get_settings().MAX_PAGE_COUNT = max_page - From 8ccb6aaadf20c5ebe9877e944a40d543619e95f1 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Fri, 19 May 2023 22:38:52 +0300 Subject: [PATCH 06/13] Print-pages limit. Exc handlers was added. --- print_service/exceptions.py | 55 ++++++++++++++++------- print_service/models/__init__.py | 8 ++-- print_service/routes/admin.py | 6 +-- print_service/routes/exc_handlers.py | 66 +++++++++++++++++++++------- print_service/routes/file.py | 25 ++++++----- print_service/routes/qrprint.py | 9 ++-- print_service/routes/user.py | 4 +- print_service/settings.py | 2 +- print_service/utils/__init__.py | 16 ++++--- tests/test_routes/test_file.py | 8 ++-- 10 files changed, 138 insertions(+), 61 deletions(-) diff --git a/print_service/exceptions.py b/print_service/exceptions.py index b62e2ad..64fe804 100644 --- a/print_service/exceptions.py +++ b/print_service/exceptions.py @@ -4,6 +4,36 @@ settings = get_settings() +class ObjectNotFound(Exception): + def __init__(self): + pass + + +class TerminalTokenNotFound(ObjectNotFound): + def __init__(self): + pass + + +class TerminalQRNotFound(ObjectNotFound): + def __init__(self): + pass + + +class PINNotFound(ObjectNotFound): + def __init__(self, pin: str): + self.pin = pin + + +class UserNotFound(ObjectNotFound): + def __init__(self): + pass + + +class FileNotFound(ObjectNotFound): + def __init__(self, count: int): + self.count = count + + class TooManyPages(Exception): def __init__(self): super().__init__(f'Content too large, count of page: {settings.MAX_PAGE_COUNT} is allowed') @@ -19,16 +49,6 @@ def __init__(self): super().__init__(f'Invalid format') -class TerminalNotFound(Exception): - def __init__(self, type: str): - super().__init__(f'Terminal is not found by {type}') - - -class UserNotFound(Exception): - def __init__(self): - super().__init__(f'User is not found') - - class UnionStudentDuplicate(Exception): def __init__(self): super().__init__('Duplicates by union_numbers or student_numbers') @@ -49,11 +69,6 @@ def __init__(self): super().__init__(f'No file was recieved') -class PINNotFound(Exception): - def __init__(self, pin: str): - super().__init__(f'Pin {pin} is not found') - - class InvalidType(Exception): def __init__(self, content_type: str): super().__init__( @@ -69,3 +84,13 @@ def __init__(self): class IsCorrupt(Exception): def __init__(self): super().__init__(f'File is corrupted') + + +class IsNotUpload(Exception): + def __init__(self): + super().__init__(f'File has not been uploaded yet') + + +class UnprocessableFileInstance(Exception): + def __init__(self): + super().__init__(f'Unprocessable file instance') diff --git a/print_service/models/__init__.py b/print_service/models/__init__.py index b48de7b..0dea421 100644 --- a/print_service/models/__init__.py +++ b/print_service/models/__init__.py @@ -63,10 +63,10 @@ def sheets_count(self) -> int | None: if self.number_of_pages is None: return None if not self.flatten_pages: - if self.option_two_sided: - return (self.number_of_pages // 2 + 1) * self.option_copies - else: - return self.number_of_pages * self.option_copies + return ( + math.ceil(self.number_of_pages - (self.option_two_sided * self.number_of_pages / 2)) + * self.option_copies + ) if self.option_two_sided: return math.ceil(len(self.flatten_pages) / 2) * self.option_copies else: diff --git a/print_service/routes/admin.py b/print_service/routes/admin.py index a2b9edf..fa9436e 100644 --- a/print_service/routes/admin.py +++ b/print_service/routes/admin.py @@ -5,7 +5,7 @@ from fastapi import APIRouter, Depends, HTTPException from redis import Redis -from print_service.exceptions import TerminalNotFound +from print_service.exceptions import TerminalTokenNotFound from print_service.schema import BaseModel from print_service.settings import Settings, get_settings @@ -53,7 +53,7 @@ async def manual_update_terminal( sender.redis.close() return {'status': 'ok'} sender.redis.close() - raise TerminalNotFound('token') + raise TerminalTokenNotFound() @router.post("/reboot") @@ -66,4 +66,4 @@ async def reboot_terminal( sender.redis.close() return {'status': 'ok'} sender.redis.close() - raise TerminalNotFound('token') + raise TerminalTokenNotFound() diff --git a/print_service/routes/exc_handlers.py b/print_service/routes/exc_handlers.py index c9384b4..5fecd5b 100644 --- a/print_service/routes/exc_handlers.py +++ b/print_service/routes/exc_handlers.py @@ -5,16 +5,20 @@ from print_service.exceptions import ( AlreadyUpload, FileIsNotReceived, + FileNotFound, InvalidPageRequest, InvalidType, IsCorrupt, + IsNotUpload, NotInUnion, PINGenerateError, PINNotFound, - TerminalNotFound, + TerminalQRNotFound, + TerminalTokenNotFound, TooLargeSize, TooManyPages, UnionStudentDuplicate, + UnprocessableFileInstance, UserNotFound, ) from print_service.routes.base import app @@ -41,71 +45,103 @@ async def invalid_format(req: starlette.requests.Request, exc: TooManyPages): ) -@app.exception_handler(TerminalNotFound) -async def invalid_format(req: starlette.requests.Request, exc: TerminalNotFound): +@app.exception_handler(TerminalQRNotFound) +async def terminal_not_found(req: starlette.requests.Request, exc: TerminalQRNotFound): return JSONResponse( - content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=400 + content=StatusResponseModel(status="Error", message=f"Terminal not found by QR").dict(), + status_code=400, + ) + + +@app.exception_handler(TerminalTokenNotFound) +async def terminal_not_found(req: starlette.requests.Request, exc: TerminalTokenNotFound): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"Terminal not found by token").dict(), + status_code=400, ) @app.exception_handler(UserNotFound) -async def invalid_format(req: starlette.requests.Request, exc: UserNotFound): +async def user_not_found(req: starlette.requests.Request, exc: UserNotFound): return JSONResponse( - content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=404 + content=StatusResponseModel(status="Error", message=f"User not found").dict(), status_code=404 ) @app.exception_handler(UnionStudentDuplicate) -async def invalid_format(req: starlette.requests.Request, exc: UnionStudentDuplicate): +async def student_duplicate(req: starlette.requests.Request, exc: UnionStudentDuplicate): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=400 ) @app.exception_handler(NotInUnion) -async def invalid_format(req: starlette.requests.Request, exc: NotInUnion): +async def not_in_union(req: starlette.requests.Request, exc: NotInUnion): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=403 ) @app.exception_handler(PINGenerateError) -async def invalid_format(req: starlette.requests.Request, exc: PINGenerateError): +async def generate_error(req: starlette.requests.Request, exc: PINGenerateError): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=500 ) @app.exception_handler(FileIsNotReceived) -async def invalid_format(req: starlette.requests.Request, exc: FileIsNotReceived): +async def file_not_received(req: starlette.requests.Request, exc: FileIsNotReceived): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=400 ) @app.exception_handler(PINNotFound) -async def invalid_format(req: starlette.requests.Request, exc: PINNotFound): +async def pin_not_found(req: starlette.requests.Request, exc: PINNotFound): return JSONResponse( - content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=404 + content=StatusResponseModel(status="Error", message=f"Pin {exc.pin} not found").dict(), + status_code=404, ) @app.exception_handler(InvalidType) -async def invalid_format(req: starlette.requests.Request, exc: InvalidType): +async def invalid_type(req: starlette.requests.Request, exc: InvalidType): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 ) @app.exception_handler(AlreadyUpload) -async def invalid_format(req: starlette.requests.Request, exc: AlreadyUpload): +async def already_upload(req: starlette.requests.Request, exc: AlreadyUpload): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 ) @app.exception_handler(IsCorrupt) -async def invalid_format(req: starlette.requests.Request, exc: IsCorrupt): +async def is_corrupt(req: starlette.requests.Request, exc: IsCorrupt): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 + ) + + +@app.exception_handler(UnprocessableFileInstance) +async def unprocessable_file(req: starlette.requests.Request, exc: UnprocessableFileInstance): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=422 + ) + + +@app.exception_handler(FileNotFound) +async def unprocessable_file(req: starlette.requests.Request, exc: FileNotFound): + return JSONResponse( + content=StatusResponseModel(status="Error", message=f"{exc.count} file(s) not found").dict(), + status_code=404, + ) + + +@app.exception_handler(IsNotUpload) +async def not_upload(req: starlette.requests.Request, exc: IsNotUpload): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 ) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index 164835b..b588749 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -22,6 +22,8 @@ PINNotFound, TooLargeSize, TooManyPages, + UnprocessableFileInstance, + UserNotFound, ) from print_service.models import File as FileModel from print_service.models import UnionMember @@ -118,12 +120,15 @@ async def send(inp: SendInput, settings: Settings = Depends(get_settings)): func.upper(UnionMember.surname) == inp.surname.upper(), ).one_or_none() if not user: - raise NotInUnion + raise NotInUnion() try: pin = generate_pin(db.session) except RuntimeError: raise PINGenerateError - filename = generate_filename(inp.filename) + try: + filename = generate_filename(inp.filename) + except UnprocessableFileInstance as ex: + raise ex file_model = FileModel(pin=pin, file=filename) file_model.owner = user file_model.option_copies = inp.options.copies @@ -160,7 +165,7 @@ async def upload_file( (меняется в настройках сервера). """ if file == ...: - raise FileIsNotReceived + raise FileIsNotReceived() file_model = ( db.session.query(FileModel) .filter(func.upper(FileModel.pin) == pin.upper()) @@ -170,29 +175,29 @@ async def upload_file( if not file_model: raise PINNotFound(pin) if file.content_type not in settings.CONTENT_TYPES: - raise InvalidType + raise InvalidType() path = abspath(settings.STATIC_FOLDER) + '/' + file_model.file if exists(path): - raise AlreadyUpload + raise AlreadyUpload() async with aiofiles.open(path, 'wb') as saved_file: memory_file = await file.read() if len(memory_file) > settings.MAX_SIZE: - raise TooLargeSize + raise TooLargeSize() await saved_file.write(memory_file) pdf_ok, number_of_pages = checking_for_pdf(memory_file) file_model.number_of_pages = number_of_pages db.session.commit() if not pdf_ok: await aiofiles.os.remove(path) - raise IsCorrupt + raise IsCorrupt() if file_model.flatten_pages: if number_of_pages < max(file_model.flatten_pages): await aiofiles.os.remove(path) - raise InvalidPageRequest + raise InvalidPageRequest() if file_model.sheets_count > settings.MAX_PAGE_COUNT: await aiofiles.os.remove(path) - raise TooManyPages + raise TooManyPages() await file.close() return { @@ -239,7 +244,7 @@ async def update_file_options( if file_model.number_of_pages < max(file_model.flatten_pages): raise InvalidPageRequest if file_model.sheets_count > settings.MAX_PAGE_COUNT: - raise TooManyPages + raise TooManyPages() return { 'pin': file_model.pin, 'options': { diff --git a/print_service/routes/qrprint.py b/print_service/routes/qrprint.py index 792d8da..9771f1d 100644 --- a/print_service/routes/qrprint.py +++ b/print_service/routes/qrprint.py @@ -9,7 +9,7 @@ from pydantic import conlist from redis import Redis -from print_service.exceptions import TerminalNotFound +from print_service.exceptions import FileNotFound, InvalidPageRequest, IsNotUpload, TerminalQRNotFound from print_service.schema import BaseModel from print_service.settings import Settings, get_settings from print_service.utils import get_file @@ -38,7 +38,10 @@ def send(self, qr_token: str, files: list[str]): old = self.redis.get(terminal) if old: return None - files = get_file(db.session, files) + try: + files = get_file(db.session, files) + except (FileNotFound, IsNotUpload, InvalidPageRequest) as ex: + raise ex self.redis.set(terminal, json.dumps({'files': files})) return files @@ -93,7 +96,7 @@ async def instant_print(options: InstantPrintCreate): options.qr_token = options.qr_token.removeprefix(settings.QR_TOKEN_PREFIX) if redis_conn.send(**options.dict()): return {'status': 'ok'} - raise TerminalNotFound('QR') + raise TerminalQRNotFound() @router.websocket("") diff --git a/print_service/routes/user.py b/print_service/routes/user.py index 8a5df4c..4ac1654 100644 --- a/print_service/routes/user.py +++ b/print_service/routes/user.py @@ -63,7 +63,7 @@ async def check_union_member( return bool(user) if not user: - raise UserNotFound + raise UserNotFound() else: return { 'surname': user.surname, @@ -86,7 +86,7 @@ def update_list( if len(union_numbers) != len(set(union_numbers)) or len(student_numbers) != len( set(student_numbers) ): - raise UnionStudentDuplicate + raise UnionStudentDuplicate() for user in input.users: db_user: UnionMember = ( diff --git a/print_service/settings.py b/print_service/settings.py index c870006..331c29b 100644 --- a/print_service/settings.py +++ b/print_service/settings.py @@ -16,7 +16,7 @@ class Settings(UnionAuthSettings, BaseSettings): CONTENT_TYPES: List[str] = ['application/pdf'] MAX_SIZE: int = 5000000 # Максимальный размер файла в байтах - MAX_PAGE_COUNT: int = 5 + MAX_PAGE_COUNT: int = 20 STORAGE_TIME: int = 7 * 24 # Время хранения файла в часах STATIC_FOLDER: DirectoryPath | None diff --git a/print_service/utils/__init__.py b/print_service/utils/__init__.py index 0dab0b3..63cfe1e 100644 --- a/print_service/utils/__init__.py +++ b/print_service/utils/__init__.py @@ -11,10 +11,16 @@ from sqlalchemy import func from sqlalchemy.orm.session import Session -from print_service.exceptions import InvalidPageRequest +from print_service.exceptions import ( + FileNotFound, + InvalidPageRequest, + IsNotUpload, + UnprocessableFileInstance, +) from print_service.models import File from print_service.models import File as FileModel from print_service.models import PrintFact +from print_service.routes import exc_handlers from print_service.settings import Settings, get_settings @@ -43,7 +49,7 @@ def generate_filename(original_filename: str): salt = ''.join(random.choice(settings.PIN_SYMBOLS) for _ in range(128)) ext_list = re.findall(r'\w+', original_filename.split('.')[-1]) if not ext_list: - raise HTTPException(422, "Unprocessable file instance") + raise UnprocessableFileInstance() ext = ext_list[0] return f'{datestr}-{salt}.{ext}' @@ -57,13 +63,13 @@ def get_file(dbsession, pin: str or list[str]): .all() ) if len(pin) != len(files): - raise HTTPException(404, f'{len(pin) - len(files)} file(s) not found') + raise FileNotFound(len(pin) - len(files)) result = [] for f in files: path = abspath(settings.STATIC_FOLDER) + '/' + f.file if not exists(path): - raise HTTPException(415, 'File has not uploaded yet') + raise IsNotUpload() result.append( { @@ -78,7 +84,7 @@ def get_file(dbsession, pin: str or list[str]): _, number_of_pages = checking_for_pdf(f) if f.flatten_pages: if number_of_pages > max(f.flatten_pages): - raise InvalidPageRequest + raise InvalidPageRequest() file_model = PrintFact(file_id=f.id, owner_id=f.owner_id, sheets_used=f.sheets_count) dbsession.add(file_model) dbsession.commit() diff --git a/tests/test_routes/test_file.py b/tests/test_routes/test_file.py index aaebaab..f45fbf1 100644 --- a/tests/test_routes/test_file.py +++ b/tests/test_routes/test_file.py @@ -4,6 +4,7 @@ from fastapi import HTTPException from starlette import status +from print_service.exceptions import FileNotFound, InvalidPageRequest, IsNotUpload from print_service.models import File from print_service.settings import get_settings from print_service.utils import checking_for_pdf, get_file @@ -56,13 +57,14 @@ def test_get_file_wrong_pin(uploaded_file_os, client): def test_get_file_func_1_not_exists(dbsession): - with pytest.raises(HTTPException): + with pytest.raises((FileNotFound, IsNotUpload, InvalidPageRequest)): get_file(dbsession, ['1']) + assert FileNotFound dbsession.commit() def test_get_file_func_1_not_uploaded(dbsession, uploaded_file_db): - with pytest.raises(HTTPException): + with pytest.raises((FileNotFound, IsNotUpload, InvalidPageRequest)): data = get_file(dbsession, [uploaded_file_db.pin]) dbsession.commit() @@ -82,7 +84,7 @@ def test_get_file_func_1_ok(dbsession, uploaded_file_os): def test_get_file_func_2_not_exists(dbsession, uploaded_file_os): - with pytest.raises(HTTPException): + with pytest.raises((FileNotFound, IsNotUpload, InvalidPageRequest)): data = get_file(dbsession, [uploaded_file_os.pin, '1']) From 1361b3a8000ed9d027bdbaca836ea0559a6c1735 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Fri, 19 May 2023 23:06:28 +0300 Subject: [PATCH 07/13] Print-pages limit. Workflow update. --- .github/workflows/build_and_publish.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_and_publish.yml b/.github/workflows/build_and_publish.yml index cdaac9b..c45e84e 100644 --- a/.github/workflows/build_and_publish.yml +++ b/.github/workflows/build_and_publish.yml @@ -108,6 +108,7 @@ jobs: --env ALLOW_STUDENT_NUMBER=true \ --env STATIC_FOLDER=/app/static \ --env STORAGE_TIME=30 \ + --env MAX_PAGE_COUNT=20 \ --env AUTH_URL=https://auth.api.test.profcomff.com/ \ --name ${{ env.CONTAITER_NAME }} \ ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test @@ -174,6 +175,7 @@ jobs: --env ALLOW_STUDENT_NUMBER=true \ --env STATIC_FOLDER=/app/static \ --env STORAGE_TIME=168 \ + --env MAX_PAGE_COUNT=20 \ --env AUTH_URL=https://auth.api.profcomff.com/ \ --name ${{ env.CONTAITER_NAME }} \ ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest From d37c248ab401f26d0d3b16e534ed6ac67477e3b2 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 22 May 2023 19:15:32 +0300 Subject: [PATCH 08/13] Print-pages limit. Workflow update. --- print_service/exceptions.py | 6 +++--- print_service/models/__init__.py | 6 +++++- print_service/routes/exc_handlers.py | 22 +++++++++++----------- print_service/routes/file.py | 19 +++++++++++-------- print_service/routes/qrprint.py | 7 ++----- print_service/utils/__init__.py | 4 ++-- tests/test_routes/test_file.py | 8 ++++---- 7 files changed, 38 insertions(+), 34 deletions(-) diff --git a/print_service/exceptions.py b/print_service/exceptions.py index 64fe804..3a37e98 100644 --- a/print_service/exceptions.py +++ b/print_service/exceptions.py @@ -76,17 +76,17 @@ def __init__(self, content_type: str): ) -class AlreadyUpload(Exception): +class AlreadyUploaded(Exception): def __init__(self): super().__init__(f'File has been already uploaded') -class IsCorrupt(Exception): +class IsCorrupted(Exception): def __init__(self): super().__init__(f'File is corrupted') -class IsNotUpload(Exception): +class IsNotUploaded(Exception): def __init__(self): super().__init__(f'File has not been uploaded yet') diff --git a/print_service/models/__init__.py b/print_service/models/__init__.py index 0dea421..12a1778 100644 --- a/print_service/models/__init__.py +++ b/print_service/models/__init__.py @@ -47,7 +47,9 @@ class File(Model): print_facts: Mapped[list[PrintFact]] = relationship('PrintFact', back_populates='file') @property - def flatten_pages(self) -> list | None: + def flatten_pages(self) -> list[int] | None: + ''' Формирует и возвращает, учитывая интервалы, список, содержащий числа, из строки вида + "1-5, 3, 2"''' if self.number_of_pages is None: return None result = list() @@ -60,6 +62,8 @@ def flatten_pages(self) -> list | None: @property def sheets_count(self) -> int | None: + '''Возвращает, учитывая интервалы, количество чисел, полученных из строки вида + "1-5, 3, 2"''' if self.number_of_pages is None: return None if not self.flatten_pages: diff --git a/print_service/routes/exc_handlers.py b/print_service/routes/exc_handlers.py index 5fecd5b..42f6bab 100644 --- a/print_service/routes/exc_handlers.py +++ b/print_service/routes/exc_handlers.py @@ -3,13 +3,13 @@ from print_service.base import StatusResponseModel from print_service.exceptions import ( - AlreadyUpload, + AlreadyUploaded, FileIsNotReceived, FileNotFound, InvalidPageRequest, InvalidType, - IsCorrupt, - IsNotUpload, + IsCorrupted, + IsNotUploaded, NotInUnion, PINGenerateError, PINNotFound, @@ -111,37 +111,37 @@ async def invalid_type(req: starlette.requests.Request, exc: InvalidType): ) -@app.exception_handler(AlreadyUpload) -async def already_upload(req: starlette.requests.Request, exc: AlreadyUpload): +@app.exception_handler(AlreadyUploaded) +async def already_upload(req: starlette.requests.Request, exc: AlreadyUploaded): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 ) -@app.exception_handler(IsCorrupt) -async def is_corrupt(req: starlette.requests.Request, exc: IsCorrupt): +@app.exception_handler(IsCorrupted) +async def is_corrupted(req: starlette.requests.Request, exc: IsCorrupted): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 ) @app.exception_handler(UnprocessableFileInstance) -async def unprocessable_file(req: starlette.requests.Request, exc: UnprocessableFileInstance): +async def unprocessable_file_instance(req: starlette.requests.Request, exc: UnprocessableFileInstance): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=422 ) @app.exception_handler(FileNotFound) -async def unprocessable_file(req: starlette.requests.Request, exc: FileNotFound): +async def file_not_found(req: starlette.requests.Request, exc: FileNotFound): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc.count} file(s) not found").dict(), status_code=404, ) -@app.exception_handler(IsNotUpload) -async def not_upload(req: starlette.requests.Request, exc: IsNotUpload): +@app.exception_handler(IsNotUploaded) +async def not_uploaded(req: starlette.requests.Request, exc: IsNotUploaded): return JSONResponse( content=StatusResponseModel(status="Error", message=f"{exc}").dict(), status_code=415 ) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index b588749..b8208c5 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -12,11 +12,11 @@ from sqlalchemy import func, or_ from print_service.exceptions import ( - AlreadyUpload, + AlreadyUploaded, FileIsNotReceived, InvalidPageRequest, InvalidType, - IsCorrupt, + IsCorrupted, NotInUnion, PINGenerateError, PINNotFound, @@ -125,10 +125,7 @@ async def send(inp: SendInput, settings: Settings = Depends(get_settings)): pin = generate_pin(db.session) except RuntimeError: raise PINGenerateError - try: - filename = generate_filename(inp.filename) - except UnprocessableFileInstance as ex: - raise ex + filename = generate_filename(inp.filename) file_model = FileModel(pin=pin, file=filename) file_model.owner = user file_model.option_copies = inp.options.copies @@ -173,16 +170,19 @@ async def upload_file( .one_or_none() ) if not file_model: + await file.close() raise PINNotFound(pin) if file.content_type not in settings.CONTENT_TYPES: raise InvalidType() path = abspath(settings.STATIC_FOLDER) + '/' + file_model.file if exists(path): - raise AlreadyUpload() + await file.close() + raise AlreadyUploaded() async with aiofiles.open(path, 'wb') as saved_file: memory_file = await file.read() if len(memory_file) > settings.MAX_SIZE: + await file.close() raise TooLargeSize() await saved_file.write(memory_file) pdf_ok, number_of_pages = checking_for_pdf(memory_file) @@ -190,13 +190,16 @@ async def upload_file( db.session.commit() if not pdf_ok: await aiofiles.os.remove(path) - raise IsCorrupt() + await file.close() + raise IsCorrupted() if file_model.flatten_pages: if number_of_pages < max(file_model.flatten_pages): await aiofiles.os.remove(path) + await file.close() raise InvalidPageRequest() if file_model.sheets_count > settings.MAX_PAGE_COUNT: await aiofiles.os.remove(path) + await file.close() raise TooManyPages() await file.close() diff --git a/print_service/routes/qrprint.py b/print_service/routes/qrprint.py index 9771f1d..a482d57 100644 --- a/print_service/routes/qrprint.py +++ b/print_service/routes/qrprint.py @@ -9,7 +9,7 @@ from pydantic import conlist from redis import Redis -from print_service.exceptions import FileNotFound, InvalidPageRequest, IsNotUpload, TerminalQRNotFound +from print_service.exceptions import FileNotFound, InvalidPageRequest, IsNotUploaded, TerminalQRNotFound from print_service.schema import BaseModel from print_service.settings import Settings, get_settings from print_service.utils import get_file @@ -38,10 +38,7 @@ def send(self, qr_token: str, files: list[str]): old = self.redis.get(terminal) if old: return None - try: - files = get_file(db.session, files) - except (FileNotFound, IsNotUpload, InvalidPageRequest) as ex: - raise ex + files = get_file(db.session, files) self.redis.set(terminal, json.dumps({'files': files})) return files diff --git a/print_service/utils/__init__.py b/print_service/utils/__init__.py index 63cfe1e..1c44b33 100644 --- a/print_service/utils/__init__.py +++ b/print_service/utils/__init__.py @@ -14,7 +14,7 @@ from print_service.exceptions import ( FileNotFound, InvalidPageRequest, - IsNotUpload, + IsNotUploaded, UnprocessableFileInstance, ) from print_service.models import File @@ -69,7 +69,7 @@ def get_file(dbsession, pin: str or list[str]): for f in files: path = abspath(settings.STATIC_FOLDER) + '/' + f.file if not exists(path): - raise IsNotUpload() + raise IsNotUploaded() result.append( { diff --git a/tests/test_routes/test_file.py b/tests/test_routes/test_file.py index f45fbf1..a04465c 100644 --- a/tests/test_routes/test_file.py +++ b/tests/test_routes/test_file.py @@ -4,7 +4,7 @@ from fastapi import HTTPException from starlette import status -from print_service.exceptions import FileNotFound, InvalidPageRequest, IsNotUpload +from print_service.exceptions import FileNotFound, InvalidPageRequest, IsNotUploaded from print_service.models import File from print_service.settings import get_settings from print_service.utils import checking_for_pdf, get_file @@ -57,14 +57,14 @@ def test_get_file_wrong_pin(uploaded_file_os, client): def test_get_file_func_1_not_exists(dbsession): - with pytest.raises((FileNotFound, IsNotUpload, InvalidPageRequest)): + with pytest.raises((FileNotFound, IsNotUploaded, InvalidPageRequest)): get_file(dbsession, ['1']) assert FileNotFound dbsession.commit() def test_get_file_func_1_not_uploaded(dbsession, uploaded_file_db): - with pytest.raises((FileNotFound, IsNotUpload, InvalidPageRequest)): + with pytest.raises((FileNotFound, IsNotUploaded, InvalidPageRequest)): data = get_file(dbsession, [uploaded_file_db.pin]) dbsession.commit() @@ -84,7 +84,7 @@ def test_get_file_func_1_ok(dbsession, uploaded_file_os): def test_get_file_func_2_not_exists(dbsession, uploaded_file_os): - with pytest.raises((FileNotFound, IsNotUpload, InvalidPageRequest)): + with pytest.raises((FileNotFound, IsNotUploaded, InvalidPageRequest)): data = get_file(dbsession, [uploaded_file_os.pin, '1']) From 1c64e00a81d3f2f499ed820f6ea38fa60492f970 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 22 May 2023 19:17:34 +0300 Subject: [PATCH 09/13] Print-pages limit. Workflow update. --- print_service/models/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/print_service/models/__init__.py b/print_service/models/__init__.py index 12a1778..9332ee3 100644 --- a/print_service/models/__init__.py +++ b/print_service/models/__init__.py @@ -48,7 +48,7 @@ class File(Model): @property def flatten_pages(self) -> list[int] | None: - ''' Формирует и возвращает, учитывая интервалы, список, содержащий числа, из строки вида + '''Формирует и возвращает, учитывая интервалы, список, содержащий числа, из строки вида "1-5, 3, 2"''' if self.number_of_pages is None: return None From 74f2ff4deb5173020ccc6d76856e37cb03c6bf53 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 22 May 2023 19:41:26 +0300 Subject: [PATCH 10/13] Print-pages limit. Fixes. --- print_service/models/__init__.py | 7 ++++--- print_service/routes/exc_handlers.py | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/print_service/models/__init__.py b/print_service/models/__init__.py index 9332ee3..e3af743 100644 --- a/print_service/models/__init__.py +++ b/print_service/models/__init__.py @@ -48,8 +48,8 @@ class File(Model): @property def flatten_pages(self) -> list[int] | None: - '''Формирует и возвращает, учитывая интервалы, список, содержащий числа, из строки вида - "1-5, 3, 2"''' + '''Формирует и возвращает, учитывая интервалы, список из целых чисел из строки вида + "1-5, 3, 2" --> [1, 2, 3, 4, 5, 3, 2]''' if self.number_of_pages is None: return None result = list() @@ -63,7 +63,8 @@ def flatten_pages(self) -> list[int] | None: @property def sheets_count(self) -> int | None: '''Возвращает, учитывая интервалы, количество чисел, полученных из строки вида - "1-5, 3, 2"''' + "1-5, 3, 2" --> 7 + P.S. 1, 2, 3, 4, 5, 3, 2 -- 7 чисел''' if self.number_of_pages is None: return None if not self.flatten_pages: diff --git a/print_service/routes/exc_handlers.py b/print_service/routes/exc_handlers.py index 42f6bab..63d286e 100644 --- a/print_service/routes/exc_handlers.py +++ b/print_service/routes/exc_handlers.py @@ -46,7 +46,7 @@ async def invalid_format(req: starlette.requests.Request, exc: TooManyPages): @app.exception_handler(TerminalQRNotFound) -async def terminal_not_found(req: starlette.requests.Request, exc: TerminalQRNotFound): +async def terminal_not_found_by_qr(req: starlette.requests.Request, exc: TerminalQRNotFound): return JSONResponse( content=StatusResponseModel(status="Error", message=f"Terminal not found by QR").dict(), status_code=400, @@ -54,7 +54,7 @@ async def terminal_not_found(req: starlette.requests.Request, exc: TerminalQRNot @app.exception_handler(TerminalTokenNotFound) -async def terminal_not_found(req: starlette.requests.Request, exc: TerminalTokenNotFound): +async def terminal_not_found_by_token(req: starlette.requests.Request, exc: TerminalTokenNotFound): return JSONResponse( content=StatusResponseModel(status="Error", message=f"Terminal not found by token").dict(), status_code=400, From 5a987ee243340be5c4824c3bf5983d33fa148b71 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 22 May 2023 20:00:15 +0300 Subject: [PATCH 11/13] Print-pages limit. Fixes. --- print_service/models/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/print_service/models/__init__.py b/print_service/models/__init__.py index e3af743..0d6538b 100644 --- a/print_service/models/__init__.py +++ b/print_service/models/__init__.py @@ -48,7 +48,7 @@ class File(Model): @property def flatten_pages(self) -> list[int] | None: - '''Формирует и возвращает, учитывая интервалы, список из целых чисел из строки вида + '''Возвращает расширенный список из элементов списков внутренних целочисленных точек переданного множества отрезков "1-5, 3, 2" --> [1, 2, 3, 4, 5, 3, 2]''' if self.number_of_pages is None: return None @@ -62,7 +62,7 @@ def flatten_pages(self) -> list[int] | None: @property def sheets_count(self) -> int | None: - '''Возвращает, учитывая интервалы, количество чисел, полученных из строки вида + '''Возвращает количество элементов списков внутренних целочисленных точек переданного множества отрезков "1-5, 3, 2" --> 7 P.S. 1, 2, 3, 4, 5, 3, 2 -- 7 чисел''' if self.number_of_pages is None: From 30287c5d826321590a2c62ae3b6275bb87b00e76 Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 22 May 2023 20:31:50 +0300 Subject: [PATCH 12/13] Print-pages limit. Fixes. --- print_service/exceptions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/print_service/exceptions.py b/print_service/exceptions.py index 3a37e98..6025840 100644 --- a/print_service/exceptions.py +++ b/print_service/exceptions.py @@ -5,8 +5,7 @@ class ObjectNotFound(Exception): - def __init__(self): - pass + pass class TerminalTokenNotFound(ObjectNotFound): From 950e9efd590a88b00c966b8da69df9893488e37e Mon Sep 17 00:00:00 2001 From: Artem Morozov Date: Mon, 22 May 2023 20:35:51 +0300 Subject: [PATCH 13/13] Print-pages limit. Fixes. --- print_service/exceptions.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/print_service/exceptions.py b/print_service/exceptions.py index 6025840..99ed16a 100644 --- a/print_service/exceptions.py +++ b/print_service/exceptions.py @@ -9,13 +9,11 @@ class ObjectNotFound(Exception): class TerminalTokenNotFound(ObjectNotFound): - def __init__(self): - pass + pass class TerminalQRNotFound(ObjectNotFound): - def __init__(self): - pass + pass class PINNotFound(ObjectNotFound): @@ -24,8 +22,7 @@ def __init__(self, pin: str): class UserNotFound(ObjectNotFound): - def __init__(self): - pass + pass class FileNotFound(ObjectNotFound):