From fdce80873b901d25c3e79d81b96d4e3c1ae2d98d Mon Sep 17 00:00:00 2001 From: Simo Tuomisto Date: Thu, 27 Nov 2025 11:25:36 +0200 Subject: [PATCH] dependencies: Updates for 2025 run --- content/dependencies.rst | 312 ++++++++++-------- .../img/dependencies/conda-ecosystem.graphml | 207 ++++++++++++ content/img/dependencies/conda-ecosystem.png | Bin 0 -> 25144 bytes 3 files changed, 387 insertions(+), 132 deletions(-) create mode 100644 content/img/dependencies/conda-ecosystem.graphml create mode 100644 content/img/dependencies/conda-ecosystem.png diff --git a/content/dependencies.rst b/content/dependencies.rst index 0081116f..9097e571 100644 --- a/content/dependencies.rst +++ b/content/dependencies.rst @@ -6,7 +6,7 @@ Dependency management .. questions:: - Do you expect your code to work in one year? Five? What if it - uses ``numpy`` or ``tensorflow`` or ``random-github-package`` ? + uses ``numpy`` or ``pytorch`` or ``random-github-package`` ? - How can my collaborators easily install my code with all the necessary dependencies? - How can I make it easy for my others (and me in future) to reproduce my results? - How can I work on two (or more) projects with different and conflicting dependencies? @@ -19,8 +19,8 @@ Dependency management - Simplify the use and reuse of scripts and projects -How do you track dependencies of your project? ----------------------------------------------- +What even is a dependency? +-------------------------- * **Dependency**: Reliance on a external component. In this case, a separately installed software package such as ``numpy``. @@ -52,26 +52,24 @@ PyPI (The Python Package Index) and conda ecosystem PyPI (The Python Package Index) and conda are popular packaging/dependency management tools: -- When you run ``pip install`` you typically install from `PyPI - `__, but you can also ``pip install`` from a GitHub - repository and similar. +- When you use ``pip`` or ``uv`` you typically install from `PyPI + `__, but you can also install packages from + source code provided in repositories in e.g. Github. -- When you run ``conda install`` you typically install from `Anaconda Cloud +- When you use ``conda`` you typically install from `Anaconda Cloud `__ where there are conda channels maintained by Anaconda Inc. and by various communities. - Why are there two ecosystems? .. admonition:: PyPI - - **Installation tool:** ``pip`` + - **Installation tool:** `pip `__, `uv `__ - **Summary:** PyPI is traditionally used for Python-only packages or for Python interfaces to external libraries. There are also packages that have bundled external libraries (such as numpy). - - **Amount of packages:** Huge number. Old versions are supported for - a long time. + - **Amount of packages:** Huge number. - **How libraries are handled:** If your code depends on external libraries or tools, these things need to be either included in the pip-package or provided via some other installation system (like @@ -84,14 +82,13 @@ Why are there two ecosystems? .. admonition:: Conda - - **Installation tool:** ``conda`` or ``mamba`` + - **Installation tool:** `conda `__, `mamba `__ - **Summary:** Conda aims to be a more general package distribution tool - and it tries to provide not only the Python packages, but also libraries - and tools needed by the Python packages. Most scientific software written - in Python uses external libraries to speed up calculations and installing - these libraries can often become complicated without conda. - - **Amount of packages:** Curated list of packages in defaults-channel, huge - number in community managed channels. Other packages can be installed via pip. + and it tries to provide not only the Python packages, but also other + libraries and tools needed by the Python packages. + - **Amount of packages:** Huge number in conda-forge and in other community + channels. Curated versions in licensed channels. Other packages can be + installed via pip. - **How libraries are handled:** Required libraries are installed as separate conda packages. - **Pros:** @@ -104,27 +101,39 @@ Why are there two ecosystems? Conda ecosystem explained ------------------------- -.. warning:: +.. figure:: img/dependencies/conda-ecosystem.png + :alt: Figure that shows non-free and free parts of the conda ecosystem. Non-free side has Anaconda Inc., Anaconda repository, Anaconda channels, Miniconda and Anaconda distribution. Free side has Community, conda-forge and Miniforge. + + Figure 1: Conda ecosystem visualized - Anaconda has recently changed its licensing terms, which affects its - use in a professional setting. This caused uproar among academia - and Anaconda modified their position in - `this article `__. +.. admonition:: Licensing and conda - Main points of the article are: + Conda was originally created by Anaconda Inc. and they provide their + own licensed packages. At the same time a big open-source community + provides most of the packages. Thus it is good to know what is free + and open source and what is under licenses. - - conda (installation tool) and community channels (e.g. conda-forge) - are free to use. - - Anaconda repository and **Anaconda's channels in the community repository** - are free for universities and companies with fewer than 200 employees. - Non-university research institutions and national laboratories need - licenses. - - Miniconda is free, when it does not download Anaconda's packages. - - Miniforge is not related to Anaconda, so it is free. + It is highly recommended to use Miniforge to create the environments + and to use conda-forge as the main channel for software. You can add + `nodefaults` to channel list to disable Anaconda's repositories. - For ease of use on sharing environment files, we recommend using - Miniforge to create the environments and using conda-forge as the main - channel that provides software. + **Free:** + - conda and mamba (installation tools) + - community channels (e.g. conda-forge) + - Miniforge + **Licensed:** + - Anaconda distribution + - Anaconda repository (`repo.anaconda.com `__) + - Anaconda's channels in the community repository (anaconda.org) + are free in some cases. + - Miniconda is free, when it does not download Anaconda's packages. + + All of these are licensed under Anaconda Inc. and free in some cases. See + `Academic Policy `__, + `Terms of Service `__ + and + `Non-profit & Research Policy `__ + for more information. - Package repositories: @@ -162,13 +171,10 @@ Conda ecosystem explained - Package managers: - - `conda `__ is a package and environment management system + - `conda `__ is a package and environment management system used by Anaconda. It is an open source project maintained by Anaconda Inc.. - - `mamba `__ is a drop in - replacement for conda. It used be much faster than conda due to better - dependency solver but nowadays conda - `also uses the same solver `__. - It still has some UI improvements. + - `mamba `__ is a drop in + replacement for conda with additional UI features. Exercise 2 ---------- @@ -202,16 +208,17 @@ An **environment** is a basically a folder that contains a Python interpreter and other Python packages in a folder structure similar to the operating system's folder structure. -These environments can be created by the -`venv-module `__ in base -Python, by a pip package called -`virtualenv `_ -or by conda/mamba. +These environments can be created by: + +- `venv `__-module in base Python +- `uv `__ +- `conda `__ / `mamba `__. +- pip package called `virtualenv `__ Using these environments is highly recommended because they solve the following problems: -- Installing environments won't modify system packages. +- Installing packages in environments won't modify system packages. - You can install specific versions of packages into them. @@ -268,6 +275,12 @@ Creating Python environments $ conda activate my-environment + or + + .. code-block:: console + + $ source activate my-environment + .. callout:: conda activate versus source activate ``conda activate`` will only work if you have run ``conda init`` @@ -318,11 +331,16 @@ Creating Python environments ``activate``. - **Linux/Mac OSX**: + .. code-block:: console $ source my-environment/bin/activate - - **Windows**: most likely you can find it in the Scripts folder. + - **Windows**: + + .. code-block:: console + + $ .venv\Scripts\activate Now the environment should be active. You can then install packages listed in ``requirements.txt`` with @@ -576,6 +594,106 @@ Exercise 4 Export the environment you previously created. +How to communicate the dependencies as part of a report/thesis/publication +-------------------------------------------------------------------------- + +Each notebook or script or project which depends on libraries should come with +either a ``requirements.txt`` or a ``environment.yml``, unless you are creating +and distributing this project as Python package (see next section). + +- Attach a ``requirements.txt`` or a ``environment.yml`` to your thesis. +- Even better: put ``requirements.txt`` or a ``environment.yml`` in your Git repository along your code. +- Even better: also binderize your analysis pipeline (more about that in a later session). + + +.. _version_pinning: + +Version pinning for package creators +------------------------------------ + +We will talk about packaging in a different session but when you create a library and package +projects, you express dependencies either in ``pyproject.toml`` (or ``setup.py``) +(PyPI) or ``meta.yaml`` (conda). + +These dependencies will then be used by either other libraries (who in turn +write their own ``setup.py`` or ``pyproject.toml`` or ``meta.yaml``) or by +people directly (filling out ``requirements.txt`` or a ``environment.yml``). + +Now as a library creator you have a difficult choice. You can either pin versions very +narrowly like here (example taken from ``setup.py``): + +.. code-block:: python + :emphasize-lines: 3-6 + + # ... + install_requires=[ + 'numpy==1.19.2', + 'matplotlib==3.3.2' + 'pandas==1.1.2' + 'scipy==1.5.2' + ] + # ... + +or you can define a range or keep them undefined like here (example taken from +``setup.py``): + +.. code-block:: python + :emphasize-lines: 3-6 + + # ... + install_requires=[ + 'numpy', + 'matplotlib' + 'pandas' + 'scipy' + ] + # ... + +Should we pin the versions here or not? + +- Pinning versions here would be good for reproducibility. + +- However pinning versions may make it difficult for this library to be used in a project alongside other + libraries with conflicting version dependencies. + +- Therefore **as library creator make the version requirements as wide as possible**. + + - Set minimum version when you know of a reason: ``>=2.1`` + + - Sometimes set maximum version to next major version (``<4``) (when + you currently use ``3.x.y``) when you expect issues with next + major version. + +- As the "end consumer" of libraries, define your dependencies as narrowly as possible. + + +Common issues +------------- + +Here are couple of common issues that arise for new users of environments. + +1. **Global installs:** Installing packages with ``pip install --user``. + This installs packages to your home directory and makes them globally + available. This can cause major problems because these packages override + packages installed in the environments. +2. **Environments using lots of storage space:** Python packages that contain + libraries can take a lot of space, which can cause quota problems when + you're installing Python environments in systems with limited storage + space. By default packages are cached to your home folder + (see these documentations for `pip `__, + `conda `__, + and `uv `__). + Conda and uv reuse packages across multiple environments (if you create + another environment with the same packages, it won't take more space). + For these tools it is important that the cache and environments are + stored in the same filesystem. Pip only caches downloads and self-built + packages, it won't reuse them across environments. +3. **Environments creating huge numbers of files:** Python environments + can have huge numbers of files. Some systems (like shared HPC systems) do + not like that the are lots of small files in the storage system. You can + use `containers `__ to put + the environement into a single file to solve these problems. + Additional tips and tricks -------------------------- @@ -645,7 +763,7 @@ Additional tips and tricks Packages available in GitHub or other repositorios can be given as a URL in ``requirements.txt``. - For example, to install a development version of the + For example, to install a development version of the `black code formatter `__, one can write the following ``requirement.txt``. @@ -663,96 +781,26 @@ Additional tips and tricks download the zip archive of the repository. -How to communicate the dependencies as part of a report/thesis/publication --------------------------------------------------------------------------- - -Each notebook or script or project which depends on libraries should come with -either a ``requirements.txt`` or a ``environment.yml``, unless you are creating -and distributing this project as Python package (see next section). - -- Attach a ``requirements.txt`` or a ``environment.yml`` to your thesis. -- Even better: put ``requirements.txt`` or a ``environment.yml`` in your Git repository along your code. -- Even better: also binderize your analysis pipeline (more about that in a later session). - - -.. _version_pinning: - -Version pinning for package creators ------------------------------------- - -We will talk about packaging in a different session but when you create a library and package -projects, you express dependencies either in ``pyproject.toml`` (or ``setup.py``) -(PyPI) or ``meta.yaml`` (conda). - -These dependencies will then be used by either other libraries (who in turn -write their own ``setup.py`` or ``pyproject.toml`` or ``meta.yaml``) or by -people directly (filling out ``requirements.txt`` or a ``environment.yml``). - -Now as a library creator you have a difficult choice. You can either pin versions very -narrowly like here (example taken from ``setup.py``): - -.. code-block:: python - :emphasize-lines: 3-6 - - # ... - install_requires=[ - 'numpy==1.19.2', - 'matplotlib==3.3.2' - 'pandas==1.1.2' - 'scipy==1.5.2' - ] - # ... - -or you can define a range or keep them undefined like here (example taken from -``setup.py``): - -.. code-block:: python - :emphasize-lines: 3-6 - - # ... - install_requires=[ - 'numpy', - 'matplotlib' - 'pandas' - 'scipy' - ] - # ... - -Should we pin the versions here or not? - -- Pinning versions here would be good for reproducibility. - -- However pinning versions may make it difficult for this library to be used in a project alongside other - libraries with conflicting version dependencies. - -- Therefore **as library creator make the version requirements as wide as possible**. - - - Set minimum version when you know of a reason: ``>=2.1`` - - - Sometimes set maximum version to next major version (``<4``) (when - you currently use ``3.x.y``) when you expect issues with next - major version. - -- As the "end consumer" of libraries, define your dependencies as narrowly as possible. - See also -------- Other tools for dependency management: -- `Poetry `__: dependency management and packaging -- `Pipenv `__: dependency management, alternative to Poetry -- `pyenv `__: if you need different Python versions for different projects -- `micropipenv `__: lightweight tool to "rule them all" -- `mamba `__: a drop in replacement for - conda that does installations faster. -- `miniforge `__: Miniconda alternative with - conda-forge as the default channel and optionally mamba as the default installer. +- `uv `__: Tool for managing multiple Python + versions and environments. +- `Poetry `__: Environment and package creation + tool. +- `Pipenv `__: Environment creation tool. +- `pyenv `__: Tool for installing multiple + different Python versions. - `micromamba `__: - tiny version of Mamba as a static C++ executable. Does not need base environment or - Python for installing an environment. -- `pixi `__: a package management tool which builds upon the foundation of the conda ecosystem. + tiny version of Mamba as a static C++ executable. Does not need base + environment or Python for installing an environment. +- `micropipenv `__: Small tool + that can install dependencies from multiple different environment formats. +- `pixi `__ & `prefix.dev `__: A package + ecosystem that install all sorts of packages using the conda ecosystem. Other resources: diff --git a/content/img/dependencies/conda-ecosystem.graphml b/content/img/dependencies/conda-ecosystem.graphml new file mode 100644 index 00000000..ea0c1758 --- /dev/null +++ b/content/img/dependencies/conda-ecosystem.graphml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + Non-free + + + + + + + + + + + + Free + + + + + + + + + + + + Anaconda distribution + + + + + + + + + + + + Anaconda repository + + + + + + + + + + + + Anaconda channels + + + + + + + + + + + + conda-forge + + + + + + + + + + + + Anaconda Inc. + + + + + + + + + + + + Community + + + + + + + + + + + + Miniforge + + + + + + + + + + + + Miniconda + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/img/dependencies/conda-ecosystem.png b/content/img/dependencies/conda-ecosystem.png new file mode 100644 index 0000000000000000000000000000000000000000..c30774ef097eef5b16ba7a2585593e98b6fb2ac1 GIT binary patch literal 25144 zcmeIbcT`i`+b+sh5kwIzfPzwNAVpM~^d?2=y+lBz*GTV)f{Ie4D4_HnT0m-~gkYga z?;Ro_y+j}(kPvbg>b9|e-x>FgbM86c8T+qfBr9vp`OddK?=xqfYN{*I(lFCdP*Bj` zP`<8BL9zEd1;t-o)O&zW{I}O+C@AibZ(Ntv^)g*dJn-^(Z|}D6H6i9?C8kWyaDR!%nRc;_c+uX2VTETpnhyr zV%0fKz%Afsq{*902=w;n=Nc_Pe`k&Z&CShWkocr4zR!qor_svJ>1`4Q8h;EB(px+l zN-jPq?y-0|T{c4oMJX4yjBrcuu5@2G#;HDF-R_L)&DG1(&b;|59k~1h6`Nm*^c}Ie zZdmw9+B1{{K6*Phl#uhp2M+ni9f80|2CWY+BKqK<{&c1Ap)&ja937Z1ez_2}UFq*J z)0WtSTpC7zyR+0Jeb@7W%b#CRbE=q%36~-?vRb{i?=R3wSJWzrj*02xOFk)Jm7P4g zy^cWn6XsyLv>)LnRUUnL+ZzqiU57i8ZryuJDIat=^CcP6`1CJ|a|bHXc0;9e;)mCl zN9`2@l^;M3K4cyRhp|e=vFhe%XIgxW>ftsjX@e|`2eD;E+V$qrG7HYG4}%Lqhyq9j z!)qVhyy3Q_VOZWS?D$@rU+w@Ey@*%3)eW75gzRbqhA z#qgV%R=7+hB%GQ@W?Oghr#=qNVivTy?6+|*xV@z%->_&Rhz(+cz#ZF5q0H)ra-YkL zjXTCp0JJt$5f3`67@E>hSVQ2J%vx`Z6C%JJhs!fFGD;nX*BjWNJ!c!9on9D2iq`?6 zQVgFx{B)x`c{@Yt2_XLN#(^Spc;p`2v1)H%0E=gb!YXC#N}jPw+J&L;W4?944Cy9i z5V#9*eW?^|aLbvJXFo-RZbBJa?B1u^elw^VoqEExBFkn*ZXcL>Vlma?Xq6|4fWx53 zHCL9c8TZkATU+;j6VEvq(ifivYnNCHh1g+1fmC!^Fkq>AHH3QlIzHk0%?gv}4+9IW zzWx%JOYr`}s%0@^$}t2a@6P+j4dHBv@bFWjQT2cc*s?7S6rC;8G4oq_L_R?wqwU-W zS!ff-v@|xRMD?aAgmkl=GQYAwH{mc^S>`-h?-OCulij&IS_NnFX%BFv_% ze$=*}6x(PduW>1t)dC_;$X-zc&gNvKn{Rl9lT%5$?{pN2MUj@))V)`auo8JzNvddN zD%Nb?83AeD3@idvRA*QaJXZZk7*JECw^;8U=phRBoG;zrxx2mPj>Af9{(>SR2ILI8 z_9V%kAQP|gNAbdrgykwsIT$@wY^lQSuPe|lcCd|h79o>;g}^s42TRV1G~1eB!g|eh zWv)Z=0ENm_i7h|F7bj>N6&IJwws6>%fSt2`oUn|@2XoJvo3$tcDusIkLJ7G}s}k9@ zO03kF`St0+C{p=X@uU*@as?9G9~$$VP9ee%pB6iT${&S;5J%77TtuVL%!3FpTQBnI zG0r4+#srofFEP1@c*0Xy9kt)gcd5)e*eh>0wt5gWbmMcK6nXgz9Us$ zSJk-OVe{=P&AF=i+`MY*B`J2zohR$uM&W=(iJsSr=GIH{TfO0n>V;{r`NYM>TGMS$ zgz(RrkJK@lBXM@lWgF27tX?p=IPZtxgC` zlJxayAM%$;*)f=`T1ZF=V^IA-Hr0&aI0{G241g zfXc8)uYI4&@dET$2OEeOaS8G7c<0NQAn;XIePFF{mrezyy44~w3C;qpj#MP9FR6^S zEEJ;D`BiV+NL5|{UwZTPri9G~13>agBH%GVzQtZE6T@IsVkM6gFmi9MTPOuw#7&*R z{j@Y&Jal6vpAx>h9|S~Yid?T|Y#i4KJ`MQ$cMlItHOKbD4HXsZBRJ%1h|A(UwQ%{P z7=(>Rmg=jh#6&p$VdKY-A6r|e>M1Cqg5Kdk`}}p&S7wrY+oU!CVd;=JMu73}to513 z&U7W|?TtymI$5Rs1`@;(nxexfC>ct|L%UI&8cBk%wUr&mv!7-Z?7vdS1h{e@{rrK( z$g^hNQ_*^P`n0F6MMy4#I zD4Uy7EMJz>+kRwm7zpl9t_75tbkN+7c;Doqn0?oHFYwX6e?R(H68{Z!B9Q**UiK3$ zx_cw#z8q>Y{)>K}RW1W#48vL7D{xurRDqYU zukPaDaiO4*I}f?Dgs3^P%{1xdET4!4SZnq*y>g&G4ztkdIpq>`B==<>`@ieG$CgfM$faJre)_Edm;ID#d4xSaM@KxI&GVU(y4&&i?KQR;uOkr- z!Ey3{b7bgdei-q(w{S@*yw9=gT$K+_M2gfS%HkqaIh(e>HD0^{DYRDBU!12GUuhTZ z%3b-3CXDxFu|eMOh~T%f)IxxSAR|LJ*BJLWRUS(2M~R(HPrJZmmSB|Ivp`&*gMpv~ z+u`x|ZLhh0RXyc_`TkNSvka3o8ljE1REZ@V2IBA`w`u z-)3*9{g;v= zuT1tDEKS-=6Bn12SfAc9Dk)w1G9HHZGneFxjeZ1aKF}Qe%@Q8wLXhh#4Hqw7^i+Ly zbu!w(rXkc0*M}k_H#<0dUe8IBy*-E?3k^fo*Zi=Z&oMPB?yaI_I9PJhaE0q;xnmoM zzWlUku}go!6bMn{`X$AGq@7X3k0j){Qin&k^JJq}2iQ~;QB&6GtPMwx{<6ZapK_mA znt8domZB8f$qA1om7+Fl4-EP zAo`#<2IL59ax6Mc3peaO@$d?(@W-rd(a(p!d6oluq)PXe6Y~gt3>q~#P(%~WUA8dP zE9L79lxI$F?komSzRJ8=w`x0_dC+9tCx%-EY1N9o=B!5EUT=>)%j(WDt)H4 zBx^ZdvPyTb*oT`>l2l)X$vQJ@9a5!{$c(MsTi4Zv?KwYM*_&^Mo<~&U8!n}zSI2CU zW{MsvUD18~3#@~<&vdahJ20;78Ml)oe?N;t8mHiL=l~8 zXFGL~W?mS{DsN(5VSzEMt>8K5QXq$}s^CvYsmv>gvnO_@Pqm9B-ZvzE-{ovjt$-bV4md)6njH%{1Ta5T}%GJ`T z1~wRSW8$?ETdxjwGc=13#;l+NX1gY%k)w<|A=uc?m?Pg+7AkeRixagH!USXFvBH5^ ziRO)iU~h+>Nkh3`wUv90ZOhQTMa>#6p{rWJa_t@|)~seL7S)q&Q0N>ljKvg^7f@U; zFF}2l0^Ap9j`;OKn$tH7Nqs}m?X^zy*5j<~1|L8-y9$nR&dS(`_#8fYS9Afxvz#o@ zP*ZX5H-q(>@9)vev$4)XehGjOy2g;$9!S4LZ$N%iwC5>ttFVrl#+X=>>C!Wn28HU$ zo3nrUm!{GA(Spj|>NUf%HFJ*kULdkZa}r)Emz~8pfbxy2);HDShs+kXq&lO@q}4@< ze26fgQz`=wo9Ny5wWs7q3k=Gg=RRHf+=PgARySJJ@t(bj_Md-|RO#8ryPB}ISVFky zUzrX=gt5Sqiv!w+z!eP15+IZUVTp?EL)(^AWY1NYq|$>dvYzIH}ZH2Qo@}d(+Qo&<`kHgSYcPIlZoZx z7c_+5scZOeaH!EH3VxKjw&00Me>)P*vnGMqAk_FD_gHv&WqoiDkUD zd41q#qzIyI4|_o30!UD}CF`J! zddDH%0;A{8{JR9&GcqzX?}+Sq_ggl>kz+=}ppw@u8s+K2ycVxiT~&!LUXH_OQ?j5o zv+NSZ+;aF0tMthmamH*W`liI$^nq7s72__QKvu6>scWRESaWG8e6C1=H1uGyVb~fD zX$AzmiUxcCt~2klq|PdJLDY?k-ic<`!6nA{j`O?$R!{9x%|Kk!^JN6q-vrC?O3KcM z9Ko;qTX=X(C|hbgLbzr#(wfq1-od_5;2mx(lNomS!*2yVLfbjyZvxgq3R{L;!gK~UvHA0+M;RcT&HXiIw}k9%a?J}(H5`YoFLlDr z>p!$rAL(@r$@nW>N#~2&`^S+>2_j=Dt(JNP`9wYp>B?smx@k=!WNm zLFTP5rb3>~Gcbh7VL>b?QjF9A#8TH(MWQ$c@J^MWL?!m^_o{+B=hv538ZJLb{N z#lkQsPxYxOGUri3fj7pugZNB*mH>O7`U&u>biPed zi*~))J{_>Pz%0)ZPUNfH3ORgwOzK`OGjx+5`ji2yXa4eheA;w`c&KJw>3)uLjEMwy zeMiE0kb5$8c^!evjzMnLF*%_Us#oH{eb7xy4yg!7DK{IEff>Vw9ES8%iITOs{C&{q zv*nS4zjz^|D)oeoNz}H23(>XVQGvwD6DgkH7Z(T-4qKL6)mu{eK!hBxK)enA)#F?* zfXGJD|IEw+-<`E9X?npAZT82D!rt-z7v+Pdmm7L<5U>);?ZU!4F~6jt^gaAs)IW7a zm`lQE=F{6RBfX!@iZ9w7u6R$ar)p0xr-@2o|0OoCbN%MXWk~@6zYZ+r+OJaEhdW3k z_tWZV114Vl7XzRU*7^6r|6fIYZokasmpS{-JlZKL_pnp9=<@LL@_fZz=xrmG*uCjn zJY;!3vGMxK-R2YD$u|FbBG~8=Awg|bmBR3aE=H2$bxh(;W=(OO*+N{Ibzcbp-fU1c zC(#==x9z9`#TnY-)92^{1~1uAZUtIuQ0H4(?^LW5k^2V^M^U|XU@G0S{kE8MUth7n zPMvdKInaUXW8m%bgT{Z6Zx0^ZV?TIur~Z}6kS!1VEPHvF5`G{0dhx)6vc<19#@@v~ zEW677aw$N+R@!j=VXg5u*y!Kk|116fcFJQD86RH-MoTT^L@x;{>-1ftP@sD|^rz)? z-UT{ACr_T#$x;>d+j!m7?%^Y&VH=UvVnY#3{}n3z%>dIV-3^S4j9z?pU+6PI`jkOr z$XzMRwG>>r)P1{*`;>XZvoO&VS%Jg%(-c$-c3I))0R-60&Mp@@m&sz@GbO zf^Iwh=_j6CHLpK33hvzN3JmqhKYZ`2IE{o9vyXs^=%u+8rdjhe%4f9%vn>ZtEn$nX9LK=&X&q8iQbu1$`b!1p7j z{&~|`#E(GwyTb)QJ@k(#`tQSb5YqqYVvPDs>U%h|b|HUc=@eZ>%(6ty?QUqoeB1v;{3ElTgMD-9mYFE=uUGC zN{oDZ^grH9$ZaUZBFdO|Def(un6-StlXZ{~zfH91nYBo?|J|@2+LNk*}=$G)Qs ze?&%(bK5|-c0qkmXaO-hkmsO3l_?%BzV}@|aG#L!(@7;OEJWoT7o%CkeRd!Z{yl8d z%S|jISiP4fU%Yt1>Zw}cTF+zQ-XChPR8oQ_-~(ENX5R*=kx!BrJ&1U-7#B054fZ)k zs%BkarY8+9Ex9q$w$h9^iRb1U^Z5KWx~iTJErw4FtXJ7`aPE6tXdCj})DLPTONwdO zwlRu-S+ndK+!J1A6U1g%6nNctHWX&UOvFx`kqD@y0sp2i*lTCHqE0tlKw&vr+tAoR z)>l<4!*ljzTgr}Wd^II#mlAi@clkK8&Xg6G`FWeuG0S3iLW%!rm8?;{xV|erU^Ngj z*(cyC1GkVM20l>1J@{nFZO*T!qseq(qj5E*j>J5?i;!`gZSS(W)>vS4wyy7;QB{PO^ijLrPm zUQTHh5bX8a3Lcyn#y2aL%ScS9?8Ig)FK9eAe2WmeaibYNTF{w7DI^w?ia!$Oy{f_B zV%Kq|Ti55QDovK`5TbPAyqipW728G7l^|11X#4oTLsSvBKeOY3z|cmK9)V>*iC*!-({>8ix*kz?g;@+p^% zgH?PF7ai6ie_qWZ&KREM{a(QQ>1>Ox5#YnHg0$FfmU76=B}&OMw2%g7!Lo##f6%#w z`D1|*3ew!1pr1iA*b6cpjAxZ7TCmt$v=d@37u=H_#-)?0y;SeG7})bXGb2m8Dka$m z94QtGz(HlGkxl=!^Y+j~ofl>=H%K7|nNwS}(6;;fZ8|2R7WU734LK6S^Nl^1K ze%6v{a|=>1M;xjU7D$NTCW7sQ1DZ3bx6hk8Lq8F$${%Sv%IML{hmYnmGA3u| z|K0uRpz(_MJBuh={F+5jAJ;Gcnp{7O@FKwXGr98`l?Nc7XAkEmk_tAvrIm8D7eZr8 zE6-FZO1=+b&KCu`FY*kaGEQ%9DP zwuSF)tvc$5dZOI*K{Ff?^^zrz_V|SR`5A48*|=GWk4cO?S>gW%^aD_n-NM^PK9l8xcc#?cdZiNM$)rsz-xI&X|Yzj8sN8OAT1J_>p?dLyqY$ zOO0xb2>cDPMYtZDi~*mY5jG)i-|bPY!irs+q>|n`RTusePbIA+2q<+AUK1}L7;SGR zQ_|el2Tttmt57j6V?pE?R!jq$>J*Pvy?K)+@ve2K#t+q#NLl9Q;R(^N0_aeHHDzj_JlBWfSc|-lFj+B#Bd(PH>{91YeT~HofAP^2mYEKo1ia#tJ!k@4h z6~g$LAu5w)b@V&3I3<#;)%5cERq-M{8oK$n1OP8N$$zB7%OlK3RET8&YF^;pF9oz4 ztZOzOLFS9huHqvaX?T6fAR=W7D=6Io^Q0gY?0dMTvn`kDqT0kfcwcST1b?rwSp z=!9Q&#BBo}<_2JsIFU+X#g|o9Kw}cOhUp4e#By$q*7wkcCZHbIgWMK{rgPMKSlp5B zha{IghOafF%|kLS?N!wAYlsJ6x-X*Oj_D>Vy*^S5etTeQWS{LoLVr%PLr-}#QbkzR zXN3gBj~x4osR!r9k`ji^q&FTghy&@#XaNz9#g^Y_pJno4>je5>_CB_Ft&p(<)LhU- z{-yI8q~R1rl#u5n!e@a_3b6)wK~2<@Bj^){O(%`!=Q-2X6{UBE!GLa_`kL6bHI?<7 zvXsbbv{KWb%Xj!%u~Tyt$>BgakcnxQT;?W}FeX~YOP&z{;JO)NC6XvgVsX8Av2^e8 z5%AVT(tFl2bTVZ40}MBM`+DzM{4>B*Bq1}Q27piKnY84Y#@1L@A_cyTO-wi{0Sb~q z-qzRe9qKvfzAVyI32pX;N(iSa(B6s`3&TE(<_1M3;LxN>cJegV9wPcc?3|>f5XhKS zNf0xN5gU~V5JL^jwdd4bs$LW$1yzMYLax&mjBWbxiM4nW?<3&D91&U7Td{_+P_gK| z9})3We!h__p(KVDG?5G|4$adNV9F+iiE3H=g#%1eC5rKZF(VOJA zv(hlrPxeTBL-@4Q);jjt;Hms+tIqQG0^1w>2#`r;r%j)MF{_%diWQezqo#K7=JAZq$8xE-GL#rEivVLdCRaiMCHFMnH8!iS^5YjC#ugK#;*xH1>e|_i5>=YS1HVWD3%DI|BzeA2 zZv_MC-FWSTy{|SqfP!h?p})18ngCDPQHv5`KOn_Tovv|xT?+;u{7ypvoUg|IDf4Fm zpMDGrAl&{Db$rWAO{#{R56{HWo$mzRyws zL4CedBu>VHK>$}^eWh;rnZz5H{x?&gnHtv)uaAp}ZRG7W4j&nQpf+01Da5!AwGDm2 z&2pj>u@l5*nt22eqMul?nGs*DJ@Sww5K&#s>!%SNqEqF*eKl%kcu_|==?iMUliv~J~{59VJBmy1bStJ9rp*bOy&Ya5rIemIkg z3TmRhYALLdlF8F)aPD!9Ig??bBM?)z)TCzzIX#jqfq4Ux#p*s+skH3R2jf6J96Rw@ zc)JP1VJo-H98cgm&cveYrWD!*2-AZ3Tt_iAUTLLgQ9m!AC(a2Mb`fn&xyYi~5$ z((y0&H(pG>JH3imFRf@UN=)-{%w4JM4Kveoo z9K^Kx;>GQ%xoR3t>tGlEsqV1MhveNL<_)_oh&cDME<6IN8P{c&rhR^+eoJCO6t$g%$5 zoK6W6PsH%E4w{JJ7qRPNcut9*ovuIhTKPIs<$KjoAG<831;o>#u;Br!98Q%RYMI-L z(wRwFK)HTi{F%{TK=s}a_I?FXMXCc~bjWNO=)h|~TAb%AT!gdfxC#^DQ2RMHOUczL z4I5hUiItZO(4BFo$Ac_zzn72S>^Wk}wrKaK zk!Zr)Tr!7VjwPK<$9(W2Gj8^6Pd{GEq94>Su(NR>dpv$^{ec}WuGg_oJv_pC(OPUw z!VjqZ`;0up*Ta0S5f{Dn7D|_0N^mcP`>|cigq06^zO#=?*G%?@mcP)+yOWsZxODiA z&ae7XYFKnv0U+GIxTtfOO)7u2B$2g4hdJY-0Q3Db4{tlhmbugzJ-!Z@kX%(icqDC4 z1DvH|G0?xhrC$RW61SdoGOMa#Mf@3G^tUV@h6^7DCbt^%7d3QUp4(kW0|P0!mD$Mpd8^Q+T3*W|x+b_i*| zU)u1~n-$Iz%L&_8X~(3NC`mno-G-zXh&STF`Q*nUi@sGN{JJDXC#SgRE>+f2rzfj;GoSE6~w|4N`sQS7R z8w74fm!ZwdZm*@%hzbE4M{JsCjGrH9pD`-wofiT&s#uRo&eW96`<-2CPe9O}m^QXh z7=1a6QGWbO+m7N)LybRCTSo`39+L7CSN<9VyfUhi5AtKKIBoWQM3FvKrasT@ajdpz zD2iO`@9+wFhOCz;d+L*3fOwV)8+Br_Mt1DTi!lc%K#R7_xX%rbyN;!J+Ph^=hv zpjL0m^XD_QhA-hS4PKtB!&A)^WH5e-p^6#!eU-I757`%n4W|6Sy}!yc+9`g+tzs>A z)>sR-m34NSBpZ$vos3Q}rp0*;28$vwueO0gt1mA>G7Je|GE2%t)<7&8-2`|Z=D0S} zP6s=2+vMGg7v1GX(Zn#b5!ZqAKGLc>!vL6XZA8)>%?Oqr%CbjK$C_yb32%(gII&6= zI^zGz$*CK1NA(7$X1%_ds5k`I9Skl-^r4R)gxyX1(W#|K1NNxEq_>PZ{>ItA*^XLI zP7AQi{vy$-qAaLa6+n3dn=(5n%obO+owvsf;L~H>lZR3Cya2UljGt{&sLXSx+G5LC z{<1Y4%Nz-yJibGG%SbV*Umc8sdXhvA_<8sgnqLDbEhvId0qu&urcJ8@i7KNAtfSaL z)CnOS@?V6^D)mGDi-@^8f&FSm)VBASJSu)cJqIIi&BevXPYRIZE} zop06$pf~-jyB@|qE5%09quXizy61j&v#wPNVJMRMHNUtNxOzqDFRnD8*|DRP=YJ#LQgm7xNKJE5C>#e`9lKL1 zj^CQBfMb&Tm-hRkhWKAfbfyTXRV{n>uK4aZiu4sMNR#4cIb@*;EE+ZI-_RI6@a<0w z?LQPtzx8P@o7aaLO8r@Y{nF+6THSpFT>d(^VgH355_+)6T20nb5w z^p_Dmz95k-a%akE#%o;Axi@L0-O2MA=gsG4gnJ_bpoGbZAG1k_wl75Xje$FVdx|nW zsc&LQDX-5_o1=;VKtAqmk8hPRo9H5CU4dJ=0g!h|ZjTFaOL)PS0?-R+b9VlLPgMgu zk-oP2fJUC6P5pz~A7I;oG&Hl=QeAhycTp)2ux1lzD>}eWzn69ZU7!`%$L5IaBg+O_ zouUps!TC3m!h8Q88xp)&(3u|-@w&J1WjsGW-*DS;^>0*cC$8_?`?u(xc%g8O_H3|> z4D1{8CLkJftW{Z6+a)KG`cO;`QrGDi9SH3k)(8!M|Kx5Cd|9}n^yV@EiMXos0Zo^{ z_N7xOKNjSOR1JVoQ5h^VBm5RdJP$MTuawjovD9SosRJmBCFNHhr@;dvKcTvS#SdZl zq>6|=|I~)48d+DvgZ6Ur@!wlu-5#r2l2n=ZZ^s@zuL8?rOqb^|Dt`w!^D#XL$f?IRwZ|IGMb z;@ zSfH`S&`IOx04iqUVTCGl>wj9z;2KwsvRW3Wnp??M0Cy#Us2E^BkilQcDGwuF+MwKt zJ$e>i#8M`#j!!rYw!Vv{`kziPuZiDfCHHV#9F<^g0a=6G3=+OCY;UI26>&Y zGmpra$i1S8wi9tOXUnMJJTDY&%tq?*4KdQQH;_c-kfz!&$M}qh=D@gZy}_dqqiEtI z))GNwzQUqpA?DIIpDQ0Uw=E*F3W*7A>V@Ooi;>zt%;wjQKfRm<@o$u$v`}5yIy8uh zLo8bp$o#hM3IN6muw<{ej!ErwwtO~=0h;W>@=J$@J584ENqNpeDoheiocUBjm9{i) zVB)uAK9p3{?1(OvD0hnO{yMs221}`=RM;=6daP)TM#kA*bnP>7 z;lcNk&m&s8re@)z+CYBv!NIeYX@E;N7g7U}0GfsU=x9)$^8$9_@1? z7|6mwD;y-EGDt-XeN~w39r4WEEa2 z?O3@^s>^=mF{g7I3j*+i(Us}(o-^Gl-2F8&Uo=wFzU{;KvmF#b>eC}(I1$V8tUJ}U zM|2~vB>-f1aoL!g+_kOAVx3&}d5iSHa??!qa6E|!W(1i+9pqCHUVVVx6|@H z9$&ezzl`-uen}}iPyjP-od9*wSIgNnU6;U(`ze)Yvg&uG(*xehjX-YWOWNj?$-JBVp>Wx&B zv`>H&!k=2tCT(MfFG#^L`_JYkq1`@IOV6%|TUSTvuBV3txFNOQBML@}NHp}&3jl!p}O(219s0ZTN?l1E!}6Y@>ptWZFNM~_}kfWPu;=I_d*GC zoB~{89c|ql9S=IjJ7hakJO7H4rAXk}P4oKj@ogZL8L$ce!CtEA&!1=6(hPacYDPkz zF}qRM%XZ%BdfUa({UE-RV&9E_V4|fCmRPq(8<-ja2Qml{B9m?V@&`XY=WOl2PAj%g zjDBrkHFYoSJxt-U*T&)GTnmWb}gA{{qP^knt?Ej1Y@@^X5 z#AjfmJ+Q5Nxg+&`3?Il%2{=B0037cz7#ecb?HWOZf?7;f%y8$y0QZg^C{2Gip1t&R zL_7vK++Y*fWDXn&;RBpJGWz1siOaR2AyRIdmC+gRGXgW^vw%5^Oj1xE+ReIqWCfhj zp_i-sN*Y=tq@Au978)9QX7JIsB{Dwi_Q`Fdl)9XYV$VO2<;K0{b6_qmF2W82x7n&E zf_dsgPnxq`yx9S)?vT>#7uzE?7Z(F5_5s-2A3QyZOTcLnY*+4H2OcQ3`T3Z+9d@=8 z4I#p>7+R#rr|%Wqzw=ugSsSC!ixd{Sr(HV{53ZRTsc^+FkD|!izOL#yd#FN=QnIqs zb_H}4cT4~%KqG)s0?nvj-E^%qAZfTk;n*AJ$>3VHtI>}bAI3al42o$?*egT5TR2ii zNFR3(kM*^7X|VeJX0o8EuT z>nKKQ4a}Vb`0qU6-Tfe%eF#X%eY2|+0lNvAmur)SBPgNQ_bUH`pbl@lS<`!wBMmA1 z&g>TB9Fd3PK#NzJz!6zgjvGsU^)P_^C@7L9-ia#U0=-6%j^66@wrB#m}T38PpMxom*ISu zus4N$mwRFt_1>I{Eh#CPGjrXO0J?YPK6LjrgSFv$@AgAFsQ*EBHz=K0XgJ?Q9^R1M zr9)9vTgJCuzU2=NDA_Ia8+*1FbZhze5THpcwH=d`jqm`UGhj#E(Q)rSzKJ4NrsLkP-q3JpGmwamO8ypS!(ySvnvDU z;d+Ip{=g>H>3vTwxN*-t?6MW&l!@A{9|}+32hrhy-K~HwB}2C>M5)paC2ESn-CX95 z1Il7c|EIeQJhOK!Dn!^O>%lHfI8OT|S|{p0f5`KbyZivxo=-9J8GBHNB1?CRKI3ij zA!YS14N_6ZcKz_lrH$t=KOWkC>3DSaf*zqHPaUj<_Pub}ebeJ_p|*#3za&R;((PJL zdeL7kh}|gFBIQNOhs&HYopQT0>dc2fEvO{>APql<$jFnzc&K+cwOpMN1rRokxVqZy@{tNHGw zD?4G=+>lTIqCaGn`-sAo=`Z?s01|i9nCDkWu1v%t8lfs1k-twzm)=7B_``iAlBN1> z>5qTyNU!f_ItqOA?-k!SmHjJ^KlJ0m$x9iDD&b(`FKjb!bhgi0;PyVk=0jK_Z1$g>dk%Xn{*mAdQ!*c!19dI`Ik$nWiG7lTG8Yd=a7+_4SvgZr-$Y8eCkqTj zkd=*ua^1B8=UWpeJELz0(`Y|&fK?hH?2g^65Xpkf12F0J)uziU-eC?V*zR(Lpu|a! zLHMPb6xZl{3MTkYMG@!}9i167$Nlr%-13-dk)-%$|HPaf(Bi7wl(L*sFea zLdLEy%Qcav)=Jx7v=&NiNw*nw&Bo8vt$JH8%SyV)w(6hn5`f|xIooc_17bP9T62Q? zKvp*UqsDbxd9$8P;f=VRqa0$DO;28sDvUh1V0yIxBRBKL#3Sz-k#A<&ZyEOFyG1^G z*tSBfs|zdOHsH2je~m_6Spv6tHU2!FVko}RM43Rin3U9+I#|{==sDxBG?$d5KLR0j zP@%(IYn=CsPf2U*pTUHrMtzeEc=WYS>muPa2;0OB@}B9MY`cG1!7yQ%@K_w2dsQ;;0a2n4{vzADE?@UIqY#oq0&!_*j@%QDjw4}O4<7CeR6Dr6wz#oWPZzcn8B>0V zFjqn4d5I0xx{(VRo;b_HHd5v{qHixBQ;kR~yVKXN@eG2myMdVz9qUpqoPu00v1cQ< zY`#-gzN|nwZbh^Y_fw_BK4aCf8rh^ldeoZ~4q1~DEW_7kV+_2PbEd3A&UjDVxqIuZ zc+4qZ+tr}by!dJIZQ3q#<4eAKEtWPb=aQe7KpYUo1U{ecG$HRh6TVf+*DR5Kq!#`# zu=V2Ew$_u=#w+=`h@WdRMXbZHk@5uS*8I*TkL6kcMP9kR%T0@XIl1|$Pg;?8QPw(J@2$Ec=rQs_+VkO{m?qhne?*B2Noj| zx>Utpay`dT%8|vrXpDO?(%8aM!Rk1_C}G;$XR9XODz=F$uVF42xe{EpG>Abm_?%5` zm#Ne422P7mtL$wl03$OyEsY9|1tb+ZE-5TGaC@gQMX_J8Dn}2wAHsoN81(4ra_Qul zOctygVM-SLSw~m7+Xc$15nNFQV;8)wP0wmP+tg8i#9Vs4G#OB8+jiS8%Sqw7yz%md znUP(urj#*lM0L#O=LhZD=hUVSo7x)ALF}7S7>*Z;jJ{S>@nP#KanBRBHHN|crR}E# z9U$A8PVoXQYZHcg(!n1s|5mONe8}5=3B#-Dsx2`=l~6JJiIYr}LihOQ-Idk&^ovwI z>~3=V583v9qNzNDQ(2yqL|Q!U5>zp;8H{3J-JB}Kd0qe6USGf9!W2~lfrxJgQsVQ| zsg8kthvL!}VJ%r2$gzG6ALA8$96yY%LpOF#F0E1AN7Y#|>H_U8^%5k1RbYWCVL;Mx zHsrmJ)XhokfyebkcUFZ-aJ#6C#$3Q$CnN$Vhk;ADE$CoNHDHmYdDsKCeyBP(k|Ef3 zDgM?dTuqvrzV9ICAww%sC53>C+|)b(y;aJ%2J6ivQh8H)3EE5QF&x0e;iZ~cXFB-` zSKDHY$3VwF@_?U93=0+8&mFLH8xlc2z9i^VZPOF)#_qidJ`sL+llIl2*{g)XmEjwL zD!!&ddBRVh*$gf5=O=Gwj&k#pJ7)PFjv1K76~~sV5EV75N^6YTeXt-(r?$)C)_SC$ zt}Ov+rs*lPu#E0pR689+GGmo;Ud?|xQ_VFimN~LL84B&3G+^CMcF8QhB!MCoLUCr^ z(q{44!O)w>gdBAR8^a2i7M`5p{K2p&6N#*f$X^IzMc9wvs$KN3{a4yG8q*Q)?;x|L zr^sJwCkY<`FVhfZ9>d}92R0&KwLWLUH#n8o8RWpTO0JJh%GS)%o*V+W``ED?$qKV+ zT^dM)9McK^fntEVj||UTr0Fem7#s$+@$C4}e1~KoB6l!MEIV1-Bz>m`fNU@3Sdgfk z>Yd9e$&A4>Dy+`uU+5Dmb|TD_vcLCLbB*hmIw`&u!Z75@?CrB?<@?h4PFK+|RM`(# zhv;~)z)velfL8|yTZ@Fd{voLd2;js&%R3Qrl0Ueb9tR8n^Tw$dhaK`j%q>K&Kako! z+3yg@%vVrl0Wf-ue~(`uA*AYSbN)@E!-a{;;rwWgZ0#eyJ5+r71PB@3V7 z%tx!Y;#_UJm%TTkDbGxmL2MnCrROVYLKn{Lo^OPY`y0u0ua6f4^*cUgJZQ$T;|V#Y zbAHyJ1t!ZQKE8p3EWYh~Lwd|&e@``elaSM(udhC!7Kz6uIVG2&GCQ5n?*2}b#_$lB z^@}!MC5*LJb=pn>N*>&{TPAB?hD-C+oG08nRRZ(^oMYBT+S5U%MmnrHQ$-4q)na)! z#$NR|J~lE#k2qg*&&1{qMf0ba^iH*Sk94&BrwbuHh#df2R_X-XK_;Zb)!42>~ z5=tn&Cm+tXzFCXLmQEysMwJchtLjbWw0qGfF0mn^O$W-<&|0XMwy`TJ5}i>$_Qih< z!1cJb=@$N*FXz_}cV zQXn{|wu^+>BaAM)z-yLbvl1{N6;(#>ttPeqvkd5)21tMB)a*7rim z&f7ujTw%3ZX(;|>^%hvnijL?H_-KY^iv=@oH({AJNs;`7zji#>g*;XQ*hkgC^Z5|d zur+Wp<$suVb2FLa)YLkE6?uMI{p@m;Z8=Wm4Oo@*!co=;LC z?IZ!d(GZnxw(6wh20$j#$+rxM7MMF$+d5u68pmQ z$HWszF@0Z5yR~(+aZG}Q_!mX~Ook;p)8=BY@)IKN*rZJ=7J(qNvDh04^KEEkuId3N zp;U-gc}wKY>jVt48uQF(Dap+&lFqbuf*H=NDDSK|)2CtA!zU)s6{qRv*P8J>%l6!CYa2x9`xk}6r=naw(^F1o?w>7+L}^9>dG@dA4wsrW5}RUAjV1} z;ltM!9*u!cc38UclKTxCJ=(sA%sTStIarcn%0Jft`xx---3mKtKvL}Ci;+olerAVI zJ4&BCSO7&k%8_@@CJ7$}&L)BBuv!li0Z+%E<_(K!U|f5++VuW4*G#Dqb(2m#>sAwHyx@6tW&z5NnSesT$wO+zy-GU>eqqM?!zNj&?tt?S!MoLY2ppwLIZOkqJ5*>zfRC$fh+_J`7**=V-)@q$Or=&oNICPi9$v76t7*x4}pK zM$k(<{N(l{bFF3B{STz_#qlFf(XmjQp8MJhMiP>Nrg~Wxn~_L1#F?Cv$noM-pTgp1 zgY>Din9gtF`ZK+0#vil>1g2WO6cX;?*o|ME?$>!NEwNG2Dbl_$=0Ra{3%epu)uEIk zrpIiHD9+^WD*H%~cfRxd7cVnwsyw6W=3OlcaKrjTQUT{-B)#^P8y3%W%2;|~hZ`14 zk8~e|(wr9Ei4HT@hLP>*N~TkFk;Y#$;3s1oeG=O{EhGinJRIw^*)Zejoruq{k$C_Y zz)HkeyFN121Aq65w41T*AACQ@qO!ti2`b(yJ>!GY#-FFiGO;5gmmX5z_;Enu678jP zT+};HZ1ezLzZDF$PwnUY!QI;7ggRA{wT%a#>VK&#JG4_=b)Z(NwN;HZ;0D# z+|>>poEtFvu$Ll1vwEqH+whXHFMZ-`=KIHj5lBPIW(9k?v}5{v@5!x{Gv(c`uvwCI zduKVtq>uGFXa4?A4<{V?_20U54h8=E(En4#+Xfb*Ah*v{ko&Cpx9pSYK7nPAQ{3m@ z0R91?dJ6dKgfB5