From 6496abf30753b815f0120bbecbca1b9dbf55c126 Mon Sep 17 00:00:00 2001 From: idris nacer Date: Mon, 29 Mar 2021 09:21:02 +0100 Subject: [PATCH 1/2] invoke new_pic_inline from current_rendering_part invoke new_pic_inline from current_rendering_part (header, document body or footer), so the image relationship gets created correctly Remove white spaces --- docxtpl/__init__.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index b5a372f..81f1330 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -208,14 +208,18 @@ class DocxTemplate(object): return src_xml - def render_xml(self, src_xml, context, jinja_env=None): + current_rendering_part = None + + def render_xml(self, src_xml, part, context, jinja_env=None): src_xml = src_xml.replace(r'', '\n') try: + self.current_rendering_part = part if jinja_env: template = jinja_env.from_string(src_xml) else: template = Template(src_xml) dst_xml = template.render(context) + self.current_rendering_part = None except TemplateError as exc: if hasattr(exc, 'lineno') and exc.lineno is not None: line_number = max(exc.lineno - 4, 0) @@ -266,7 +270,7 @@ class DocxTemplate(object): def build_xml(self, context, jinja_env=None): xml = self.get_xml() xml = self.patch_xml(xml) - xml = self.render_xml(xml, context, jinja_env) + xml = self.render_xml(xml, self.docx._part, context, jinja_env) return xml def map_tree(self, tree): @@ -274,10 +278,13 @@ class DocxTemplate(object): body = root.body root.replace(body, tree) - def get_headers_footers_xml(self, uri): + def get_headers_footers(self, uri): for relKey, val in self.docx._part._rels.items(): if (val.reltype == uri) and (val.target_part.blob): - yield relKey, self.xml_to_string(parse_xml(val.target_part.blob)) + yield relKey, val.target_part + + def get_part_xml(self, part): + return self.xml_to_string(parse_xml(part.blob)) def get_headers_footers_encoding(self, xml): m = re.match(r'<\?xml[^\?]+\bencoding="([^"]+)"', xml, re.I) @@ -286,10 +293,11 @@ class DocxTemplate(object): return 'utf-8' def build_headers_footers_xml(self, context, uri, jinja_env=None): - for relKey, xml in self.get_headers_footers_xml(uri): + for relKey, part in self.get_headers_footers(uri): + xml = self.get_part_xml(part) encoding = self.get_headers_footers_encoding(xml) xml = self.patch_xml(xml) - xml = self.render_xml(xml, context, jinja_env) + xml = self.render_xml(xml, part, context, jinja_env) yield relKey, xml.encode(encoding) def map_headers_footers_xml(self, relKey, xml): @@ -636,7 +644,8 @@ class DocxTemplate(object): xml = self.get_xml() xml = self.patch_xml(xml) for uri in [self.HEADER_URI, self.FOOTER_URI]: - for relKey, _xml in self.get_headers_footers_xml(uri): + for relKey, part in self.get_headers_footers(uri): + _xml = self.get_part_xml(part) xml += self.patch_xml(_xml) if jinja_env: env = jinja_env @@ -806,7 +815,7 @@ class InlineImage(object): self.width, self.height = width, height def _insert_image(self): - pic = self.tpl.docx._part.new_pic_inline( + pic = self.tpl.current_rendering_part.new_pic_inline( self.image_descriptor, self.width, self.height From 30578cf88c0ad6d74860333ba4051a0e50d8ad67 Mon Sep 17 00:00:00 2001 From: Eric Lapouyade Date: Tue, 6 Apr 2021 09:46:57 +0200 Subject: [PATCH 2/2] InlineImage now possible in header/footer --- CHANGES.rst | 4 ++++ docxtpl/__init__.py | 12 +++++------ tests/header_footer_inline_image.py | 19 ++++++++++++++++++ .../header_footer_inline_image_tpl.docx | Bin 0 -> 16326 bytes 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 tests/header_footer_inline_image.py create mode 100644 tests/templates/header_footer_inline_image_tpl.docx diff --git a/CHANGES.rst b/CHANGES.rst index c5dd815..e7fcb37 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,7 @@ +0.11.4 (2021-04-06) +------------------- +- It is now possible to put InlineImage in header/footer + 0.11.2 (2020-11-09) ------------------- - fix #323 diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index 81f1330..734e2d5 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -4,7 +4,7 @@ Created : 2015-03-12 @author: Eric Lapouyade """ -__version__ = '0.11.3' +__version__ = '0.11.4' import functools import io @@ -41,6 +41,7 @@ class DocxTemplate(object): self.zipname_to_replace = {} self.pic_to_replace = {} self.pic_map = {} + self.current_rendering_part = None def __getattr__(self, name): return getattr(self.docx, name) @@ -208,9 +209,7 @@ class DocxTemplate(object): return src_xml - current_rendering_part = None - - def render_xml(self, src_xml, part, context, jinja_env=None): + def render_xml_part(self, src_xml, part, context, jinja_env=None): src_xml = src_xml.replace(r'', '\n') try: self.current_rendering_part = part @@ -219,7 +218,6 @@ class DocxTemplate(object): else: template = Template(src_xml) dst_xml = template.render(context) - self.current_rendering_part = None except TemplateError as exc: if hasattr(exc, 'lineno') and exc.lineno is not None: line_number = max(exc.lineno - 4, 0) @@ -270,7 +268,7 @@ class DocxTemplate(object): def build_xml(self, context, jinja_env=None): xml = self.get_xml() xml = self.patch_xml(xml) - xml = self.render_xml(xml, self.docx._part, context, jinja_env) + xml = self.render_xml_part(xml, self.docx._part, context, jinja_env) return xml def map_tree(self, tree): @@ -297,7 +295,7 @@ class DocxTemplate(object): xml = self.get_part_xml(part) encoding = self.get_headers_footers_encoding(xml) xml = self.patch_xml(xml) - xml = self.render_xml(xml, part, context, jinja_env) + xml = self.render_xml_part(xml, part, context, jinja_env) yield relKey, xml.encode(encoding) def map_headers_footers_xml(self, relKey, xml): diff --git a/tests/header_footer_inline_image.py b/tests/header_footer_inline_image.py new file mode 100644 index 0000000..b2303d0 --- /dev/null +++ b/tests/header_footer_inline_image.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +''' +Created : 2021-04-06 + +@author: Eric Lapouyade +''' + +from docxtpl import DocxTemplate, InlineImage + +# for height and width you have to use millimeters (Mm), inches or points(Pt) class : +from docx.shared import Mm + +tpl = DocxTemplate('templates/header_footer_inline_image_tpl.docx') + +context = { + 'inline_image': InlineImage(tpl, 'templates/django.png', height=Mm(10)) +} +tpl.render(context) +tpl.save('output/header_footer_inline_image.docx') diff --git a/tests/templates/header_footer_inline_image_tpl.docx b/tests/templates/header_footer_inline_image_tpl.docx new file mode 100644 index 0000000000000000000000000000000000000000..87d0cb44745d98659c3bb3c2daa1c57da126da2a GIT binary patch literal 16326 zcmeHuWmH{B)9%5Y;2PXrf(Ca8?(XjH8Z5ZGySpR-f;$9vcL?ro_hjCgcV;qk?^^fw z_wB{0&FSu^ww$W!>aHp|Nic9U03-k!000mHmMzSgV?h7_S||Vj6#xyYDP(KoWNhQ4 ztK@EH?5IueW^F~72M$V^0{{h%|KH<(@Ed4Il$PyggbzLyfBHnN+F-KfhotcZj6f`< zC+2H#&kFHHVb9~k?bkyUA}l9^D}~a==QdfZ8SJRJStH312~X7;fmKs%j{QWJdjD1_ z0*^UbNy-eAJ}%06NEF=Y(XrquX}<*dMoEZtl3?7?_>2H_s#}n^A|D7U`8^`v;RkwQ zzFSXzenC%OCE_^JFYFZU=A!KF(sOAq8e^3Jk5_Ziq)^d;KqbPWgHXs|$b8tGT;kkT zY8sJn#G8a5WAqu%4STYxDfi5q6|N*q4+)9xQozu?FZp`mpkK=Ts=W&+W{{-IEv=pw zyh2gP%hHTzN2Y05x+K_)2@hOt)97aP&lDz@TsO)PZI}!Q!AZk^nGX-d1>1k+l0W>s z1V)VR1X81DBcj&1b+;dH|N$N(qOi3Xfw2Dw|O30)siP=Nc{^-fd{j(`d3 z0@W6>Ii*{s86DIdSLm6$6;(5Jjh4!>CBUqupYN?_dt3Q|4u{1(OBAX1#eGgQHd+bT zs+Z?nBri}1Uthrha(~lg{8*eXr@$T=prXP7HCfle*vgTC{wMuk4gMdjwtso_invY- zpa%1w20RB$w8}4bV&%&)7>+MtEkHqQN=TtD&0Ea9Jaf;_gKF>Viw#ds#gBV9W{5hk zCupDHBq<|=wZhEa>vU^AescpP27N1Ja+|f=giqhSF?k*$k)Rq12vvEY8`ti35-P_Tt{qAX=DQm{5jCFB2^k zjhDT!U2HzKQzG>S-3?pZ3~hl+;C%K^{dnSl*_;If0FDs>0A%1xakX_YVlc8bbhZXg zcR%O3ie$;?B@TGMQ@ATWETHMSkNq@JU>0v5+YKr(b)s!Z6Dp^PLb}t~?nA|AV9N8( zj(ddYv+xC~h(g50{V>^B1!`=V1KXF0fkwJ6lq`kM*-Py{eX@#63OMy>rWvtK-ef~B zb$3^DdyWYg+bO6;bo`9ynIgxhLMMz)iiMF8mh7zEF_>yyo2w9#NrqPk(8!K0ONs&$xMBB?Eejfa6b1_Gv%xP z^gNS}Gk+%`lG_YXP`7xsl?`{qwzEXMK54sT8X}4F5Y;IL2WH?$yME&+R`{LO!P+Np zG+6+K+7xD*yf;J4w+ALBxaWGm@eLPhl=o zvN4_|mcN^z&h&N>9OL@P@YS^lLT;N$SnV;l%H2}T;I+2ynf_j$h2?>1vDsYE)Dh3k zPdU-|QM@dgvz|u}q?JlG?>fsqRG0Y-I&8t;qah4F#a6uB9j$uXAXQY4Vg2EvYpUEG zHU>Pl1Eo6Gp>JanK^33H@*UiWZu)}6^~VM1st^0oO~=gwj5@t*Hi|TL-ThLyg9q4j z-SaNZZfFdx_Uj(EZnn&k$>*xCh_54W$nDQ?@TH&57AncolN@T-MKPi)+f0!BegxJx zJ;z%}LPI8Z0HhKeQrl<;klah$!AiXR_KoTic&&F?UGXyB&bUWGca!Z(QqWih`Q$*H?GC^+0A!v{>=zb z?ICnC0?mUM1OV_B01fh+5%|wc`Bzi$$E*ng^m~D$|7RZ+36em+4=M1c-#6g8S-|gJ zBEtY(stS#wI=9L#Y$bMsG0@&`F+&XC1=FFBXs)IE0*~=S zYP}QDpNn`f3BEx#57d!0I=)fJa3jYZ3|SG+)R(b)rdb~h$pnowB{nl=N%C6y z$iDL#(#R-5;Z*d8d&pr55+ag!tBnB%HBn$o3N(Tpj0-5ocXvu(IlftL;Y`AE220bK21?ij__Sx@2r{000Vb#BUO3Vr%PUW9ww> z_;cQwP8zgXVnhl)g?K;&Jw+tb)FJLcT;`y2pozNy!3wJj4S^FMs#|L-xDmA>q$z$N z3>|*8H{p1DdGgYua4Mcq1jS4xNUPLTGFaDtz#bM~G;O`rBTGs+o$b^R*EI;y1RP!;$)n~wh z^7&`W@XdLnoI0C&IVKxqHKIsH9tvhS6c{qq_&S3~ml4SYnT)IykBNj1=;Be~k_N_A z(-a&(OZmzhBJJ3c(AJd&cbJ^d1daw05NGZq^zTU^d4u9QuD(GOFH-YaF@!VJ} zWSVHAgqAuW!4Bs=4c`N#tAxH=a$Ti5bH_c76&}AKV_um2v1cZ0jXbpCy$-9A__9J$ z%4hn07(_xd9V;s9MvL+)O(Wcj*^`Z+)c|UF%BI{CJ$rk*Nf5x6`52xowo6;7fEtR% zEC{l+Q)h;PhFX{y9E0QsE5uNJw&7| zLz&h1ifQ-}f<3`hWWvXt0P|H)4Wnhr+O5Uwj<3sMqBUA@+Wf}|!M{o}i8x+pDo~Oc zfs*`R2g=yS=wAid{{)fDJraq_?yz8>QhX6gk8+Wmn4XYo*yj$@Gt?#gp)@#;s5?gF)k4e51HC8SiwTFr-cU!Ew8Hd9&*7@5Kx$yeb>-}Z-x9s1}} z@xX>@H$NouQFQeOPfO*97$VQ1+NO;NGxP1)Riwe#WgF~V%H;O~@<@;(lI9X6Of{>n zw21R}=uvMUCr~0Ck+{~uV|iwi@HIuFWyeAOV`CoS)B1T|*3?lS+~O&_5p~7Jkq2 z!~SjoZ?b9aCz4|U?UkV=okBv7nidtGMx5+ZB%-x17P*>=pZsv3OyflGDmf?`7on&R zHx^q&)guU7Z(7E=;YEo6dCR(e7K;j%HGAoRe#1@wN-dktoIqC-eXsoFuA%Y5#02kg z6e7eD#!LRxYGMuZiPj1eA1$qZJ(veh93kYrA9gMeoX?1w61?yt>H$Z^-b4xKP8A2D zB^d5ah2d!=Cm5Coo`J@azRc5ilEz1^#g}nrMY>4usGDhw++}U3Dm~?WUmwzuy$JUO zLx{%E_&alog1%}hHSobB0bY+@#IF=qKslE7xY8mzQ$4=!9X9k-AY@U}kF1>Lb!sBT z3F_sB7?L>Z%gT8dfj^gi-#yLXu`$-!yy|}KsPOdz*_b3BbkX60$Md+8^$!fw(&MNn z?n7#fr_z;SN~sQsl)x`Zg8K*=gvRto69xBfqZxA?^^;=dT+;)RqQ{Dy1;a4C^$xEJ zq#%RY~M{y;f?13LYA;djd;BeV&32Iyseg^)*f-=!Ci9GByhN^6@C&b0S>FS9Qz((j7C{{X zOW8yF7$S_Ept*Q+E2-Ts?=8>Ty-`(Fw)tj7jZ$De(HXtgx*o6=;w@@WJEngaePxa{%?;?UW?1<)48h}h{n_x`id;H!1Aw+RBrIE3-~ zOEmfKP4m6XloR<^Gzjy{gb!v&@FYg7#VnE~o;?a=QdvsGs2fq~*f}s$QhPa*(abNE z=?O(H%&9aWX=BKvNr~RGO3g7ahSU_}ghk9H@pDZq1o9SecS%rCQ+h!s#X&UrS{~XK zLgBtXDZ33&-`i@Db89JlcS_<+;9&CXObrX2&$81Y0A1{FV?RM;r8xsEXqZ zu8+{P!_HNZ?voNX4uq*9`Y=&TtfI=}5bvgGKO!h2 zGdrd}?Fv6(=!sN+149dYtL7S5>I}TMb>-@I(P&$b$+248({6o$-nud5q zjg~&61Ft$yuGx8e0qX7#ECLffkBqV6NywQ}Mtr!?A5!T{;;R&qGz5ld`tB)4mtOwV zsZ#1rG5unDWlfBG^)1^wJNZh99TE-|7S4~%T#CL?jeF9@9UuGAOP zx1J}(PW@xkgEmLBjhBpeI4ZYZ`Xp()pg0MiMdt%1(~1YOcB7wvF#M}#RoTXYUIRUA zd0YSh{SVD@GBdU|X84W%rd~(tlD4=aZ`(=E@kBjspF@txWjxZJ*Qyf-6~&(eLz#!JrAmKA_)?9WAcb_E#=}%TGV7XZD}I z`W!`gpHJFz+?-3a*mo{IgCIerA!1GN`O z-3pzeQ#9$(s*BBPX(&vMfuH&3ShF+eDWHRug($jS5^5$Zt+nP;FW3P^81|Vm#Ve&! z_t=0N?;4h=!jMYmIhsnCF;Gfe`U{)n!=1E9hBIBw4%-He%7@?}_8coU&5r71+{WXw z-@fQhw>PfXu+x46G4AdIZS&O6m#;sEL}N;W#~gp3H8mhb1U6d5v2h5{%_i-DSEe>n z70oU&Zo=5&(sBaP^AAUtj=?E5^7HO!v|q+VvjlOAU+P+FVLE~4 zu?Ac)WHL2H_BmYCb>nmWDLWIjc60`wXGwk->!3RLE4666AwA;qP-hlsnjPAs>fvz3 z(yEOWd6=RSKQQP;MV5K{KG826H{H32Qf*(5(pj4c)3V-T1-|`6N(8&l!%NyD;F7K| zT-`E_sde#D@C%iN{(+N3^i8Ez8nSjSQ;+eH0@9}Sy~!i?x@A;?UH!z zkMW>y!JG`lu6H$f8ywCDQt>4r&-{o)B20^0L#5zfXoSaz5INLwPBatLHhkQz*9vkA zCus$)M#ZFgoBGy#w(%ZHx>8*w8d4d|0{gu#EHHmFd zTBn4~yYw)~w7)p+44`-hNAZ_?G@cL<6ieFzK2c)zQJuv%gXm+BOOL5GQ8Cc%x(BS7 zt5Y$s&ZES_mb%nLFjLnjqShJ}`8MiI`EcNZycT<_&J_1k+!Ns^3PQtdoc zxOZQ%Wt|!8{XM1@GES<^!>I1xF&C!v*``vxcifn7#`ux@rXTPzc66esKPZgDDVHVB zN42A~a{#mzDIrJ&hUwX{em3##=z~gMHyT=o&@?YXY|i+;5-Ie8VpArAzRF;Wfetoj z{UF*96CS#7KS3=q)wg-b0lIf~E_}{^eugYO* zSf0De^|qX-zipPY9jd`?mR%?6Hd1Nv#=Q9VNe7LY>@DH1efmMd#wkxM-s8B?3AV5B zUDSJ=Q}cU)xk_rF?;#c|T&L1WMtyj%eeh@&e)4X{vw?l}>5-SweRGN!qG~dRWP{Sz zfs}==cA0O!P)4U6BIZ2_EH|-+UoAdUykY{frSgbY9)MxRf3Asbirk@b!2tlBzpf-4 zjh&p#ZA^b#5*MgwMjx;t`BYE8`dut%Xo-Us4C8}*%&K%*I;c@DY~u_Cu{7kW!&8%) zd0nkVMV&94Ik|y2x;JUV_M{&j*)!EZxKR`DT9}66y&nbC`zHrl7muDs)3_eN7YJ4e zqno-NysdTOUGsTe86iqkqmqjU%h6*l?44eqQZCM-2*)cD_t|7M0oZ)a5${y7;tA_f zRBVALW>p}iK$jO|xO(o{H@llQ2bbi6O^y?^8)W~GUf@+v1ab0G5#$!WHcPrCBE+QF zmrr2_!DL77T9A|!>63uakx91jI!AQVQ0MWf!?)Z1jaC9h_?N(91dC2MS~AiQ6*m4Z zkNydoy!cbu^%kzYT+qu7_VUYtty|>4YUnsnzV>LtWqUV0_fest+jCM1{7GG_7%$qC zcc7tbV#rGz+p#wkaWk3@%YwJ0nBon1(_|?a`zuNIA1`3LJ_^4fR0TuLdW2vCF_0gCG1SV) zkqj)+DBz|@B6iVZs^YPtyn-yswRMY$&rD^|^zJ9~R=;-JyPmyNoY5ze<9VE;SIv|? z_;5>_)EncLih7b_A#53|b|s6yg{&XkroO1QI=5g6t+O1UgdyL$XEln8*d08>VTMET zot}9hVKDp>uc(wfjSz6wia|y%=grsfyD* z{8Ui(X55XcHWviB&_;TlC%=Q{7}s_4Lz_BDYU+8$jJCCYwa?(kX2}|D8_K#S^p zM_x>EDRK`5hs{Piv2WAaC;eUed_u?kbE6-l0kn2v z0!bsu!?ap`;q5J=4Fr8(UjNnOB;cW63IO(u06(YzN`RrWqm!+*nza>!xs$Q=Z~i7> z9w~q_hY&d6|9w-oFS5cOgxTcWd(%A&M!y4d zWK)<>q5Is;)w^7f8fZ$7lA|6i@#Q1z?&{l_f+j=lj~Q?n)ka?eQ#UxGC>T3?_$_C8 zPdC{g$3Ex_58o+#6U*pv)Y;w0wc+vV)h?!QLAARF-q}B`q{Fga{|2x}8Mp(D^^a$h zbFj5@{Qr8ujF{h|f5E2#Z2=Q2&UNJ4Dw_%KO~w!Bb5!T-QG~3ZmZ)$IPkBFOHgCyn z#>cb~%=Eu`mz#bez$HnvX5yESST*I6bM|uMPs2|HyA(R8F4Fm)gDw42Gu$T`VdT8a zgSUwSrMZecjqyRB4{zPj0DpHU6dWMJ;R^k6Z#w>&~7OtWRep!H$xfe{Hr z4TaP=*VmcPbJ+?@{eaqh(2?xT)QYH!6IFBMw_% zk^4_ehq!8-J|N<2Ch?gR&9)eO9?dsiZs55yn}!6^R!9hL^v|z~4OwpYg8C6cl);1{ z5LdmuF_0vE6a%dI0;CmsWZStZ?9T#BIJfo}j2?FNP{vudktGR6$=6P*Z&zjfzY&@X z8)Qw^55kR5v_Cz~wLe{5@iOQbq(Onk?4HJ-S=CX8T|YiQb8AfmZrk3a6&dWsnZi)@ z%pK|T5iJ-tt-`t2kwa+Kq@XiAeu9FcK#d#>mb-Hp6nyyj$yjhoaN*RH1w%M%m*(@R z<>D05BI;P4bDvP!Uf!gH);UVoB;-3D(44>^?6LbgHxlZ6$pX19FOM8vvU5ng2(Y)H z9TMW%_7PvwY8hyy5yR~=;)A=11GZGKz+x2NZhoZ~dx;ysA=`Ld`jlX5gbWvVCQq2g zDW`X@nxOKcNYJ~%7w#A7cK4B90vogGDQ(60q5P%jMf-zU%C9pBI! za-({8FKn-Hwc5*|x^(A-6!m@F4->h13@ci5z_I@P>QZ@C$sYJks&_AyvW;38Uz_KX z6P+hqEj!sHMRuV8Z8ZJD?)K1=E~`};&xCP%p0G=5rxR{&ShV2V58=xt*6j7mWi9Vv zo%0qfGk^SOlyQ2}pimHWi$u+An+;tBe$aM(-HDS#ubNPZxe;cGY@0l%Eveolivs*kP?6ywuQI@~9hymD7P7v23 zTUvZww@yw*SH8A*+5($KamFf(G&(C|)HNbh7UC|6cOVd8AGotb6*?8%3kb5_UYYF{ z#^Ez6j}<{}PBg@noVJh%hfaHQGZ^_}o*CB|y)hQOoPa3ae}i+$iXe^#lO?7n8qQqb z5F#mM>Ll?lEqK~g?=fIVicx&nXoHAtZo3mVyeM{Ww>(tmeGqw$$ji4lVtsu7_eA=A z{g{!cw$I&SNzt}6FfjB(97S1b+0TI~29aY3XeM43IgDHHz=E)|v9NeAXN1#sOAA>> z6a&oDie1V#r&L>h{xiiQdt79`wRD_?UVE@PqTcUx*Vr-vTHiFy8s1- zo^46yMOIjR9dJ5m+~NT+0)Rednay>^Y4{bY_G?f#k8&=)}sthG@O;c7OJn?9c9R^71oQcb`2 zQd>8gDBlgAevoRFj~T<=G1&k9BGCWdApm&(=U{E*b#;eNspe2*)U_|tYul9S^y*zW65>ymWP-V2@4*t+WilmvMqn`)h-V!WzuAOw zN1uY)+yFHfX#q~ZFFpaqGeXPwF&8+_NA`8v8(y6ET-t6lX-4<7$)9NQNTWD!ovf|j ztvlsM(1iB?__RR%^`W)@hyQ9XX#ows7)$;1vJFk$f&2AVwnn`2jorD& zQL-+LzU-LLuhenlnZbk_gi zX%o3EVv5j}g74{5o>K9j!cRr4_@uZU-C&_FP+@T{Pz5*}i(SDS(L8r<-$n1U%-pA$ z(teg@S5!O};Mub!tFAivVk3$0x<6N$qEpC;@Sd}N^t^;&RS1$vQ>ITWMgk%up2nt%{v+$F<5h{+yOMlcAiL5>KNPALS~Bhz6g7<9vtE9i-tD;O3oM+EVob|4}M`ai?^ zn_6dFp@E1Dx!hJDqF3aveS+W`B}gBC4h@9;o*4*BWtRJU zlf`v_uuxm4G)znG5Pjkt+!M`^B$%i`!z& zJ+XYl+7HaVt9`XYj9dJ~=GBauLS!Ud%{6V4@ymQTY)dG=k45MLh_vHh@d4%Ig-SC+W?)PtQH3 zCFx;t9~?R*(jSVc_Sk_(JT_x@yIC-u9#$ea&i8nGH|RraeyuiTgVzVUz3va*uqWi& zvp(GVc@g;Tbs)+GvLj0ad8)<*d#ukj zG%_P+qNdscHzU*0jDwP)g}``H6-;TWDwL33uHPTx%u1@KeZ0!K1S3-giRB7xt}iD7 zg6t@}fx~O6g25}w#SjNnB3gjW3o}SNyA~Wxe|8ad4$c6!PAozkTv&yhnsAH;%~XXz zXJ=ykfQ&hsaP*e75#&d!f=hT+%gZV0RP(v5QntwTgNbbT+2HLn>-B%c&|%L;EyM}f zeNW1%w#eS9BbzdJ>5@BLfDu|TqsVzO?_I~U6wBqY5(BbNrgLsu)Gl!WUg4|N;DLqK z=jp>gh>PSr=c_a&g<6Gv?gSc#uA{d zRw=6$uobp*Wn=2}4i?_uJ3G%euAVYsFTEoJgP>LO&~kll6AO`CxlQs!#4$owASfet z(7%-Nr{`2e&yIXE?>_jd0(X=2HHP>HRV4}xm8WKvLR@8ta{4iSKIH^)RgxwufsNwA zm8?f;ZCS;{yHYuWSF*@0*@E|J)yJRuoYa*(i=hsjp)?;cXVM=lZc-1vRr)=<=$BP{ z46;jxtDauW$)c-iJb!~9PUy=^&cm~=%5ubBTD}4OoG^{HPrX9({zE?IMag0u^c7~Q zBO%Q~;mi`vB-w<@4YgC?KoaSg?C4l^S-|xNZ{jTFJ;Il{{y~{mh3&LGgOc}I`$Tgb zqD@Vl+baUsH8D=byC2a3BiFA{X$-U1ufa}O`l;b+N_fjI{8o!rOCSzozAxJ2Ip*VZ z>{i$87_LVbL6sY|`cC~NAreg`5GA2H-yu*x;4Wrw1i}=%v{-Wqo*)q8loX0-br0EH z(F7%Vv4Thb5Txgd3HZ>clld{U7Q=-<&Se2hS{{vyCKWmFnQ;W*Y#(Lt2ubSR_i&OgA^TtEub96wj9AM<&@j)>sf_8I z#0gOA?zKwd$E}fsm&)uPp&o`WOzb!MSjdT;JrFCrrZ1$vSE3iqU0ZqRUnuZ!Pm~KQ zX>LYB9paYpYV+Z0y(45VF%D98p-{?mXnCJla?fv8Kik~KRyycd=rEWc*Yj}9+ybFi z?JebVs?Mx_@@;Y{ZG69Bxgw30U6-Ytyj;Z$=hex@0e(?1NlQCM1$QTZ4%E@UlBC)k zMPz);h%$OXp>0*QjtUngC3MFzC>XV=f+NPhD#Su?jQu#LhTBfx+yCgmh>A_N zV`)4gM0LY&AkV}5eJL+!2DhLmHlcR2)UFvVJwcF&Y#)I`L78NdB$2BIrjIfjp5e0w6+*%Y!pqV1 z?OBR_*{Ks#=-Uxd;`0SW?2Z*B`5fK}t~92veiD3oUJz2OM-SNb`9z$TlT6NhrXDU* z-W$uR-y!(Nqf;^ta$32Zww=zKZ?I;D>UwMw&RI?Iys(-UyQk?mzisM<6JeXS>4%za;Xn5hLg{s?5P-QG#K8U7zhoiVI4S8HSQ-Bo^^TXfO=m>%Tcfz< zBW!2K0%eK(K;39r(0ZhA;p=B8RTE~tO_FNz+%Y+ zJGg@;7wfwe2@AQTA-W~dD-!BGI;?8i6=khR#8n@@LF!8|G3uBflao^aK;MSjrYQKu z$Jb0GQaC?14&kl&im6#|pRi$7p?1g>g?B-?`08}*Di6Zl4Is$+He&}F<0)0)WJP4C$>fmj8niSG}mi@SFU;u@i7GE4Vd1u~A?oHZt zKq(rR{)q^s#r6KsCFFZQv@`Mv=L^#T=dxoT>)mJ#yPe6VIyFeA>;y!6gu#PJ5) zu?WHFcdt0)!>0I%ub0`_P3i@&{m|t#n{dSVa)Fkx#l-iwmB`N$!lGj$Jp`d4Md5Bn zuOau!NMNnHpAvFyn=ZyjG-$!z$TnWXftfq~n93Qut&jHC)s zJ^g_KgbYlY1ZGP9w)@0jXzTEs>;UTv{x?$+Xt%uLv~B$v(SlEtkN9F%h2XFjp!MqB zRI{iP4=1g#9?PdsOg1QQuf0jhGcift;ojT#L>w`JQg`=cRGFq0)8~(Y3Y*a?k&ap& zZhH0OJ}lX6C_~>afe1J0eb(-C8nOVhEt=KK0314#8!Hw$HaN=^V`+Ydkgy&{E~BZk zBq=?NG6`TcUULHDAT|mk;}|N<|BCtG!IGCBS1(`cT7(0hp!5ftby(ty})Hi0yd_CF2y%tzAm}P6|U`j?Ah2H_rjZ`-@tq@?? zZFjS$)p@gYEy~ppXT_i0SpD7M$_}+9-NjzX9>~EwCtfRvu|v*N@F-qeLB7tB$@uPZ zDf4dbB|Aigg#?Dm;(Mbc>&MA#Cd5?pE-SyPQ$~Zlu!`o&lJlk}kxJzMSad@{6WTmf zRs8pDJy(029tWT>4grM`>94}5Z)f+@j{UDJ0tFFxWGD>F0JC<#k(|GgKdGF;hgH&4 zEkWPx$X8J0(7Yk9wX+&_L4NjRLkJ|axodcLh&K|2a2P#nbc&Vd;*vO4B$AbzC}XZ! zeIew|-ZWaD5~$q85nlcj$fSEY3^xz4$3z;*L;{1W>K-4b%Zy1Ew7hpgP)eftVc+uxydgg5)1!*2aH8cU9hsO2$%Z zyp$N*O(;`&@;;6<+v{!7@N*r>;|Iu4=m2nq+{QoOPGD}+guI7d^Gd})@+l*zoA>?97DkrWFh|M@+5>kf4 zY8K{eZM#J@PCqC^UmxXLT7yKind*zpa!M`au<#IgWgvYXpDn<`diy%*(Iz_Zus^Tt ziFx+)etPDYuoA{5ylc*Y*7Y{COS%Uh*$he!l{LEqMA9dI0$^@oe$!30>k{@?Y?ulT<^v45fg08$nJ;2$pSukgRS9e;(_vi$}AyA$#& m`tOs$U(xEEfBgmiZEBE{gaE4RPtO|}AP-EM(dGL2?f(E83Nv>A literal 0 HcmV?d00001