From 51e0ed94c0bfe985afd16896d69946e853de4b24 Mon Sep 17 00:00:00 2001 From: Gregory Poole Date: Wed, 3 Jul 2024 14:57:53 +1000 Subject: [PATCH 1/6] Update documenation. --- docs/content/configuring_services.md | 15 +++-- .../INSTRUCTIONS.template | 58 ++++++++++--------- .../docs/content/getting_started.md | 5 +- .../docs/content/notes_for_developers.md | 51 ++++++++-------- 4 files changed, 67 insertions(+), 62 deletions(-) diff --git a/docs/content/configuring_services.md b/docs/content/configuring_services.md index 1f486c7..5a0da20 100644 --- a/docs/content/configuring_services.md +++ b/docs/content/configuring_services.md @@ -7,14 +7,19 @@ Develpers and project owners/maintainers will require accounts with one or all o To work with this codebase, you will require a *GitHub* account ([go here to get one](https://github.com)). - Branch permissions for the project repository should be configured as follows: - - - Protect the main branch to only permit merges from pull requests. This can be done by clicking on the 'branches' tab and clicking on the 'Protect this branch' button for the 'main' branch. - - Select 'Require status checks to pass before merging' when you set-up this branch protection rule. This will ensure that all CI/CD tests pass before a merge to the main branch can be made. + Branch permissions for the main project repository should be configured only permit merges from pull requests. To do so, navigate to `Settings->Branches->Add branch ruleset` and: + + - give the Ruleset whatever name you'd like (e.g. `Protect Main`) + - set `Enforecement status` to `Active` + - add a `Target Branch` targeting criteria by pattern and type `main` + - select `Require a pull request before merging` + - select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check + + This will ensure that all CI/CD tests pass before a merge to the main branch can be made. Several secrets need to be configured by navigating to `Settings->Secrets->Actions` and adding the following: - - To host the project documentation on *Read the Docs** (see below), the following secrets need to be set (see below for where to find these values): + - To host the project documentation on *Read the Docs* (see below), the following secrets need to be set (see below for where to find these values): - **RTD_WEBHOOK_TOKEN**, and - **RTD_WEBHOOK_URL** diff --git a/{{cookiecutter.repo_name}}/INSTRUCTIONS.template b/{{cookiecutter.repo_name}}/INSTRUCTIONS.template index a2f6cf8..293bfbf 100644 --- a/{{cookiecutter.repo_name}}/INSTRUCTIONS.template +++ b/{{cookiecutter.repo_name}}/INSTRUCTIONS.template @@ -2,54 +2,60 @@ // Once this new project is configured, you can delete this file. See 'notes_for_developers' if you need to see this content again. // -*Now that your template has been rendered, we recommend configuring it as follows (more detailed instructions can be found at `https://adacs-python-template.readthedocs.io/en/latest/content/configuring_services.html`):* +*Now that your template has been rendered, we recommend configuring it as follows:* -1. **Create a GitHub repo** +1. **Create a Python environment** -Goto *`https://github.com`* and create a new repo with the following: - -- account: **{{cookiecutter.github_login}}** -- repo name: **{{cookiecutter.repo_name}}** +Use your favourite method to create and activate a Python environment for your development. -2. **Enable GitHub Actions write permissions** +2. **Install the project and all dependencies** -On Github, navigate within the repo to `Settings->Actions->General` and select `Read and write permissions`. This needs to be done -before the next stage so that the GitHub version bump action that is run on first upload does not fail. +With your envirinment activated, run the following from within your new repo: `poetry install --all-extras` -3. **Push the local repo to GitHub** +***NOTE: This needs to be done before any tests can be run, documentation built, etc.*** -Run the following from within your new local repo: `git push -u origin main` +3. **Create a GitHub repo** -4. **Configure main branch permissions** +Goto *`https://github.com`* and create a new repo with the following: -Navigate to `Settings->Branches->Add branch protection rule` and ... +- account: **{{cookiecutter.github_login}}** +- repo name: **{{cookiecutter.repo_name}}** -- type *main* in the `Branch name pattern` -- select `Require a pull request before merging` -- select `Require status checks to pass before merging` +4. **Enable GitHub Actions write permissions** -5. **[Optional] Configure repository secrets** +On Github, navigate within the repo to `Settings->Actions->General` and select `Read and write permissions`. -*This can be done at any time when you want to enable these features; they are simply deactivated until you do; see *`https://adacs-python-template.readthedocs.io/en/latest/content/configuring_services.html`* for an account of where to find these values.* +***NOTE: This needs to be done before the next stage so that the GitHub version bump action that is run on first upload does not fail.*** -Navigate to `Settings->Secrets->Actions` and add the following *Secrets*: +5. **Push the local repo to GitHub** -- **RTD_WEBHOOK_TOKEN** and **RTD_WEBHOOK_URL** enable automated hosting of documentation on *Read the Docs* -- **PYPI_TOKEN** &/or **TEST_PYPI_TOKEN** enable the publication of code releases on the *Python Package Index* &/or the *Test Python Package Index* respectively +Your new repo has been configured with your GitHub repo details. Run the following from within your new local repo to push it to GitHub: `git push -u origin main` -6. **Create a Python environment** +6. **Configure branch permissions** -Use your favourite method to create and activate a Python environment for your development. +Navigate to `Settings->Branches->Add branch ruleset` and ... -7. **Install the development dependencies** +- give the Ruleset whatever name you'd like (e.g. `Protect Main`) +- set `Enforecement status` to `Active` +- add a `Target Branch` targeting criteria by pattern and type `main` +- select `Require a pull request before merging` +- select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check -From within the repo, run the following: `poetry install --all-extras` +***From this point on, no development should be performed on the main branch. All updates to the main branch are managed via Pull +Requests in the GitHub UI.*** -8. **Activate pre-commit git hooks** +7. **[Optional] Activate pre-commit git hooks** From within the repo, run the following: `pre-commit install` +8 **[Optional] Configure Services (Read The Docs, PyPI, etc.)** + +This can be done at any time when you want to enable these features; they are simply deactivated until you do; see *`https://adacs-python-template.readthedocs.io/en/latest/content/configuring_services.html`* for instructions. + 9. **Start developing!** +No development should be done on *main*, so create and checkout a new git branch with `git checkout -b new_branch_name` and start +developing. + If you have any questions, consult the template documentation at *`https://adacs-python-template.readthedocs.io/en/latest/index.html`*. diff --git a/{{cookiecutter.repo_name}}/docs/content/getting_started.md b/{{cookiecutter.repo_name}}/docs/content/getting_started.md index df2dc23..493164a 100644 --- a/{{cookiecutter.repo_name}}/docs/content/getting_started.md +++ b/{{cookiecutter.repo_name}}/docs/content/getting_started.md @@ -6,10 +6,7 @@ $ pip install {{ cookiecutter.__package_name }} ``` ::: {note} -This section is intended to be a place where you can show how easy it is to use your package. -Taylor it to your own needs and see the *Markup Tips* section at the end for some guidance on -the extended markdown elements that the Myst Parser gives you that you can use to build -content. +This section is intended to be a place where you can show how great your project is and how easy easy it is to use. Taylor it to your own needs and see the *Markup Tips* section below for some guidance on the extended markdown elements that the Myst Parser gives you for building content. ::: ## Markup Tips diff --git a/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md b/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md index 03d9296..e1cba17 100644 --- a/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md +++ b/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md @@ -196,33 +196,20 @@ Documentation for this project is generated using [Sphinx](https://www.sphinx-do Developers are mostly spared the pain of direcly editing `.rst` files (the usual way of generating content for Sphinx) in the following ways: - * default `.rst` files are generated by `sphinx-apidoc` from [Jinja2](https://jinja.palletsprojects.com/en/latest/) templates placed in the `docs/_templates` directory of the project. - * [MyST-Parser](https://myst-parser.readthedocs.io/en/latest/) is used to source all content from Markdown files. MyST-Parser also offers [several optional Markdown extensions](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html) enabling the rendering of richer content (e.g. Latex equations). Several of these extensions have been enabled by default, but not all. This can be managed by overriding the behavior of the `conf.py` template (see below for directions on overriding templates) and editing the `myst_enable_extensions` list therein. + * default `.rst` files are generated by `sphinx-apidoc` from a [Jinja2](https://jinja.palletsprojects.com/en/latest/) template placed in the `docs/_templates` directory of the project. + * [MyST-Parser](https://myst-parser.readthedocs.io/en/latest/) is used to source all content from Markdown files. MyST-Parser also offers [several optional Markdown extensions](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html) enabling the rendering of richer content (e.g. Latex equations). Several of these extensions have been enabled by default, but not all. This can be managed by editing the `myst_enable_extensions` list in `docs/conf.py`. 2. **A single point of truth for high-level aspects of the documentation** The project `README.md` is utilised, creating a single point of truth for the main high-level aspects of the documentation for both this documentation and all the homepages associated with the services used by this project (see above). -3. **As much content as possible is generated from the code itself** - - By default, the`.rst` templates use the content of the project's `README.md` to create the documentation homepage, followed by the following sections: - - a. _Getting started_, generated from `docs/content/getting_started.md`, - - b. _CLI Documentation_, generated automatically from any *Click*-based CLI applications that are part of the project, - - c. _API Documentation_, generated by `spinx-autodoc` from the docstrings of the project's Python code, - - d. _Notes for Developers_ (i.e. this page), generated from `docs/content/notes_for_developers.md`. - -#### Overriding the default behavior of the templates - -The behavior of any of the template-generated files can be overridden by placing an alternate version of the output they generate (i.e. the filename should have the `_t` part of their extension removed) in `docs/content`. This will be copied over top of any template-generated files and then used in their stead. The easiest way to create such a file (if it doesn't already exist) is to generate the documentation once and then copy the file you wish to override into `docs/content`. This copy of the file can then be edited. + ::: {note} + *MyST-Parser* directives will not render properly on *GitHub*. Similarly: *GitHub* Markdown directives will not work on *Read The Docs*. + ::: -Some examples of changes you may wish to make: +3. **As much content as possible is generated from the code itself** -* new sections can be added to the documentation by overriding `index.rst` and adding a reference to a new file (see below for more details) -* new MyST-Parser extensions can be enabled by overriding `conf.py` and extending the `myst_enable_extensions` list. + `sphinx-autodoc` is used to extract documentation from the docstrings in your codebase. #### Generating the Documentation @@ -253,9 +240,14 @@ The majority of documentation changes can be managed in one of the following 4 w Examine the Markdown files in the `docs/content` directory. Does the content that you want to add fit naturally within one of those files? If so: add it there. -4. **Add a new Markdown file to the `docs` directory**: +4. **Add a new Markdown file**: + + Otherwise, create a new `.md` file in the `docs/content` directory and add it to the list of Markdown files referenced in `docs/index.rst`. Note that these files will be added to the documentation in the order specified, so place it in that list where you want it to appear in the final documentation. This new `.md` file should start with a top-level title (marked-up by starting a line with a single `#`; see the top of this file for an example). - Otherwise, create a new `.md` file in the `docs/content` directory and add it to the list of Markdown files listed in the `docs/content/index.rst` (if a `docs/contnet/index.rst` file doesn't exist, then create one by generating the documentation one and copying the `docs/index.rst` file produced to `docs/content`). Note that these files will be added to the documentation in the order specified, so place it in that list where you want it to appear in the final documentation. This new `.md` file should start with a top-level title (marked-up by starting a line with a single `#`; see the top of this file for an example). +5. **Extend the MyST-Parser support*** + + New MyST-Parser extensions can be enabled in `docs/conf.py` by extending the `myst_enable_extensions` list. See the + MyST-Parser documentation for a list of available extensions and instructions on how to use them. #### Adding images, etc. @@ -269,14 +261,19 @@ Develpers and project owners/maintainers will require accounts with one or all o To work with this codebase, you will require a *GitHub* account ([go here to get one](https://github.com)). - Branch permissions for the project repository should be configured as follows: - - - Protect the main branch to only permit merges from pull requests. This can be done by clicking on the 'branches' tab and clicking on the 'Protect this branch' button for the 'main' branch. - - Select 'Require status checks to pass before merging' when you set-up this branch protection rule. This will ensure that all CI/CD tests pass before a merge to the main branch can be made. + Branch permissions for the main project repository should be configured only permit merges from pull requests. To do so, navigate to `Settings->Branches->Add branch ruleset` and: + + - give the Ruleset whatever name you'd like (e.g. `Protect Main`) + - set `Enforecement status` to `Active` + - add a `Target Branch` targeting criteria by pattern and type `main` + - select `Require a pull request before merging` + - select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check + + This will ensure that all CI/CD tests pass before a merge to the main branch can be made. Several secrets need to be configured by navigating to `Settings->Secrets->Actions` and adding the following: - - To host the project documentation on *Read the Docs** (see below), the following secrets need to be set (see below for where to find these values): + - To host the project documentation on *Read the Docs* (see below), the following secrets need to be set (see below for where to find these values): - **RTD_WEBHOOK_TOKEN**, and - **RTD_WEBHOOK_URL** From 1fa035cfdddafbfd710d160a76ef087ee329fbf2 Mon Sep 17 00:00:00 2001 From: Gregory Poole Date: Wed, 3 Jul 2024 15:30:33 +1000 Subject: [PATCH 2/6] Update questions image and some tweaks to the README. --- README.md | 48 ++++++++++++++---- ...python_template_cookiecutter_questions.png | Bin 33220 -> 35609 bytes 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3d1e4a9..dd181c2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ This template takes the effort out of starting from a good place. ## Getting Started -***Make sure Cookiecutter is installed...*** +***Installing the needed dependencies and building your new project is easy with the following steps ...*** + +### Make sure Cookiecutter is installed ``` console pip install cookiecutter ``` @@ -10,24 +12,50 @@ pip install cookiecutter ``` console pipx install cookiecutter ``` -***...use it to render the project...*** + +### Make sure Poetry is installed +Use the official installer ``` console -cookiecutter gh:ADACS-Australia/adacs_template_python_base +curl -sSL https://install.python-poetry.org | python3 - +``` +*(or better yet, use [pipx](https://pypa.github.io/pipx/))* +``` console +pipx install poetry +``` +### Render the project +``` console +cookiecutter gh:ADACS-Australia/adacs_template_python_base ``` -***...answer the questions...*** + +### Answer the questions ![ADACS Python Template Questions](https://github.com/ADACS-Australia/adacs_template_python_base/blob/main/docs/assets/adacs_python_template_cookiecutter_questions.png?raw=true) -***...and configure the services you need using [these instructions](https://adacs-template-python-base.readthedocs.io/en/latest/content/configuring_services.html).*** + +### Install the new project +Create a new virtual environment using your favourite method (if you don't know how to do this, go learn about it now) and install +the project by running the following in the new repo directory: +``` console +poetry install --all-extras +``` + +### Configure the services you need + +Follow [these instructions](https://adacs-template-python-base.readthedocs.io/en/latest/content/configuring_services.html) to +configure GitHub, Read the Docs, PyPI, etc. ## What do you get for this? ***A codebase that eases collaboration and automatically:*** -* Ensures that all commits on the main branch and released versions build correctly and pass all unit tests -* Enforces code formatting and linting policies -* Manages code and release versioning -* (optionally) publishes your code to PyPI so people can easilly install it -* (optionally) updates, builds and publishes documentation to *Read the Docs*. + +* Ensures that all code on the main branch and released versions: + * builds correctly (including documentation) and passes all unit tests + * conforms to the project's code formatting and linting policies + * is properly versioned + +* And optionally, automates the following for new releases of your project: + * publication to [PyPI](https://pypi.org) so people can easilly install it + * publication of updated documentation to *Read the Docs* ***Other ADACS Python templates can then be applied to this base template to quickly kickstart a new project.*** diff --git a/docs/assets/adacs_python_template_cookiecutter_questions.png b/docs/assets/adacs_python_template_cookiecutter_questions.png index 6b25cd5b9aba4c0f6453ca441e5107885fb1a102..9b52fc891dc2e26641c2c16c2ea5b0a6a2ec1161 100644 GIT binary patch literal 35609 zcmZsD1y~%-wk_`N!6Cuj26uON_YmBIyF-8^xH|*E-Q9u=5Zq<30Kwhgg(y6F6%DYwR^3-Cq_+079E8c1quoZU0zN~0}2Y35E6GrLV$edwh5y{PSEZevJz0$ zlca}`9~Rbn@;1uKP>hf`5)^cl9TeQ(ERcg3azH`BeUF4fgq(38hgv=~6fEQn{Wm=y z=HEGC3G-q99fxv;q(g~oO3KSa&YG5P*49q$ADumv#$H+=1sCkJ^gQ&Gl>{uE9a+t- zoGq+by&YZt7J(A-7Jx(@tv$>sy&WB#+y%UassG6#0Ez#-%tlT5PZke*VQM{PHA+cm zH)~1&D?2MYwFn9&C8dy?m5qRgl+3@1Lw*TUfAsKh5nyBU^73N!;$n4nvt{Gp=jUf* z=VasLWP#*harbfZF!yG0a)19{mHfLNDQkC2H#-*(J7*`#zxA41ID2{sQ&azK=>LBH z>prc$?f$zZC-;9n7UTih{-&^Tu(GrL-?|}1h5lX@P_y&4cF>oybA)scqzw@c4i2Gz z^8c@t|8DVrl+^q0lDz!?Ps#t0^8c6AcDHtubasR^=^^spBlE9j|7YUA3JS6Pee(a& z6aUrC|6GOivj~b1+y5Oi5tRCUOUO(UgOZmL*Ybw`lY^L#H}udOwc&I9Lk?fMxJ<8C zYMP#LsR)5dhPu!~5?Ya(F*XQ)h$uc*L&`D+`E!vByu28Eu^g6o$=zwuRq)&M{syW0 z(`Vbe+tc%qtG+Il*`AD?4Cij0LjQ+Lzi`+n=>HHx&^XjM2d-J$27>=n=nsC+x+dmA z^uNPT6a-S&Z}{BpN~8$?A-HZ2|ECJYblA6|<0|uiS%cZP{&$E*<^4~UA=HOL%Nkk1 z$Ft)8hev=UwQ~H2%Gkf+qw#^MnLc`C@S**O0Pc_fk3CXp){9N3FJ3f0Xx{t3LcWIp zJ-u;zW0^*Y0_W&LmElmc~m>KWG3BOOz-mC@@Lh8K})zIv;d zYtYnvJ~8Mi9(pvsIhr5(CQDwvqFKq588MdQF(Y3n6@wFt1(Nv88fOt6LVI9LvvNnl zm>PIly42(t_v785%=(TB!Ms5;e##LAvqDM*WlW-Wp;1$2p-xA_QM>1SeO?p(97~O~ zy?UEDu6lt=K%M>5g4GLG712qhT1EHL#q6U}Lu`&oi}T{Gqs8I^OQA|slGI*URxC*I zU}Tbu**xkgGH&HWFlJtJI8L}D6f?X3@*=W9=EAVfB7&Fxmg{(~50S#iYW=;Wq23yd z<8eC66urGsgAEAo!F^hnG{iHDC)jtPQeU&uw8!MnT3Z93&iwr7-|i0!Y2+g;Hg2$q zzuyYO6k0}7ueXx_RjN$#tJ%?z!|T+D!)~US+SS|jcR^Gvi(xZTlG?}h_NHJL{Z4OJ zPV~L!tGqX@sgumEroK=3=b*RngBG^6kHDD~|1SgPslR22`yph}CO*dKXiQ+cn~z}Dptv-mByG)%Xs z9Sr*IU--Z)9nu4ulPM&l#)S$y1Qt)%JeMmPq`cnY^v30GIPZ^Nd8Pe5@8%0X%??OE zK_|wdl{c)C)cbd|P}*a$O568eGKOpl_~9G5UfQB3X$@?kzS~V`^#?_^`)ttW2x# z^=C=F(SA{7&F3ITy1p&~KZf*@+JUTrCb50k*rgBNVrMuWylk7-WZg0~z$f<9^Y$d# zM3>HGn;>A>Hnffh&LOFT2zfUaId6TsLGIQVj zr1dIuFWZ*b&q&nU{iW*y0#5nkSo}5^mzHYsUYeE~KRgac`1Usi&(0iW3J$gFYYvtU zi4LA-Y3z;B&89M%Qu*W^DzDxCsy;LIqn!my&Ys=dg{6BNV!F=tj!4hjRDIw*=HRgF zwJtd9r}j8m(f+ekCrK7=?6a2=JB_5MY1Cg-Y1!OtvEepa^URocTpmv6M7Qu+IPRRE?rm6XK?0Obt@QU2xoscKK`~$y=V}!6e;ZpA(ZcZqkyTk`qkEQq&4Yd2S@kEGBQD|%-nkx*6WA{;LVgY|5P z&{XRIZaztDaJjnY)ffLPNmT@UO873j{UEW5LPh98%Jr}$?FTL!fIwB`p*USMsQYJe zz#Oc^9OhzRfMLgHM{V*)@#v?3n|WREZj!1F+)b_dz~DY8tIAOh(3rmYTjVlOw)vAg z<7TU0=nlYg$ymNWl$&Rj6!@JrnQq^{^ktDZYYdSG+gQe*x|!LKzEosd7f-GldU~ta zsc<=BF?t4{F~&NthppT1!qs!dr09mD5TuMLM{ONXPlX9!C6cZ^e<@HomK3_4>!0+Noa2a(&h-s6+zLsAP`91V>pS=lI%L~L3>h|zi4#;q2-@}KTpEtHO%ZW@c5D%S)? zR+EXJz}f~LSDCzhq3tk?3W3Fe)u&?ZMH9dSn7M-xl1IOQfC#&czh+zi)Q{sGKVD7k z#pL6qMZ-G$S&BxShfh5kz!YT`P&CG{;#1xV&rb4FHe%=hc#43Fi;D>dA3hxn4Xb6` zw3M2Wc$XUye>?LEndgR%+?&3~EY6L|wn(gi(K*lU{s@K2alH3o)~`KpFRJVzT!-&3 zZ?>Z-7&A;&o;H0B$m;wb+@M1wdi7FE@)rEt`QAgM)fzOX0I7NQ|e@ z4V}qj?=W|Lmdv9VTmb}UuP;wbFk?F8qvl+Q^GPl%GONp!y%>vT$59CA#PrV+?BWjU zypMSA)|FNkJAK^yLbrx^JTH$8&kcYoWKHyaAXuPe6b3$IK^0MFcE7zoEm_L%6z~~s z^UX|lc6R=pXE3eErKdrL0%X~jsw&B+^=t{MH=JC6&nuqdXeiz!E1$udb=G^|llhAG zbgO+?)ZcV%qlYNEs2CTVKdh|r5w$7dw~V&w#)7`X)=3??B{LeDsL_g|yGRAs`^;-@ zq?LcC8`G-(Q6$}-T4iAD)QG9++QMvT#WJNcHHOHWL~YK7#4lggnHumKa)0{}H5V{X z%OYK|;iUjBOZF8hek!pTkEOBL_6x$rKPF>d*|_{lumAG~a?43G__!9<%O6eGaRZCS zxZi^PT;QiouLmOAHjB6F#nT$J_y*_Nox5>FU+x{vNVKFLY=MwjI+_0ANG?HsPX?4U zD4p#(9D;U*Q>d67T;z=St?-~EpP$LWWX4nZfS7Ko*7HkSJRh+hW}`@fW4xp;oKtT! z_Is^o`V>h1DFdwX~N=aJ&4;$ zu&S#o=Jpgm)U>C@&Mzyw8~kXb(L_IqU9lrcRX&U*GrUiSQ!=~yc}S<=Meke?)Mvww zk<4NUkY;$k>v`*H{aqNRrIQ^fiRMCFfIm3Fxir1udt7yNojZ%ES3nVP{VleCn523j z%elKechm1o*!B9CES;ysgn#E<@hrRFtwV`XbzWFCL=n_nLq7-ej&iCekn(HLi0-Fb zCWlgC&LIoq0v@62D@Mru9AXpD9%%Lk~XS!I&c} z72GZLBLkD%NLWF@SQyeyaEO<8H-IeZUN>N^;uEH2bhvCENNZ~2Y zJ%*}@ut_<1YFsFtc%0&G2ru6%ZUlAB)XwC?l7J`3`%?Uf912=M;CeeD!Le|0k>DPD zXFK8J!rWBIc~#~`ex23OzfWTf^r&{dL^B+5C@dtBM>g0|yOgQ9NYOP>SLWMG*3`%Z z^X45QiC^VAZp3pf`m9!uFD_F0*Voj7I_4=SSl0s81<&>7v82G7{-%YR z>4g|drE9^Q$g04--SbHuVZYE6Gb^QY!d4K)>5+}XmUMGs^4H!qBlPcv}pFHO4ggJ_3s-d#Tf<~>e4BN zrheVDHMv@Vu~(yY(C?P>e|u~IkJJ?nI-6wXt6VWDBsBuWZcY1g*T0ic2jP4_n@bW> zpW0OOPU{+PnR?5cYrEIWSr}+z@2lyw%JDynsfM98!%{V&SEv5f&H4T77BK(oanZo8 z)q!&A#nq4UJVGi~Mjk#X%FhVXHjf-AzkMH@#DQ$;KN{`F)_)>2|Kz8;|Y@-tdwppw`e0Kun)h*+`;U0}u;>g=m0W z3^>V@)F=R8pE|=@nO_@OGbi%En~VSk)Xst?Q&rKHko!^&iYffe8=P7#&#y@ZjbFyF zQfPci5)-$MhFwOn8K4x}P)ubTZJ?yBXO9MBJ)zv@2lS5Y9JGe@rIq~I`Lj9g81IwR z{ouvPXN?|}r?Gw90jl3Y8LuqUX*;zDNSO_t?$KVaS~0WFxc_XeO?}zp6Mlv_=~)>? zJo#Q_{OhgGXJ{FWW5In#CM3KS4Eko49TDgD86V zuoug4*c_pu1h`Ox5rpYdU+Z?~!V}X*DZrGhy^dln;G>Efol@6r3(AHX)yn=$>F)2` z(Ht+wrf&)|vT!Ic$N?~bncs9$qqzN0@Z8M$U&&#pP`>i=g`G>#!TXrI7od&7PNMqa zDoy-m60^!!5DT5TASdAW5V0v#9tv z*4HE4REWN5GVm5D)@nPsIp$ZPQ1#C~dj)7|y-cR6L^-CU#s*s!pAIn;jg&tbJ^%8o zUugKMShu(q@ii8t(J70Aq^EXt|8r9cXznZ*XPEYbu{uR3LrbrsXmGS>I7ZX-K?1zh zo_u6GBQkN4`L&0>pdx}5;gzc}v3g` z-?A5TlB2L%Y&sj?+QcG01b0ecTlnD?HSRm`NAd-o1K9u~-Z7&)SzuyeHPeLfpsZ@B z4>@83F?iCp*@t)1NOl#1RQ3Fj?4DH>H72X%$eT6UzvjE2b3{A3WA{g>B6D2<9)qhf zU=alnX7-I-IK!iHgWFUCX~n9t@B|5PU4GcciXPr~N}6LzI}yN%SS)>kB2lao#r7;x zY`@zKGIjiE9%K1AwcU(So5=$^DhVafB%dWO@Uc9zQkfM#{1+-)XTHjSo)%Oq(v;|1 zCvRM`tyKV>YHlUC?^Jq}9VLG*q3J`HcL6M?@AbzNJdD^F(<^e;(R2>WWO#;i< ziDs+Tvi>>CAY3jig|6zJ92l?xNN>eBGIV#yxSNZzH6)2{=z+4FReY8%e;Q*G#hoQT zO=I6)Y3tDA@#)m#xOi{JA~&|ID2!5xU1z>QpAv5S`jE(|SjF2r&lDQYuQgEv5PthK zdO}~6+{|H%ntnKknkTv$Ps+Hmaa+sC8yke|j^^FakYZawm)rJBbku%B!8*n}9U-}- z$Imt0VN+Yap>{u!jA1|Fp+Wr#j_NB!A_m7kY>d+! zgquXcgY?z+X)534`s`=GFez;C^s+H4odw8MUm+AoIequ@lIte=&@AgFT2!>;f89SbhI zw9b#H| z^{LD&SzRsHp0X|#B!|t~3BKa1)h|%<9Tul_5UR7*l;YhiXMb+9OL_nPX};m=Jh7Nz zv5Vk)cV~m`3|_?~#aeQej^qQlH%}S`Z-JtYD_*hZ+@T3Gh}!j>bS`pX5mV!2$V;x8 zYAkz?m(AyRh;*RSAvWZQFVI~5a_+EeG2avIJ(YvS%Rav|`94?FXT7>BMM5u;22e-F zgy$UMIdP&KVV?S$l6+7lVe+YL*N2JTmO6W-W$IU z+--6gu=)dHD;Da9seh2-JUE))24&~Q@hHY+KpZ50dd;`e!b8|j<@C%RX__7mKH0PG zSLRi)RImLea(N*q(`79k5CgD(B{+c5`JkXpY=#VEs+TlKPT|kEwH!a{?6QWh%lGv6 zTK6L2J1Q$mR>hG@B;`XJ91?3IZknxc#cLr=n>43fB)gB*<1D9(5MC!1@_wwZk2-2&oFVp8@Qaz)XuC<5FL;zLPwCzCa;2i0N!zCm z{SAuOb42OiDmjb+?9XUeUj8eOY)-jtA4O0=RW%*5-264bxgu7E0AhctW;x6iZQ_>X zQXNz5n~Ujyi5lsy1RzRwGt0}hqk7T&F9@XmRw<;#_Mn$p4x%>GXj&<7Og?aSJYk4i zmYw|JkSnD0?zMnVDl_B7?$yiUY6kw>>k~^|D|LwKV}~oUKTJHGgI+=P=~hx>Rg^M*B~1Yd5pUGP)TkfN5i_bAJgiC zP=cCO<9MaPdNgWcHW-cl>BRzlKrgoK0O^w~V8hnl_=7<0vI^MMERDge4(6&M`_$-PEP!(1;#kn2^W4!4aN1f@syH~N!2Ha<(< zWnB40>-uy0`gv1PQ9WgE^z6W5pwn6E@Djgd*E!0@(HJJYp_YGLZtz`@|saze*C zw^FMu{O+S$tOXA5rI+>OVJFIU4cEjL)Q=>A4pjtdHIyX3e@ z2uAyaJeM6lSNq5{ughVWB1HTFYEr90*vYiIXaCiw8?bf}_SJ2)y2@id-G~w-4s!MJ z$cF7;ywtcldwbKVT;UWFXy#s5%5MpWPKMnXk=790NQe5T1YWM@JE775M-c*gHu@?h z=!FYpx@;^tywDDf1vRDX-W@ zI9awht?IfU`F{F%T%!w@YfAEO_?=N5 zs@2p*{<>UVZIvIoj{-$YFj$WCC2BK{opJ+$;8#v?SzJzY*Ek$|8B)MEQI%1gkBaL} z-=p>OScEmdHtZprIP459$Zn;%oOxLd@RVARc=bq0XK?(f{$So0m+6?Gd3K>*XR{JC z-*u;IeHha|9<4fb3d>lmg4rgE|Zzl)H4 zW|(b)uxIiDflu=iE-`5k9Y2=$d!EF*8x9)6p1!!LAZf?>1W_-%XF!pv+k$40%}Cv z{l_id#X8xa#kt~F?;N*XxDv|brj1l`n=irDOuHm-%>cN0=|sYF=jxYA{tU6{^n9V! z73^@rRRjD~x|9BvcfP%Rq&Dbxr>4&-*t#T5neW&@H~(0kTD|tshAYL zGYXMZBxQYnQbbi25RMoTv2Acb_8BDL8d43%8Dbi6qph&)P`w;Hb6Dz6^oX@|(G9`s zlb3K4qC>BFG&rw)#LmLvTMyZ%zC;pgWY2o0X5#}EX_<}NwQ|<%!7y<4rwErBO1oHi zSQ4-ZXlkA>2ciSg+*o~uU5#(29cKh|dH(foy;i9wT~S*W?#jm4Y?2Ta0(s|MDj|uJ z2vqj-mN!!BQZM9{lF;tqa_`eOsux5Gf6ChJ`1^Nb*EKz_?Zm-KjSi*Do&N&qg>tbK zEnzXl3z6SlN@b&Cwhlz1Yhol)=6m>DM{bGwGn8{u^!4`M#vo>VOD&7G~-*C^uxHX>j<}TB#GcOJK+3-+9&=0sJ(#wla_;i+Xos9yNB(M zm=_FyYW!nG4yD6G!&6eNHQED{a;fZ8IpYKk>yjw~{eSR!sO-s%vvI9aTx&);QmdoZ zK;0f8%v0Zj`wI#-z43o)odPgpQxzDF2g0=i0=XrEyQ9Zj1CR*+YA5S!b-R`22S(j}F*;|VM`%+F%x zwI@1wUnl~f`W8ML<~EDW>>VOxTB`M|w(*-*=5WZ*ee;$4UGWi2J=s!tb=|>92nVVX zzrx94T@~8aO?Y6P6p-;<&N=mG|bN$4;fe*NCEUMymr=s<&@ zpX`FW`xMq(K4b|tQ9*PUOWu!f7OVDfDI8RBlj)PY&h)qlz!@ zUq=O8|3dIg4>ixv&&iCv+FMo+Q51o4K8csiz&y1qdIKucF$l)*qF|A$RJ+{y55Di6 z6-gwPnu|HFXjH5J7tEbU7QyAHtV$Gllq<2`0ToAciEVY=ZQwR?p}2|*pl6edD@8zG z=5Jwk-ZNy23)xN0Iut&bK_9^h=ERExC!i%WC*?$nhar^nJ!UYip?cWqrMKR}mKi-_ zPSu&@3q=c9p}5w6Og)IN$O~HuKE;6hML$}85ti>UTdJ%$Hp7`pS={L5*5iLIm^?z6 za4v_Do*59ilY+-tHN7PDmLol6?(QiGGe(jU(RojGDMr( z#k`@s(W5G~+AZ+wEC+~hCUsQt3(gY>Z2_IXJpy0M>^oRg4Ji&UpNI1?cG?3ZC6Y0Z z)rrCWOahMWx~rX5S#Nzsy~$n>nx{@3-eT+_WC+p_f)u(Mi^z za`r`+oP{&u$cFsO=S#40ave!B(6I(vD>pDP6FRC7OOkZrQ$l`KKr{O#`VSy0*BFoM z8X=8MIA8R6txu%z4*b730}DPi6ZicIb>IXV)|J$7mh2K2iP7a;?>-J=YGQDb7fEda zjWFE>7K2B!PIO4hkl(e!y|LRU%@|`Uizpd_>s3E0TXdRt&Ks67m8a(D;Fb2sIQ z=g^rx;$lpyQc684nneutwi~OD>kzGAZ6UJt1&eTz_I2W^_5vr|{?d%vy6@_J zAc%9~3C5=$Rg5Uz?W}W^&pGwpxhHPuu11I@@bSX1O`Vm=;O?Plg&h~e!L-M~m8O+V zo%4b$r968pyE2bUvhw>QF_aM!E`&>Xg&5G#4#n%l<~)#SVLjrL>?^PyRm0q%nfDL# zF*oC*2D2@t7P)0@z|m7 zOpW?OF{>hcl2F;jd4btQr#BRa#(=;#QGE2AupM$D2I8E+Z%a+W9J)(KR zIi{jZD^BCH3$pD(Jsf2Nt<<>)cn%x(rGgOI$Qg4n0$>~Z$(r#2A`-z4Q~IMQ4{LBB z+dup^pv;m5L=23!gArm9gyuG(GNH>a9o2C2bd~53fo!|RLsur!*%BX<-!u?OXs90! zzc(sgx16?5>@?1WW-Gq8e2IpNIyT$9h%}yb{&d!3dg2L^4EQVXb_umq`wK$@M#y;5 z`n|IY8>kkulygWq7{1zSw1@u^bACUe+^9lvGbR%y)HI1W^_;%d5A}^ms+n&+Sj-&P z(M>=7%e3h)y1!_OkItC!?XTJ>eIimWUUi}m0C*PZ+5`a5f&vQKwf9q_atkmwt zAh5->GUHuHv?A4MDL=1_8cN+yIHCw|&RM^+@)`!f0eXvY5X7Jb{Do^$%`HuB!y#}W z_%Rc%#z%D}AF{!!>ydzO!}MDmwpRcq{Vr)v_Y3n(THkRrxT$J_P=VHT23eD^SKL@P5UwxT46TUPtnbYXmrW5sAxfKkILQo}toHy=83a zn$)X^+^luEN8vzQ?i|50e}Zuv zS8E>Ri$cj_Cv++B%+yAzyM#G~{?TC+7m0~S&hM-IK)GQKCkLOE$Dco`&zq&nXT~h> zu&?znzmUEU_GEEzY6K~A#A?YyRJ#w8x7pVAl1q=aiX?b8S>uj-L&mzHN7%O;I)pRB z#_pkG@q)Dd=QvuqC&J;lPa^1~F4SFE2{V;a>^Cq5?wy9Td90EU4@8H-2Xhgd{peFo@NTD+gyvMTyP zCnKVCI(s7nDkTk7h|{&hkW7vZA+f@GpxS_2W&Y9{94!HqfW4zN$8TnbpT~T`+|}X_ zxq@je-282bgtZdG@dADya;Wl@cYz^b&=cCK~XlKyaho;ocoThax?6a zz7pO1CI1-Qg|KZf5*KSpwrQw(=KbrU-gCXpu4swfwq2{(iH=y|qQtYIq;0c5o)b6> z;Ya3W>LhXyV%^2tqPv#Fn8w!2Ud&BK-{P*X>(?1J;_^7v`iC7j_^3e)=|4ZImo`8w=uGIY+GA44sDN z2pD=c&BMc3yc!nG*R(YvEkIy=sTW*Th*4p&Z)q~#OWz8nU9+$g#o@}rU+Sd%B$YI) ziK}O>roqjctCx737$4Ar08(tHKAgnOsI)Y9PpwYcNtM`YucG$gIuee~CT<7OO*F!w_@)E75z zzFqDQy;Qsl*#4%`KB}?9b+O&_t{Ofp9aJjAYN6uqQHs!^f<6?3grmiN!C%h1EFfSq z$Fzpv!NfiiVQf>TkEf!(8w>N(_j{@RVs-y@2#5Q=QpuNuPFhDvQ7VO8G+#VhJv_=< zN~}UCpD->YHYtCsn;40h0UvQ^m#$nr1oqK@t6x6LN4S%F|+w9B2|D4u^kiJ)DX3@w-dxo zMlkGIeWXtU{H}kg7H_3>QhR&YE84W?H2G~`8Hr9Vq-RTbDDVbS{}lFx-vFQ7z^00r8w!s5*!nbxp z;1_b>Y0er7O<()Zv>#Vy7UkA=ROLsO*W`e7hbC9u*`?@qFSNZs-pTHlM0yAD*< z>=T1BltBj(2+1Sa5ppcPA^VSF>FD4&uA~R%GS=p{H64>RPnt4vbI8;|RwN;q>_$1n zy_LD9!}3ysXcan%`7XDlmC~xhH_4ps14}UyN_!}_uEW(3ZDQ`U_U`ZW>A#F8&IKHV z#$aO8L2(s4FG*D|#m?+M~$q@y@_MM?j~*Wlq}iY$M$FR^hJa9)0dl@5;+ zky#9b$Eb!!`82nQncphtby~^HQ=nHIgS8TyF#MNy7)C-ZL~u5q0I=&|i4KG_TcY$9 zBBK0h_7HHcR4w4%Z_+6p=+bqGvu3m+sKa%P)mZ+kf*dyX8B*ki4clT>%j3=kg+mAW zlyaF&h)|0Tmx_pO@iSIFUvhDrYzG#CK$x)zIURA@Nh5LixS}|M-_+B5@$|OM2RhY{ zBqyG)D72dm*g}uV6F;KYzowfy`o7M8Usac3aI~BxV4p1~6bb4k;n!;HIx*LF5_qNA zO8B#EoUinY)&I_!(e^Lr1ZE*Vl{LB2VWb!w;Laz!T#p;Dda71n3`qMb#T%UPGyB`j zhnt8+`eWUrz1%q;mi61J*GJK#xvt0$dgq&J)iRDLEI|&Qeavh|xXe7z4s$_YshxtW zask=pgO`c>gWe;Q+kr3nv&$=|X~3$)318n4Gky7w%|`)1jm|vL&&BD2`%~>GN13NB z{Vij@vkkVYO&oN%*VwMPvC!~=;_elWCe(SgKB0Uj(H#jKrUNH70a0q4i-^XNo1Id6 z*}g0LT$fhQY9<0^|Jt|uj|k=wH>_?e%BWxrwW!}`j3;rI;+ zZnKd5-Lxbo!<%8{w%&ZK1q<c825h4O%-wys;sPgI|2UTd$^C7g9sh6oE~Jt(x)k zM%q_8vVHLk)9hVA6$-wt#a^)x7!(*4^>g%)N)eLxB(?8s+-smihvpt_-FR}&4!xV1 z!lCwjhw2>c9LycsvDGd5uivMJ&PaR_cYsHS>+x_{lau8)q50Hvzb~lr+-FNP3F3at z71=@5jS(TDsRGoo-@B^tos7Vd(rIS@cu0xT=R&Y=59kd=t1g#KZcN6!`!mK=qlEx- zK9h?f_LGz2Aq9W#%se33iNxV1KGc3D>xIyh3S`x}bmV|qv2yKl_~H|s{tOiTFyxF? z#lVu1;zjsJE$g$PuQO3@k2=g^q2PwgaRaIS-sPv*P{%CE@gdl&UqSu~4EaHxcV|OR z6rm$Jsiwk$m~V2KL+kd&zsCjr2)4U}v+CzR(VLR4fVJzh`ybs6PVucZTxUM!P2%QJ ziMOKtKyBxy&(iEMUiBX|95^aRO>~K0!{k^wU6eJ~{uJ;+Id7{d8oK~_3?a@?`C4i|GyLzecjMHY;ubVMek33XbYCN)CSiX zOaE+Sw+8o7pT5zzTK?e=f|w7-Nypui&)fqQIzjl8;4ka>U6EC<=Kt(v{g>#ds&TDI z;}dMzF$tiOuoqlde@gMe__pnrHp3`6+=S~bylo_Q+>7?S4wk?@LOP?T`Lndk$+bC^ zqdY9tvBr}T%y%rx=YVh7p*LgD8=+n%W8CAgA_1(A+rhG#_W1+7(6P|PBwzK!C14I? z==aYt)wJ-kY)V)NQk+0!=HFO{V|AY?`$G+=8LeXzU$S|kDpFW&j}I!H+pQt30S)h9 z8D2jh7Fn)Wjw(=mFg$q#Conan%(Kzv8C?&sA^21mK)7!rghB(bP;aJjWmXb|vLc90 z4FhV|jyPmZ<);=^eqqoR)u~b0VHqD!n7vq=hd4W!y$wQLKCdp~^YpX_HSedX+h-3r z8n!4L4n1=k{4qHEms8GHRs@An<>&mem|EI!C6ZLw+F&?c7;C%Tr{lTuA|%Xc%)p=Y znF4t2Xwi|U>m5w+_PdABQo!0D#d$taK5BRo42V7ggYFIqqjE)ir(I)05Vr}X1>_3l zl{tF5dU$$l%Xy?Y={C4sa`*X2qj{1Dkzq-^P0F?(lFe5jY0+~>GZ{>5wqcx29RXi~ zWhYD4D|@#M?ZSY!0*mtN;x7AD0`)3u!*7d)O=ZkOVT^O-Z1~wNKkhQ-prsEDP6SY@ z4NGP_z-ai#$+UR8 z{;>6^Y@teWtVVPls|Af#^8Ut>xtJjZ{!yBt97!PhaGdk-V(FU5Pp#Q$rNNuF@Q>>b zB?^LqOpMjAcq#hSujfWNv?TMV+mm_B5(A|+K&p-POK=42kZF=yZ$JE@GW+-im!EhK^ za61)bdj0kBxP>LhJwX&<1_gL#)fjnd;v_wptu{gHa}*Eel_^ z#Bhwi6W_(`z5Rf=i@=qtDc2mdee_%YF%S33#;)!M@$8U#$n<<>!n|4^!Za|W zZI&vUpq1Vv+Ma(jOLdw{$A{hTX%JTxPFnscphBnWyA9H;iqRLGX*w+b^d=C(AN$Tf znk|xKxem?HDF_8iE-!ce{Ni|K=}P7tZ<42m zV&4MGm_?h~_f^y%wrm)-5y7yuM)vYf!3Yx<`#g&2CG%$vi>boS__EgzMQiuGwbJ8! zXtRyD&c_8x7(NZ4A zSM3NVrJnw_-uFB8IbwjkbQY3@Fq+f-5lEN>76JxZT`n_J*)(na*9%8$Blu$Utg&tll7nqq4h*y zHoSM@i!mVv`7ZfU41mE;=k6D2J#X48-W(W)4%_`_~@)_H3od4i313FZ9%~hl4`Pln+0? z!?ZBe7Og|E^2x^STUq+05y#;svM3RqC+>|v4sCbPO-WO^toyA2|km@K2tK95W5F3EyRb8pACJ_a~2hl+%^e)Vg7iTQ_ zTJ){5#lW9^Q9s_SdP07)Cej!OAlhd}U(m(jh{GvS2UB~w<= zzEMP`vF#B0Vm8seI4>rn@Yf+B&GAh2=D^IVkD+?ALTCp(Z-JS6H_;~0u>K?k;)==o zUIg1Pl?6|e;&&D|+o~9t;EgCf+xYh3X(nxW=LdRw=gILRz0tp!q{9YkSH9rZg zyG<$AtLv=sZ$>|@x-kY4QN19mkbZ;cC!=d$DVE{F(&jBpmH?ny$!0&2?5qfjCe8SB z22M)9xuOxOrc(OP;(n^WO=z&r%j1pa8d^WpwfOl|pG_J(bQB#$;C;c&!&dl9j@JhE zcp4ia7Cb5;D;keoBv65L!xQ3?=-3JREXh|VPn+FIzlw**wR7Yb%?y}j#)+18#Y{g8 zUFj_xqkR_&6YAI-49!SJ?EuK{!4UkzPV+PY{?Z@@*h+VQk0u*Uzuoitc>F13mb0g} z(~%E$s1#=xDl9)K$&v|Z*$snlr0rLV^{EZz>seGp!#>U6vjOYM|CFgmy)=9g1N@z+^ zn)N@FF*Ua#qpP8-ay70cpR5gWd?nH!fLd)dq*H^Fu;fz1^aJ z6vzs7;0p?TLfpeTjpB_wUL14HHO=(_C4LjTIHMswESIx;72kx@6MeF;I}Or=84IhdROPNB|cG|?hvF6h@@#zQKrDF@9| z&i7z_LCf!D?rWokZbkd@d8Doo8h=;>GjNk7%VC&2Yw<734@$akYP%RFfrp#?t5o&! zF9VTo82|WTK9y$iI#**Dbsj4~Oi$1B-@B6fE*g6=aL8vDNI==055(n8h3?w}o+~kf zAU2fq#H%gNn|QXC5cBoSaelK2tL}vp4_$~yZwN&B(x+jC_)-A@hx7qEhbvlhJ9xwd zY!;fdl$w)=bU^y-b4je)?L=4?1Spjg_1FlS@k7z6@VYvw@HlxAN(_YnsNA7)(JXtY z2xFDF{y#JgzxI=}aG6wYl*@E$as|kM0pjG^|3EKN#2kF2c|iC~+9|;8}^k z9Es)$%6nFi*G4j-0u!n0MZmYA>@9&AVODq=O5<5)veh0+qDa);)hymdG)^>2tMREC?rUYa_$xPAZ7GG zLu^L0R96?PzoYCr(@2J1O4X6}He5T63Tu$O^lR}Lc&X*4>#FAbAkaYaF@(Md-FgapTa84#Zbc{%OxDlfS@QbS(~UWWGf;xxfdh7B5f`oIBs z4fXBFiH!h$$mi)GAL_#Sj;TNTyoy5~_vt zuTqRg`nY@!;70QECnqXazGYk3aUoD2tUGKJ5h=#fzEuP1mB>HyB@7b(;&H}N1uDP^ zM@6L0lvEK3^yav_%QDq7bd{;#$1hD4D8ci?ErFVCOXu^6zC2wSAJR6b89EnFbZTRoJ1U^Uht5#Mwc)Jr#?@$#1o zMMSJ+=%w94|4#d-X6jMw92j3go6E zeHsP!D-u{cF2>-yUkjy-o(I^A|m!)|8lU^8& z3hGmbzMRq-jSu0%gG<3w$Sx#wP>C+ZW}8f>T!+OJ>ZL*M^1V^mKn!Tfd;-mPs?tte zDlZuka?{xw#Q#O|K|3bEd~xrB&isdn0XDuB;`9UM=p>*cEAQ3kI}BJ1*dAsytCZI1 zvK>6c3j*}?YHJ)$RYN4p{#%u?Xl`p5hcN*NoPtEaQZZ&nFc^B$nCS*m7QM?@hyV#x z+9I(4UYIkPdm#Y68?ACbkyTr(t6^Y;0SNZQHhOHBA~cPGhIBZQC{)o9{{Q`}yAI zdq@7v7#Ua2zRuoz%{Aw5dG9W7$ztgSUKFnk!B$z^2y|?0RBEYJ%F9p^@9kdyYEUH+ zSZDKjetDP3h>C+;MdZK~$cGAp5pe@qkJlBBKn=MTHPC)tKi51dLhD;i&Qcbv=RsKk z12*W4)y7iHt2jEOTro5@a!jb#IAQp5rSgY~j=VSVMs+RGCBE!2TBH(cKgmS8j9nH| zJ<}s{iQ3cnFuWI1(v8na)nELCw{)hYA{6sY-tlw5oU<@uKL16;3%8gl$QPMkt@3$Y zD^TvfM!u8r$~F6o0@f)75xhla?i+BZKQ`CdJeY%t%q}+#HMSSb`9WiNFfk;e=!HxZ zR?5MxfGo2v=O|YggVNRN*~EWB)npd}q6m@Re5bmNkl|_u(@0wTzI^PXt(;Bbl>*@R ztt05>Up%p2I2glX@PMV#{#oRruMog6NgnvS;0pmf;zMEF1*74e@T4g}-MIDb&Hm9s zsPiQl1!6Y_BV4Dn+(l0PlC#@-$~AC~=USN!UU`7I0UBMcxS3P|I`@)BR^tn`1kir-nG z!ktg;6fNy@RJ-mccPAYbkX@@x14<`(%_KXd7Mc^7#{`ll`Zm>~X&Q~U$k|K7ACybgZgr$3va+%bF6P!ux z`&*p?*>4W-=wp*|)M+Q=b4h980_YNWDOiKiGVdDM~8B_8z_hp*F-oE!uS$hu;|B!FiLu;CouJdqZPImxlg$; zRNnLe3B^PqZoH0dxM&ob57FpEnxct*M5Ke5-GNH(H*~dhkcF(COl0jIaxaWV z{Y44*$AL^Z7+kqv6q_&70s)__Bs?#L4vcROr%V$&z1on8fDnnE$KGd?;kkJzm_|%p zcR>xW=~KH#QXq%mt&M^o-lV-${Su0|$$Yr~$&q{m#(=u~A0=vAd(DEG8(_Ir*VhUxiG zT;l%b(#SYOR)XfAaDK_Ru&_}5d?EpNN7^o29tDDF^tPz5ot-cdA31_QSFn~u;UVp} z>q?b0D}XokOsAmol)l(Xl0(^MaK=7ueZpWdfA>|PK%N~Og&eVzJPyq&50#5VooW>g zzsqS(a$ZY~UhX)^+;02xF`IJacFLTIQl&_D^dD!{{|PYsfeG=@CR%bWj?3vAarTy8 zHLPejdQ_8wd|;Ba@Y;H=#E>Z5IiYT*Ece_fMqfVoZvf$w;sS?JH@Dd_f(PNv+DD#F zPLrA6E@eE8S`~JJ=UUo?aXkG?P`lfT_Q7kxSd;%BKt*77@t^-=(p?2|ZY|K(=5hEC z47nA;vEF>>{PY9}%n^V$RZIdyKL$ybAK1HBv}M}`A4o?7055oFKvV$gm9dxH?0ydE zSaBm1+erGM`KECwA_^K_XE7(-m^!`TwIw*)O~D~*;ZOl9d}7yYEM2@6VllZCx3cAMGvrX7QWZn7$r{#l+9Z3jnrggU1vW?3jL%Z*HCf+FiA3l)v=WH`v3p@Z4%k*B}xm!FS4G= z3Wqc-0s@TGo%{7{*^nRc_hgx1Ju&l!>YgMQ9Qr!`_TR0^@Qn(td@Z>ZJJ{|CAxppB3xs@;hy)};zww#$)= zOUdb!i%%LT^tS%zMSY=};OzLHK>M8%l`>vpS} ze}A+SsH+qm(fBDXOXWvJRne$%)z<}AVVNt*v%@1@2rCgvW5K5;+q~TNsBk?zL8hq6 z9uLjdb4X(Y8TW`NB1cVA<|t?!@myvVB*<8=K;`p-D1~APtpqi@xKVyRchn;Ke5S8p zqI!JTiBof*S8ZY%qL%!~G69{wmtj$;r-Q>U9nFjDdw(*+Y4zJ89pdaT`b*~Bk{r_v-B_x^TqeO>6^q#`{91)4w)*F&D;uabZFccqY&@k7{6Lv6YM zt(*pQT^iJ2A;!qQM4u7b26WiCt3VkhkKTY-eC|jo`WU;4X)W?$rywXq)CHYnOUD^p zdaVhAy`^O{`0G+Va-ZGgEMLrq_rU4B+)U)o4;sm|9OrrKHF`kK&r^%Aa>AG6A#QYu zwn?C4CfKn^g!#ATCnkGz3?3iEKO^-3z8mF;9H5ivL5C zrY4+zv)a)cAs74ECC`PLKKmkOkK#qkT%f7#)qlWP<7iCAVMf8WoNb_#DebjBxk9Xe zp{oA*v;2SYJ_`2_O1%z9v2Zt!TghzWE!r_w2tup&J&428YfT54X=OMNVDsk{?N63n zZtUI<7w9v~BCRi1BR{e2KXtH(0K0E<>3`BN4m|=#)~ex3^IR^+l+1paI|`?qJyU)B8u}!bR)6T8b5IHGRG0CC^@K5O4dO&cX-N))A%tvLydFAKH1GQR(avHPF_)Z*fo#lJBHfdMyh;p)V zRj>=7kIne;%NiRx9%9kbR?)e#b3arQ! zzJSV09EIGy#j>kNZyWLJEu?Lw9&b8x;v;*B67q7Rd*YLZP}ZI^m|a7WnWd zS`Dd=|BTR~`8?mT>O}#t3RO;)JpQ0zDT(iW&{~8`_O2f(fh;Nx6Jwfa99Bt(h3y+c zBUYM>@=Ok+-q|m?To2M+o)|{_Fvy%dTft~xuu*_-Y7PzenvH0pw4zxum6%)?P=kM{ z8oP&54)pMDP>S55$??SFWd%P6j3+!q1BRkX;49-;Ll}%XeS5a16~XGT$l&|(ka%VN zYC9ifmkJJ#7@mA7rF-Yi zeWJ~sX27=#2@k>%oy;P|3iT2d2_iTj&pB>XOakvth}k8aT45b#jQcItSvZQ*u5bfW z*FWezubw=avti*gu4|!d)6j}k5tubT$~I}vU>uK`Rw4%n{1_f#1XLwb&>_pkdd;te z9nkwSy*8JTF?HmhYC{om3m6QZZEdUs4H0?$P!`1S~W zNA#K>5DYBJq}8mIf4!gAvV)bK#uhIq3MR}XG9(TMNP7pEc#B91$46;7-b3y=+K9E{ zam?$NI)>i@E`66R3dsfvW6#~ldZcdlJ>gSUx3a+1;(D`e0;AEx2Sev zsjgCAv9~?*9`SRY*?NL6(;MBZ`|0PY-Y&w&;US4WS|u{MP0|U7VH&lzq$1zmDX@fk zf#N^Y6EV^Q&rH)E`rCX8nX+1{$CgASA<0)kExJW|1I^ovcoRoIaoAKnv1P{F6gde= zYZ`49Y>F1M72@xXB+n9q=a;b~l-`G9ew{2t%1al%r@Ti@@O0*U&MhkgKim^20ukJx zHSo0(P|w7}agPAM0#iT1TES^#?{I*z*w@?l_{7X&fR`kDZ~&yFKYsd9z%_ON9)Z8T zfCeI&A{$x342!I(1H!(FrZC?xM7F|f_hYellG9#Rn0V`P5ZNe&3lU`qTkwfs!A*v0 zE4zta!6{AfRXD`M1Offc@Yn>iMtE!erU@uKpPQ*;5vi;KhhHJ>aIOPgpt9hsX1%2T z^4%F+E+yO2Rgc$!8{)FgppnEU2SSlxa4Gq9j&s(>7x+753SglP7`o3SyV z*$P<+=6J=--v~M$qT(@vJ&5lF7-AGf+@6wxAjD>0)pu4S-$00hB~BL3>plNi7}RXv zG6vq?9nBO%tB~#S?j+cSIRuoy6}etc!EPtc2U7ygr)uoky`?9egNaa7@fiDeX{1v$ z3Rz`n#G`QJq~u`mDx=?|H#`{8SDLk|2JTQBv`wS{%}`+gP3t@k{je-h_9 z_xDlP@%7W%xR(}25E_`$n$@oMealTm`EG{WB(Nj^LmS59;-`7>B zM_D2jNP$)aD666%dn2B^|J7AJSAGwXBq!JY`Xz;YId`c!b^WndawEcG*r^EV|4`MhUDFcoBWmg=u4coAW0U%JCG$+M`czhM%VMAO;#37MM z1;LFT&)}vG44Khr1Wm`O_6Tc)0Sm`5Zl5wBLfXA|f~}odeQ>N?8Q(`(HP3#tPH_TF z-zF~n6cGLZyGlMv-d!vaRx~8K*6Oir-%pMe3r}KVeYzx2!|3t2m)y2=ns5McV2YKT zb+CMOtU($=_{_k;K*yQ++jFG-(bOsj#b%YfuZjGLlYe{JUjFb11M7jEZl9K} z_{ul#a&p|;pel4H3NT(QcPg$0mEkDW+FVg;id)>ykhN6lP^@$BsZN(@?*<>i0V}i# z7}?DW^>t!uN!d+{c6}S*T9!PG1Y><;wh&LRZBhr{Os}f2Z-k=wq;z&@4uXioA`i{s ziND!0YgI_AlV0D%@}Eua`5(@WgH>!-0(=_@84(`tb3>}S0j*V^1%8~wob*6%iOUz~ zbmvN`WI7eL9?mYYR=5yl>y4hdD$qYo$oy3^pb5WoW**yS432b{SaNFtPElLD$OI^v z@(W(omXJvAIjMT#*zPcin8zU`;QkN{J>@EN(lumAaQqWLAIf}X#xsTCYoCb~M(%*p z@IEawu>Z^Vnt2W{7&=^>L)0wYA=LeT%`GTb1LzscU6>Rwo>Rf(CfWTs$Iyu`+9=># zx>aREpcmW=x#iwth#d=pvs(fR(A8Rn4^{O@nI+Ls@WfP3CQ{r+lS$7+rPOD@`OhkD zgZ!wZ6Zjp}!-j=+QqmKK$=AQU_6$bJl?oKa9R`jXqa1?w>z?LdxmSW?d0DX#g4$J_ zg7PM-ciEDI_qW_GpUKFQ%^P-6%QGJH$xP1zbIU*-B+cmjogx+qJk@a?-Z*-vKn50h zf?*^JcUu1E3g0JSY8}|ETK&LGbxat=Ls4LTh$3OQb9zu3h~{ZL#>r@C)KlzKkjr6@ zzX($;Vd@ku3w_@0k4QyvpS~%KP|e61pyYichTNgwV}dGb%G2RxAFv}RTX1_sUsx7y zoiiwtY5nzfh*|{2`m!+7Q&Iyv*Sc-!VuXLj?FLcx_xGcNfmeX;_k)Dd;PJUmuCO}f zh(n>0EuA=NfaAB`p%aHHc>{&*d!NLBm{687lj@>?x#(DSeINy3OxB3FVljf`O{sF` z>fpHDh4^`nCaTuE)oPSk9hrqFg23qzQwpDdf)$E64Ct)l@xV<~c0CW5(J&a5cZ-`j z!1J0G5K9-m@jdwgr*LF;Cmt=_czPMQRiT`uBa^F*6jsD{!a}&HE3?wtXb8M7F7&e4 zys~R6Zy)NWaMA20vcseW=7X5%1h^lbz+0{|FXjfs)t>8(1gWyslIq-VK({J3v&kloLuvkrBfa4Dl$WZoeJ59zssX0Xu!0i*TLkuI?|CdY0*R zCZPaFRE9lxK6~!0-ErldqW7E|e8jO2=%2Xb@_`@R!_Nn>JWRe~ zaReEoT(<9!`9My~@NWpFF7oU1y_ykZh;3O;NEgtas!Xh`_L@-7!M9FA(V0O8j3>7@ zu_(-h=vhmr4C{={R*v`Pggdcz*B?Mo?QfNQLE|H>o|lH9AzP5+P`ESz=FOMFuidDh z=JwuEoS3H-54%QI@SeKkMOxacF>AWPe6p#f$ZK_IsAz_;Nk{tFuXwSQrK=B6FcmowX_d^AR8I`-*S=iZf{~kJ`aQUb9-hWur^0frjlUoUZq(0> z^mV(v7u<+2930=z3?EyW`Q}`OP=h+;y3l@vdp;PP$}RV&>tw3Fml5g@Z>2+qJGD9s zGnGDv4z+-nc9xNf>>oy@^}_xSjqUVb{_AIk^PwoS^9Pn^N^?YpYsPbzOl?;8>xFYp z27#~%9vtCxC5WP7J0qz}Vg!gGbEV<)v9Qn!l!oN=$ z9(&4AWLjnWi@Q}4;5ml2wj2tq<)k^MHe4IbBSZVV5Qw;+ou(MC3uRt5o2w@Cz{8L2 zg=`{|?f=NEv^`9bD5S4`Ab`7MD91M!_;mENQex3=ae|p;zFUr`>iIf6)5~(fI4qBm zuf;Xqm1g-u9|SUPt&d$paFXM8WmOrYN!Oe|Fu z)`w#oiipo~ryST252zK%C#JSpNX1_GprZKFCiyn284tp&A2b+P38cea>M)(X_On8u zlPLIZqyWd0XXF1IPhj8{D3}gkdvhoH`vg6)Hg7OgIdiGgvBX(Hf9X=u)%OTocKSM|MP=q{sCbTpaG4d z!$Cfe_!8>BO*_0HXo$6YPCG&^n|HGLuZHNu1mClq#aLPRYcx~VhlyWd+J^_uaj{Zw z`*YfXYG1`=&gnnZXgwAs8T(~W?mW=lI0VTyj#MG*&0x5W1geS!BAy#0PDQ0Kp=8j1 z0%U$(hhRsFy=*`K(_+<8@>Qg&;h;kM$}1;;R<6=kgr@2(ecg8$+Tl2?CY$BC=eg0R z_db-$h~@|5c&F5NK85@wzKEtvRw6TN2+gwSb1FlXR1uETzSRH-kCqFwpe+rt4+P~=b#)c*XH%Kvaf)Q-&9#99ZI&fJdDF~ za|bL+>+dr^IXNN>J8_0W4z$2_;|ZJ>D97D`wv!AB&0=??h%5ca>lTR*^+!zmFp1a` zoz!)z)bs0UQ98`fVK9^)IlTIV+rjzW6Tn#iL;_#NPNX>Uygw`N zbtB>$h$F1@W;kRFxwmH<3Gdv(`wQUL5%KKE`6>Z!w+mN)1lEo*z|6|YtSW~0{YLaQ zjZgo<XrK%URwpzh@O!~`(9Q}A$Y&xP)_%Hgp$m@k#ALAC#+KSDXtn3xp zr%t=AM2_Ho_5yqk%#F4O_kPDqhijgjKe%LOTQt=!w@eBE=%9M@Z*tyT5#tcsW}0Eo z>VHg|J?1_0DkHsxye)%l%IGWe1>{(O5uh*XB)l{Lu5&HqF`bf6Io&BD1wdT^t+WsZZt94=sap+J!i%7ZhpN6hGkW zT|_HEQ&OOwZjKUaeFvGtVhSi(&RPENw$uK>4-P2zX5$zP{e9h8FsZya|McmhZxWYe zQnA5SXD=oth9g&z!#K*SISCP;X@K@1{&=~hFNL)GzXFVPWDR+EA{s&w&Q64Yb}Z_ zicepQ_WA`w2Tz~TH1rdG37$zcXP2H7p0^@lKWr%Cp%lP+_x>RZv#%1C zOb)F(TpXNry_5u)zs%LIBeW<|YBe2Cg~}g;m8L5@qOW=x#27vozbI8ypW@;z9xXT; zPeQf_{91_sx^-Tw@d%O@B8QPXh&!=t=J9r`sV^rp721;jK zaY-<|?0KJhPoAM@!{!0#0P&LP^(&_itEjBk-yQLcIjCy>`pgEJMQCLvjp~xOBjT*j z;(&7CMWol^0!fkDlyWla>V96s>-VQ%dH(ZqSjShy(H1;O2l<{Hf`?rYC~Xjqo0oIH zcU-I_DcjPD-~S9T#?T*B^%UcWYKsB5Spb<;#%5BGY?f&4;CTD5!-n^0Co85_rk*34 zL=3ZdF#sx?2P(U$pdX?GKM-KnO@wpd%Hz2E?QhkT4{h1HVh#iu7l=;1ZSG^ z*>4aa7sXP;*wagnYtx7&U7v1RGnEO5jlayDWVA&rgpqYQe8A{Agdi^10CiHFIwOtJ zU7*l-z14$C;rA}AfnZinbo7o`IQ%dfeK!cql2IHlfavxwGT}+}e?xlh@=`LGj7DIOasYD)PRHE9go6S^iIO%i_ z1&6F@l$9CBV@Yfcu9WNU#4h%4YC|m|Q3MOrQ^jyljDo8=(-tfLmpzeYo2}Y{#<7nM zgcZYIAg>{Cm1Q59iRrfYQ-O?23BbS{O_IHZ69N3cvrdbI91!l^^YY8cQ6;)51EJ@p zaE)y4^K8TjW-Ie$==>6^vq$znisTD(BsHIlWFxBr=xPI6qj!j~;JE5>)5yU0r+kAa=X$rK;|L(-GRINg zE9}d4cw1karPn!h1ww9Dw49-S%$oSsvv~@Fl_s#jL^)b%`%kbGxa|FqD`DV#o&=be zK>nmM0+p&Z5ubDg1g>8r78gNbb9i|#WFw??FcH>6b!sq?zVO5mZ*SlcRjQY)EQ6W|{8LPM_JF$3GS3wPd~p^?{e-AkK$9#cs6pba2{R{^ zJK~g3lXw4-<&JC^g^sUz-$51GIO#B~3>Z`ACsK)#O9L7wSCKO4)~r@}Mleue9^ntD z;?@)*qP&}i-d>h%bEmK|qxuiD;}vx{cm>`9&(XWK$>_T6>wR7=`-V^)dvtS+1DO>I z2Sr^J@8;xw50{tTQsM}hmW-GS{#lur0ZGXaerrc8cMb8)<#Wg0ai z!2L7PMf^;rDkSxCwGB|51upwO7SQf`5$jLHyuSn|o4`KoCj)8M^)cLk>LuV{nuQ58 z0Zyx9V_a7nT!ru`BL5=6dBQd5D}h~dw9Q`JY6j_}?pQHAgqj+Afj>EVKP1+sWk!rA zA{wB=hbXgQAvzlCd1Sy6y*Ok+jCx368snIBi=efC_s8H;3l*zX>RSH3xEi57BAnfDRSLo(MQW8hpweFXH&dDAr0|c3XZ)jCvzN|1__~Ha> zBkwJ9MzHaRZpJ&G2N}8pcDZj8-?EIKSgvQeQ1(g|WJi>#xS#X1Z{B2r0AB%<%pAdw1s*FGSKld0Sg& zC+>TJr<$v5!RZ<&pMP|TSA9q_)x95)ZO3({t(FJYAJyowZ}`SivS*7A+$ui_AnXP= z3g8Wr;%sUX(HS1=`%AHfg-cop=n0*O9l9OqPThCX&=t;xtL1>ex6Dl(gr>6pxkTm< zuK^(!7aq9wD(q=h>ou4x6%au{p@zXXUgsRTL)BQXZSs~aM4Sx@34xSP!4XlY9gd9f=%yx3uo1$hx1AYL$7dU z%=2p_Z=88$AtQ|~649wZ%4EegH)ofjERC17m{J?SL946|OT1%1uG9}+)I_1{wTs~^ za%L>#ay7zrD`?Gv$kjnN5)RQwj@5{6R1_8C|dX_Y4SR z2}3j(hb_onQz8+LHDV;$B<9c9fhV1ziDNuz?#^89m{8VSTMV5R{#b_B7GSGTfDlS= zuw(ThgkEQ|8L`5x!TGMzYt~XyT^aS?wurkDRv_UK_;^svEAbnCym_lGJr%NTMnHOD-Y@!;x@F!`jk!hK^y;8csZNQ_$`Z(U~)!)=PMcv zF1?^fSRF4V{(093FosGIg5JR6hb_Q-1hdkKE-V5$s~%)^zt}92P;Py+i&ex`9i6Ig za;VysCmmiDa>>u7nNNBFX$wwLTP+K8_AZy#`aM>i`*{9T#PAv$_E#~Jun6FZ za+ut3Ox?Vc&NBN2b~`_1^CV!q+s?~oCGPeU9ska@4{9+o5|Smf?GY^0*_6P3N$I%o z`mFw(qDM^#Zz>%Fjypd3@Z?*LP8fu%@c$ztxMjfUzW-f_U?^Uhx{U9LknLIjj?qpx zCjnl0$5UABe6+2Exxa9(aM7fq=?3;eWVqo)Zt%(L8=j44Uz;dbe>txPkPyF{59HF% ziLEmSjVo%(L46IHe(?v*f4&1Ld&l}CK(p9VK#p=^`%%(;;y}og(eBg~?TsJ|2K5)Z zg2dF$mJZ&oicOepazcyrrp$Cace5Pk?q$80EXL0wUI!JhK6K2r-c=!agcb_)CZ^$d z6gw9}!%XiynPJ#YyYEfo@%ZEZ_IS_-U;&)Nex<+2fm@KO=xJP>tVp_nkFc=!ex;jX_YV@xU;F7_?@kwy|O zKPb~C`LKKZ(*10I=R@+?TS$&5g#a z;UDw5+T$$yYx=m)>ms!knkch6pi=ZSGY0tsUw-=*hz>`Jov%Bk{F^Z6QIC? z6_c4tiGOP#kbogpHpVHX0!3814sIW^HMIeeQ7tpwb!f}-d7pFxSkfbqOpz%clvIV zzoC!J2>b|{Th))ZdS+68HC`*a`@WiJ~8Q|UaEuR8<2A=M3RfX&q1SLvXrZxxmz<7 z^j!6k3p!~2QQS|7_l#G%y?2sjA)Xo&+81k;R8@Gyaw=$a+U_72p~?Nsm}VRs5*?Oz zASt@vJjqN%H^%OFbrpj7&4EyNm~@p9g&;zMQ?lB+eORZXMK=KHRaL!b}2>0d3)>B$t<>+ zIsUf9JIZv_(!F_0ZbyXK)Mczg$&Hz?)2vUpih+unbt=Zj*>B$WQF-WE(5tJk&_h;> zM@VMiRsW4bYvoZTtXS!w6hb|9S|Oy7OHVtTuxZg&Fxo)l6nnBSt&&xyS>VYJfL1C_ zAg8$jZ~14IZ$;%gX#@+FdXI{DbV=frWBU=jmY~(TzfJcMy_NUiR)U*x=%dRbg5qcI zV=8&Fib*<|Bh9SS(xWWSyht)l{&KoL=#Trv-AxqFdwCv(UyA8iucTGFU!(s3Jih2w z74W>^+taz%X58hBn=2W+CZ8&nXGVeLk#yFPhw)VuLq>*>rG>cq)3n&^QmRmX;lkK_ zXiO|T$q5ll>IeycWk?Z#GcZ)pD4Mnc_2kTiX+DeZn1v(hwDLC-a~c|gDz_LT;fMQE zFm$jQb!UMM(tDS;c1gir+Ku1krNnVdCEkLMOQ`$wJIfA(vR%7HmhXd~9c{~GdAwdkIk6Y~~Q%pi9tTIhpzFli**w5Cr5Ze%TcTJWt zy)bjrwuoOwci*=7D%m5q53nXA2!Jm<$7kS=(nkJOZq-s3k}3S&@Nnp`J)Bn(LWr;Eld@dpw7_g6zmw;SUj(NE= z;|gOZ;Xc~AgP{9!@uz^#5UOXYyLLB0mpBX}VEAN-|6|kM=;-dg{tbpy~?H%c75&lfHr4ys$6HYH3C_hlXnCSCVfq( zhO>|xcE1aC0H2?~<@4v7rR@}MZu{ySXU#L(NheaOW&2>F1cM9p?(B2aRpim;6|cs@ zDEDG;({+3~ccSTadfAt1TbKfDMaD8Zr-`9%kz*7H2+)r`Km#T{$p`h#Tb9f4$}wHdj&7v#ONJfga^1lQIz*5_0kH-^%79{@!4}WyO<8VsFx5 zoyvcRjHI@W-bhd|op?P5O#PD0;KG&@2}$H#GC}S>>v;FQ9c7+C&p%cwK5ze|$6%g9 z;@h2^b*7Y$7FsOlyc$r6rsMqFQ6v@mUaI@hFjTry?)g?e^d7%{v~*F5&1teT4Wrs% zJgVRK30gO+IVK}XNz8XQ4g~5RiRZ%KVIVs;Xb_QO4sPX6NExY&M$nx~9O~F>(Ra60HY?EC3Mzn=azB zIGBA^56r1UE5=jno+*@LukaQ23AYGs>Xj9331~>UR+;fDxqB;Sp*Z=xWA-bAAwK-F zrNeR9XBqOKu;eIzP36Fgknx~bqEqJRIpLhO!(ejX4yp*=wpD5C%<0*$t-=U|N7sNm zNXR4iZ0-#DJzI8RJ^TXsCV7LWy#8%Vbk60*i0jw|Q{}#_zhL5&d~?lg>H>7>4FyyG z{b{b`FKf_jf!cwEoS0M1!|c~6wd$k2gV_T@pOm)o2ztcIZ}~_Y#ZTi;a&w1T$*GG- zY!B(Le%k|Ci}V&$XYWFrqmvwgZsuiq<=nq2kdK+Q zzb$#8`|vGtrt-nTe(W+tFv2qJZ)D7C&X^+wC;=mk`Aq9$dXuR@{tV&9DfrPpR0@a1cUHD{}lN zEav9F%%8)wrntEHACFlrOsAXI*+p4r>M__l)hEQW7S6QeirMYXONA^7s@_OUdoxv} zRHX1>Dg{?Qkwbx4oN_qE;j#{I+FVoM@4V4NL?Fcc&a3{RY^Lp*!?SXf0`lUP<#|lS z+`(wZ&`9J*SZ7==HODN^BzrcQ8FOUJ59rJXpg`LB%e`^T7Y|+)(zpQegDo#&h&vJ53W4B)Xt`ywxvdCDa)!ih8rAb0G3JiDAb_IWE zdh|Yk!6;&MIhyW+z!7PzLSIM%e7CE$agNAcv7R@F@t^4!9(HHiyzbK>@w!pE;R9fa zNlbg-w*s@JVJHE-E2G7kTG6>}d!rKu2pJg}dBj~6)*lfq8iSyqs&IiYH+mAo8G6^i zB0|9kNVOs)pd_3+ekGi744Kw$7r!&xPTS-ip8i25 zHTub*y;^wtjXsHDpwS_bMRoPcVgi0|s5R8y`gea}28DZ97p|M@`!CiJ7~lGG3E+KZ z-dIE!gA9r7K$auS9KFwJ^1l;yxL?~wE6wZl9l z0)}>hGRVDXHat8M2+{iSMe12sR^ zvd4|Dej|*3srb|1m%%Ey{H12gIX)dDpNL0`%La=_f`m8vb_eD7>TN5dLx}4l5D*wE z2@yf%93G7nCOZv7irBT~NO|)!iSAJ~yJ>Ct!3X$D8g#j30Ik&Cp5H`poMk5~+oN{% z@5V|5L;6J?eJe18@vB@?xXBh&tI-0ON~-x}Yo240Ui&~EWc~C0+EqbY?|fA+uB4k; zmu?*QpU&)w8zchT4Ii5=8+=#dB#r}3)Jy$c13VXS=_bkv4qXSIxDkNwTaOMCUBoYF z;Su(PTyj4$fmHNrrDoZ)UvX?*-d=k@ac(mATT^#x0e!9MChmA~OPK4m*|BWgd|7eM z&ZWM|){VDn!yhNzDL^;)oc&g8V&;uTJfjb6heu-g}(aN7-$LE{z_I zmTL#Uw6}7l^M}f3-Uj47N}Tr9;Pt{>x(ds^?v)BH8XElOT1325pLx6Ti-~~R5?6fc z-DSBN)lw;kr#hqaEPRnWT6mV|FCEo&DmT>XwY(N^NTZtawNJe@J;LGp5ob=-dY{Fg zw-&Rr4)wb~C=#-xw-F08W*K`}R;+`{iW+??f`a4I9sPaSTl?$8D5Q zww#mnP$8dhUpp@MIK{F%@of&g$dB+NqrG32lA?WNsBPS(X~H>5W~wCS^_TY>*5iJ; zo*7_VC)O-*@CW*Y74&1eC~Wwh+04C(^D}llUga-c@nvd2#V72qc^3P2c**IgT&dR6 zx+Zs-z6yES2R2)+z%PU2^M0?6(7)eLFMVIvrUo1?EOaeyxdwH&aqzWn<=`6iFB6yc zY!=gbr*(M=dGAqnc=_1WhqpDt!xe!oPT$hDr>8HXPmqk#d?!*EdpK0|rI-4?R(qtJ zWBHAeJw`)stR@6&XyZ0v{DS|t79rabT0Zx@uyPyTs^;(JQQ!Ylh6(hc40;^|{IABs2 z1+MII2oJT|8{bI)kz5DZ{#l>~)7Wg7`ZOA!t%)zLATA5a>^9oT7xB+j%d5?bXj?C{ zxZNr|;NeWMDCyLzIxn0$kb~XTHHE&V@p{!?N}9|u>$-12vRcj41Tmjk4@6@dLBJ1h z8cyLD4cunj$iL_M*jM-YchuI-&bHZY@ag+1xRLAJZnc}cxa82wf` z@OulfoN>!uR%!m`)4GeaU;Z@ihFPM@+iun>p+PT2N9{@~`*NG&AlmYH-@zoY$Z4Iz zFAR_Po+mrgV%L(?QO?%!c4A%4Te_j5^}gfg37yj+#8G{RZhVpd=#Kgjn}XtS(^p~B zY@?YW^-gh#07;zZeX)|txwP<8T1BUyr=U%cRjqDfFd9jFa#}1H^fzh&q!eKWrP6Dp zl-tblal0$dUAC>9P2GnK#ecuy7+FOW4cE?zZRq>(M$cCIZ^hjUTke*vK4%u5x>tGc z0Ge7tKR5ikIH8X+FEED6G_#XB?G~fXVMpwCT8h3H7;LaO8nqkqgPYCzm)#jLZ?J~B zHPgY&%%d#I!pRLOTOOnE3k71Xe-f+ zi;GV`>`7>0G`}^&C*Iwkjs)z!KILcL#Wz29Sq5*ly7Kv07)$x4B$3#s@zf_TK6ERhzEPuv*U=M%Mww#+us}0ZbMjScTyEkXqjL9$V zJWlI8e8%_t-1cWpFMfDmE`P=OvFFjt?CE>wJ=^!#&J0*z&)->Gxut%apCuQxC!@zy z$tm7y(z<=NjYO8#PX6ObUnfe4>HHFm`LNGrf&Icmf(5PJOOxwkEEaQ3`*Y0veCXUZ zJAu=w-S;YQZ2hzL#+LPmkDiinpV}(DyLQKgwDhJ}uj_A1Qm;k^|D5Obeebe+%rB>d z%Y~zE2iDsME}50JDS^>t1@lqK@NkxW6P4Y=mh70)tI&{pzqgbfzE~T~TQY?+DTpU`uSGmN$5<}CKCBUQAM^O7jK sjFzCl!$n#br|*I`q+psFrCJXBXAY>mkm=59-N66^p00i_>zopr0QJE(_5c6? literal 33220 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 From bf9b8d34c813f9401a8708846d7294fa1419a499 Mon Sep 17 00:00:00 2001 From: Gregory Poole Date: Wed, 3 Jul 2024 16:11:17 +1000 Subject: [PATCH 3/6] Ongoing documentation improvements. --- README.md | 9 ++--- docs/content/configuring_services.md | 15 ++++---- docs/content/notes_for_developers.md | 34 ++++++++++++------- .../INSTRUCTIONS.template | 2 +- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index dd181c2..f3921cb 100644 --- a/README.md +++ b/README.md @@ -24,24 +24,21 @@ pipx install poetry ``` ### Render the project +Run cookiecutter on the template's repository: ``` console cookiecutter gh:ADACS-Australia/adacs_template_python_base ``` - -### Answer the questions +and answer the questions: ![ADACS Python Template Questions](https://github.com/ADACS-Australia/adacs_template_python_base/blob/main/docs/assets/adacs_python_template_cookiecutter_questions.png?raw=true) - ### Install the new project -Create a new virtual environment using your favourite method (if you don't know how to do this, go learn about it now) and install -the project by running the following in the new repo directory: +Create and activate a new virtual environment using your favourite method (if you don't know how to use Python environments, we advise you to go learn about them now) and install the project by running the following in the new repo directory: ``` console poetry install --all-extras ``` ### Configure the services you need - Follow [these instructions](https://adacs-template-python-base.readthedocs.io/en/latest/content/configuring_services.html) to configure GitHub, Read the Docs, PyPI, etc. diff --git a/docs/content/configuring_services.md b/docs/content/configuring_services.md index 5a0da20..e8e67ae 100644 --- a/docs/content/configuring_services.md +++ b/docs/content/configuring_services.md @@ -9,11 +9,11 @@ Develpers and project owners/maintainers will require accounts with one or all o Branch permissions for the main project repository should be configured only permit merges from pull requests. To do so, navigate to `Settings->Branches->Add branch ruleset` and: - - give the Ruleset whatever name you'd like (e.g. `Protect Main`) - - set `Enforecement status` to `Active` - - add a `Target Branch` targeting criteria by pattern and type `main` - - select `Require a pull request before merging` - - select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check + - give the Ruleset whatever name you'd like (e.g. `Protect Main`) + - set `Enforecement status` to `Active` + - add a `Target Branch` targeting criteria by pattern and type `main` + - select `Require a pull request before merging` + - select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check This will ensure that all CI/CD tests pass before a merge to the main branch can be made. @@ -51,17 +51,18 @@ Develpers and project owners/maintainers will require accounts with one or all o - To obtain **RTD_WEBHOOK_URL** and **RTD_WEBHOOK_TOKEN**, migrate to the `Admin->Integrations` tab on the *RTD* project page and click on your incomming webhook. - Once properly configured, the documentation for this project should build automatically on *RTD* every time you generate a new release (see below for instructions). + Once properly configured, the documentation for this project should build automatically on *RTD* every time you [generate a new release](#new-release). ::: {note} Make sure **RTD_WEBHOOK_URL** starts with `https://`. Prepend it if not. ::: +(config-pypi)= 3. The [__Python Package Index (*PyPI*)__](https://pypi.org) This service is used to publish project releases. An account is needed if you are the owner of the project, but not generally needed if you are simply a contributing developer. An API token will need to be created and added to your *GitHub* project as **PYPI_TOKEN** (as detailed above). This can be generated from the *PyPI* UI by navigating to `Account Settings->Add API Token`. - To test releases, a parallel account on *test.PyPI* is needed and a similar token to **PYPI_TOKEN** - named **TEST_PYPI_TOKEN** needs to be set, in the same way as above. To create a test release, flag it as a "pre-release" through the *GitHub* interface when you generate a release, and it will be published on *test.PyPI.org* rather than *PyPI.org*. + To test releases, a parallel account on *test.PyPI* is needed and a similar token to **PYPI_TOKEN** - named **TEST_PYPI_TOKEN** needs to be set, in the same way as above. To create a test release, flag it as a "pre-release" through the *GitHub* interface when you generate a release, and it will be published on *test.PyPI.org* rather than *PyPI.org*. If this token is not defined, publication will not happen on either. ::: {note} Although `poetry` can be used to directly publish this project to *PyPI*, users should not do this. The proper way to publish the project is through the *GitHub* interface, which leverages the *GitHub Workflows* of this project to ensure the enforcement of project standards before a new version can be created. diff --git a/docs/content/notes_for_developers.md b/docs/content/notes_for_developers.md index c35da3b..d529f9b 100644 --- a/docs/content/notes_for_developers.md +++ b/docs/content/notes_for_developers.md @@ -1,7 +1,9 @@ -# Development Guidelines -This section provides details on how to develop this codebase. +# Notes for Developers + +This section provides details on how to configure and/or develop this codebase. ## Continuos Integration/Continuous Deployment (CI/CD) Workflow + This project uses *GitHub Workflows* to automate or ease a number of development tasks. These workflows can be found within the `./.github/workflows/` directory and include: 1. **pull_request.yml** @@ -172,9 +174,10 @@ Releases are generated through the *GitHub* UI. A *GitHub Workflow* has been co 4. Publish a new version of the code on [*PyPI*](https://pypi.org/). ::: {note} -If a release is flagged as a "pre-release" through the *GitHub* interface, then documentation will not be built and the project will be published on *test.PyPI.org* instead. +If a release is flagged as a "pre-release" through the *GitHub* interface, then documentation will not be built and the project will be published on *test.PyPI.org* (if configured; see [instructions here](#config-pypi)) instead. ::: +(new-release)= #### Generating a new release To generate a new release, do the following: @@ -195,20 +198,19 @@ Documentation for this project is generated using [Sphinx](https://www.sphinx-do Developers are mostly spared the pain of direcly editing `.rst` files (the usual way of generating content for Sphinx) in the following ways: * default `.rst` files are generated by `sphinx-apidoc` from a [Jinja2](https://jinja.palletsprojects.com/en/latest/) template placed in the `docs/_templates` directory of the project. - * [MyST-Parser](https://myst-parser.readthedocs.io/en/latest/) is used to source all content from Markdown files. MyST-Parser also offers [several optional Markdown extensions](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html) enabling the rendering of richer content (e.g. Latex equations). Several of these extensions have been enabled by default, but not all. These are managed with the `myst_enable_extensions` list in `docs/conf.py`. + * [MyST-Parser](https://myst-parser.readthedocs.io/en/latest/) is used to source all content from Markdown files. MyST-Parser also offers [several optional Markdown extensions](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html) enabling the rendering of richer content (e.g. Latex equations). Several of these extensions have been enabled by default, but not all. This can be managed by editing the `myst_enable_extensions` list in `docs/conf.py`. 2. **A single point of truth for high-level aspects of the documentation** - The project `README.md` is utilised - creating a single point of truth for the main high-level aspects of the documentation - for both this documentation and all the homepages associated with the services used by this project. + The project `README.md` is utilised, creating a single point of truth for the main high-level aspects of the documentation for both this documentation and all the homepages associated with the services used by this project (see above). -3. **As much content as possible is generated from the code itself** - - *sphinx-apidoc* is used to harvest as much content about the project as possible from the codebase's docstrings. This content is placed is the `_apidoc` directory and is used to populate the - following sections of the documentation: + ::: {note} + *MyST-Parser* directives will not render properly on *GitHub*. Similarly: *GitHub* Markdown directives will not work on *Read The Docs*. + ::: - a. _CLI Documentation_, generated automatically from any *Click*-based CLI applications that are part of the project, +3. **As much content as possible is generated from the code itself** - b. _API Documentation_, generated by `spinx-autodoc` from the docstrings of the project's Python code, + `sphinx-autodoc` is used to extract documentation from the docstrings in your codebase. #### Generating the Documentation @@ -239,10 +241,16 @@ The majority of documentation changes can be managed in one of the following 4 w Examine the Markdown files in the `docs/content` directory. Does the content that you want to add fit naturally within one of those files? If so: add it there. -4. **Add a new Markdown file to the `docs` directory**: +4. **Add a new Markdown file**: + + Otherwise, create a new `.md` file in the `docs/content` directory and add it to the list of Markdown files referenced in `docs/index.rst`. Note that these files will be added to the documentation in the order specified, so place it in that list where you want it to appear in the final documentation. This new `.md` file should start with a top-level title (marked-up by starting a line with a single `#`; see the top of this file for an example). - Otherwise, create a new `.md` file in the `docs/content` directory and add it to the list of Markdown files listed in the `docs/index.rst`. Note that files are added to the documentation in the order specified, so place it in that list where you want it to appear. This new `.md` file should start with a top-level title (marked-up by starting a line with a single `#`; see the top of this file for an example). +5. **Extend the MyST-Parser support*** + + New MyST-Parser extensions can be enabled in `docs/conf.py` by extending the `myst_enable_extensions` list. See the + MyST-Parser documentation for a list of available extensions and instructions on how to use them. #### Adding images, etc. While not strictly required, it is best practice to place any images, plots, etc. used in the documentation in the `docs/assets` directory. + diff --git a/{{cookiecutter.repo_name}}/INSTRUCTIONS.template b/{{cookiecutter.repo_name}}/INSTRUCTIONS.template index 293bfbf..3e9006f 100644 --- a/{{cookiecutter.repo_name}}/INSTRUCTIONS.template +++ b/{{cookiecutter.repo_name}}/INSTRUCTIONS.template @@ -10,7 +10,7 @@ Use your favourite method to create and activate a Python environment for your d 2. **Install the project and all dependencies** -With your envirinment activated, run the following from within your new repo: `poetry install --all-extras` +With your environment activated, run the following from within your new repo: `poetry install --all-extras` ***NOTE: This needs to be done before any tests can be run, documentation built, etc.*** From 788c810f84086e7bf7751b99764bd3dd09609599 Mon Sep 17 00:00:00 2001 From: Gregory Poole Date: Wed, 3 Jul 2024 16:13:29 +1000 Subject: [PATCH 4/6] Note that Python needs to be >= 3.11 in the README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3921cb..ba49202 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ and answer the questions: ![ADACS Python Template Questions](https://github.com/ADACS-Australia/adacs_template_python_base/blob/main/docs/assets/adacs_python_template_cookiecutter_questions.png?raw=true) ### Install the new project -Create and activate a new virtual environment using your favourite method (if you don't know how to use Python environments, we advise you to go learn about them now) and install the project by running the following in the new repo directory: +Create and activate a new virtual environment (use Python version >= 3.11) using your favourite method (if you don't know how to use Python environments, we advise you to go learn about them now) and install the project by running the following in the new repo directory: ``` console poetry install --all-extras ``` From 0a265f5f9b804068bd3f47b8b6b50d859b8613d5 Mon Sep 17 00:00:00 2001 From: Gregory Poole Date: Wed, 3 Jul 2024 16:14:14 +1000 Subject: [PATCH 5/6] Make the text from that last commit bold. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ba49202..b3dce0a 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ and answer the questions: ![ADACS Python Template Questions](https://github.com/ADACS-Australia/adacs_template_python_base/blob/main/docs/assets/adacs_python_template_cookiecutter_questions.png?raw=true) ### Install the new project -Create and activate a new virtual environment (use Python version >= 3.11) using your favourite method (if you don't know how to use Python environments, we advise you to go learn about them now) and install the project by running the following in the new repo directory: +Create and activate a new virtual environment (**use Python version >= 3.11**) using your favourite method (if you don't know how to use Python environments, we advise you to go learn about them now) and install the project by running the following in the new repo directory: ``` console poetry install --all-extras ``` From 64c24281b87035053a13e08b8639c6e9b71e5336 Mon Sep 17 00:00:00 2001 From: Gregory Poole Date: Wed, 3 Jul 2024 16:29:15 +1000 Subject: [PATCH 6/6] Update documentation to reflect minor workflow bug fix. --- docs/content/configuring_services.md | 2 +- {{cookiecutter.repo_name}}/INSTRUCTIONS.template | 2 +- {{cookiecutter.repo_name}}/docs/content/notes_for_developers.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/configuring_services.md b/docs/content/configuring_services.md index e8e67ae..fdb7c0a 100644 --- a/docs/content/configuring_services.md +++ b/docs/content/configuring_services.md @@ -13,7 +13,7 @@ Develpers and project owners/maintainers will require accounts with one or all o - set `Enforecement status` to `Active` - add a `Target Branch` targeting criteria by pattern and type `main` - select `Require a pull request before merging` - - select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check + - select `Require status checks to pass` and add `Run all build and unit tests` from GitHub Actions as a required check This will ensure that all CI/CD tests pass before a merge to the main branch can be made. diff --git a/{{cookiecutter.repo_name}}/INSTRUCTIONS.template b/{{cookiecutter.repo_name}}/INSTRUCTIONS.template index 3e9006f..318a974 100644 --- a/{{cookiecutter.repo_name}}/INSTRUCTIONS.template +++ b/{{cookiecutter.repo_name}}/INSTRUCTIONS.template @@ -39,7 +39,7 @@ Navigate to `Settings->Branches->Add branch ruleset` and ... - set `Enforecement status` to `Active` - add a `Target Branch` targeting criteria by pattern and type `main` - select `Require a pull request before merging` -- select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check +- select `Require status checks to pass` and add `Run all build and unit tests` from GitHub Actions as a required check ***From this point on, no development should be performed on the main branch. All updates to the main branch are managed via Pull Requests in the GitHub UI.*** diff --git a/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md b/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md index e1cba17..5caefce 100644 --- a/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md +++ b/{{cookiecutter.repo_name}}/docs/content/notes_for_developers.md @@ -267,7 +267,7 @@ Develpers and project owners/maintainers will require accounts with one or all o - set `Enforecement status` to `Active` - add a `Target Branch` targeting criteria by pattern and type `main` - select `Require a pull request before merging` - - select `Require status checks to pass` and add `Pull Request` from GitHub Actions as a required check + - select `Require status checks to pass` and add `Run all build and unit tests` from GitHub Actions as a required check This will ensure that all CI/CD tests pass before a merge to the main branch can be made.