From adf4e0c2995e7007abf113b6240385a7fdcf80fc Mon Sep 17 00:00:00 2001 From: Pieter Gijsbers Date: Thu, 21 Nov 2024 16:11:51 +0200 Subject: [PATCH] Start consolidation of documentation (#391) * Start making documentation * Use snippets extension to insert readme from other directories * Skip tests when changing only markdown files * Add a "Using the API" documentation page * Add more documentation on hosting * Expand "Hosting" documentation * Import existing resources * Fix some broken links * fix typo in default network name * Finish CURL section * Add alt text and use smaller images --- .pre-commit-config.yaml | 2 +- alembic/README.md | 2 +- docs/Contributing.md | 1 + docs/Hosting.md | 149 ++++++++++++++++++ README.md => docs/README.md | 10 +- docs/Using.md | 112 +++++++++++++ docs/developer/auth.md | 3 + docs/developer/code.md | 3 + docs/developer/migration.md | 3 + docs/developer/scripts.md | 3 + .../media}/AIoD_Metadata_Model.drawio | 0 .../media}/AIoD_Metadata_Model.drawio.png | Bin {media => docs/media}/GetDatasetUML.drawio | 0 {media => docs/media}/GetDatasetUML.png | Bin docs/media/post.webp | Bin 0 -> 14646 bytes docs/media/response.webp | Bin 0 -> 15108 bytes docs/media/swagger.webp | Bin 0 -> 19150 bytes mkdocs.yaml | 25 +++ pyproject.toml | 1 + 19 files changed, 307 insertions(+), 7 deletions(-) create mode 100644 docs/Contributing.md create mode 100644 docs/Hosting.md rename README.md => docs/README.md (97%) create mode 100644 docs/Using.md create mode 100644 docs/developer/auth.md create mode 100644 docs/developer/code.md create mode 100644 docs/developer/migration.md create mode 100644 docs/developer/scripts.md rename {media => docs/media}/AIoD_Metadata_Model.drawio (100%) rename {media => docs/media}/AIoD_Metadata_Model.drawio.png (100%) rename {media => docs/media}/GetDatasetUML.drawio (100%) rename {media => docs/media}/GetDatasetUML.png (100%) create mode 100644 docs/media/post.webp create mode 100644 docs/media/response.webp create mode 100644 docs/media/swagger.webp create mode 100644 mkdocs.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8ecc71c8..dade5a9e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,4 +34,4 @@ repos: entry: pytest src/tests language: system pass_filenames: false - always_run: true + exclude: ".*.md" diff --git a/alembic/README.md b/alembic/README.md index 386d5533..26124e62 100644 --- a/alembic/README.md +++ b/alembic/README.md @@ -15,7 +15,7 @@ docker build -f alembic/Dockerfile . -t aiod-migration With the sqlserver container running, you can migrate to the latest schema with: ```commandline -docker run -v $(pwd)/alembic:/alembic:ro -v $(pwd)/src:/app -it --network aiod_default aiod-migration +docker run -v $(pwd)/alembic:/alembic:ro -v $(pwd)/src:/app -it --network aiod-rest-api_default aiod-migration ``` Make sure that the specified `--network` is the docker network that has the `sqlserver` container. The alembic directory is mounted to ensure the latest migrations are available, diff --git a/docs/Contributing.md b/docs/Contributing.md new file mode 100644 index 00000000..854139a3 --- /dev/null +++ b/docs/Contributing.md @@ -0,0 +1 @@ +# Contributing diff --git a/docs/Hosting.md b/docs/Hosting.md new file mode 100644 index 00000000..3c54a7d0 --- /dev/null +++ b/docs/Hosting.md @@ -0,0 +1,149 @@ +# Hosting the Metadata Catalogue +This page has information on how to host your own metadata catalogue. +If you plan to locally develop the REST API, please follow the installation procedure in ["Contributing"](../contributing) instead. + +## Prerequisites +The platform is tested on Linux, but should also work on Windows and MacOS. +Additionally, it needs [Docker](https://docs.docker.com/get-docker/) and +[Docker Compose](https://docs.docker.com/compose/install/) (version 2.21.0 or higher). + +## Installation +Starting the metadata catalogue is as simple as spinning up the docker containers through docker compose. +This means that other than the prerequisites, no installation steps are necessary. +However, we do need to fetch files the latest release of the repository: + +=== "CLI (git)" + ```commandline + git clone https://github.com/aiondemand/AIOD-rest-api.git + ``` + +=== "UI (browser)" + + * Navigate to the project page [aiondemand/AIOD-rest-api](https://github.com/aiondemand/AIOD-rest-api). + * Click the green `<> Code` button and download the `ZIP` file. + * Find the downloaded file on disk, and extract the content. + +## Starting the Metadata Catalogue +From the root of the project directory (i.e., the directory with the `docker-compose.yaml` file), run: + +=== "Shorthand" + We provide the following script as a convenience. + This is especially useful when running with a non-default or development configuration, + more on that later. + ```commandline + ./scripts/up.sh + ``` +=== "Docker Compose" + ```commandline + docker compose up -d + ``` + +This will start a number of services running within one docker network: + + * Database: a [MySQL](https://dev.mysql.com) database that contains the metadata. + * Keycloak: an authentication service, provides login functionality. + * Metadata Catalogue REST API: + * Elastic Search: indexes metadata catalogue data for faster keyword searches. + * Logstash: Loads data into Elastic Search. + * Deletion: Takes care of cleaning up deleted data. + * nginx: Redirects network traffic within the docker network. + * es_logstash_setup: Generates scripts for Logstash and creates Elastic Search indices. + +[//]: # (TODO: Make list items link to dedicated pages.) +These services are described in more detail in their dedicated pages. +After the previous command was executed successfully, you can navigate to [localhost](http://localhost.com) +and see the REST API documentation. This should look similar to the [api.aiod.eu](https://api.aiod.eu) page, +but is connected to your local database and services. + +### Starting Connector Services +To start connector services that automatically index data from external platforms into the metadata catalogue, +you must specify their docker-compose profiles (as defined in the `docker-compose.yaml` file). +For example, you can use the following commands when starting the connectors for OpenML and Zenodo. + +=== "Shorthand" + ```commandline + ./scripts/up.sh openml zenodo-datasets + ``` +=== "Docker Compose" + ```commandline + docker compose --profile openml --profile zenodo-datasets up -d + ``` + +The full list of connector profiles are: + +- openml: indexes datasets and models from OpenML. +- zenodo-datasets: indexes datasets from Zenodo. +- huggingface-datasets: indexes datasets from Hugging Face. +- examples: fills the database with some example data. Do not use in production. + +[//]: # (TODO: Link to docs or consolidate in dedicated page.) + +## Configuration +There are two main places to configure the metadata catalogue services: +environment variables configured in `.env` files, and REST API configuration in a `.toml` file. +The default files are `./.env` and `./src/config.default.toml` shown below. + +If you want to use non-default values, we strongly encourage you not to overwrite the contents of these files. +Instead, you can create `./override.env` and `./config.override.toml` files to override those files. +When using the `./scripts/up.sh` script to launch your services, these overrides are automatically taken into account. + +=== "`./src/config/default.toml`" + ```toml + --8<-- "./src/config.default.toml" + ``` + +=== "`./.env`" + ```.env + --8<-- ".env" + ``` + +Overwriting these files directly will likely complicate updating to newer releases due to merge conflicts. + +## Updating to New Releases + +[//]: # (TODO: Publish to docker hub and have the default docker-compose.yaml pull from docker hub instead.) + +First, stop running services: +```commandline +./scripts/down.sh +``` +Then get the new release: +```commandline +git fetch origin +git checkout vX.Y.Z +``` +A new release might come with a database migration. +If that is the case, follow the instructions in ["Database Schema Migration"](#database-schema-migration) below. +The database schema migration must be performed before resuming operations. + +Then run the startup commands again (either `up.sh` or `docker compose`). + +### Database Schema Migration + +We use [Alembic](https://alembic.sqlalchemy.org/en/latest/tutorial.html#running-our-first-migration) to automate database schema migrations +(e.g., adding a table, altering a column, and so on). +Please refer to the Alembic documentation for more information. +Commands below assume that the root directory of the project is your current working directory. + +!!! warning + + Database migrations may be irreversible. Always make sure there is a backup of the old database. + +Build the database schema migration docker image with: +```commandline +docker build -f alembic/Dockerfile . -t aiod-migration +``` + +With the sqlserver container running, you can migrate to the latest schema with + +```commandline +docker run -v $(pwd)/alembic:/alembic:ro -v $(pwd)/src:/app -it --network aiod-rest-api_default aiod-migration +``` + +since the default entrypoint of the container specifies to upgrade the database to the latest schema. + +Make sure that the specified `--network` is the docker network that has the `sqlserver` container. +The alembic directory is mounted to ensure the latest migrations are available, +the src directory is mounted so the migration scripts can use defined classes and variable from the project. + +[//]: # (TODO: Write documentation for when some of the migrations are not applicable. E.g., when a database was created in a new release.) diff --git a/README.md b/docs/README.md similarity index 97% rename from README.md rename to docs/README.md index 431ca1ab..098482ba 100644 --- a/README.md +++ b/docs/README.md @@ -209,7 +209,7 @@ Checkin is strict - as it should be. On our development keycloak, any redirectio accepted, so that it works on local host or wherever you deploy. This should never be the case for a production instance. -See [authentication README](authentication/README.md) for more information. +See [authentication README](developer/auth.md) for more information. ### Creating the Database @@ -243,14 +243,14 @@ start-up work (e.g., populating the database). #### Database Structure -The Python classes that define the database tables are found in [src/database/model/](src/database/model/). +The Python classes that define the database tables are found in [src/database/model/](../src/database/model/). The structure is based on the -[metadata schema](https://docs.google.com/spreadsheets/d/1n2DdSmzyljvTFzQzTLMAmuo3IVNx8yposdPLItBta68/edit?usp=sharing). +[metadata schema](https://github.com/aiondemand/metadata-schema). ## Adding resources -See [src/README.md](src/README.md). +See [src/README.md](developer/code.md). ## Backups and Restoration @@ -313,5 +313,5 @@ To create a new release, - Check which services currently work (before the update). It's a sanity check for if a service _doesn't_ work later. - Update the code on the server by checking out the release - Merge configurations as necessary - - Make sure the latest database migrations are applied: see ["Schema Migrations"](alembic/readme.md#update-the-database) + - Make sure the latest database migrations are applied: see ["Schema Migrations"](developer/migration.md#update-the-database) 9. Notify everyone (e.g., in the API channel in Slack). diff --git a/docs/Using.md b/docs/Using.md new file mode 100644 index 00000000..bf9c2d8a --- /dev/null +++ b/docs/Using.md @@ -0,0 +1,112 @@ +# Using the REST API + +The REST API allows you to retrieve, update, or remove asset metadata in the metadata catalogue. +The assets are indexed from many different platforms, such as educational resources from [AIDA](https://www.i-aida.org), +datasets from [HuggingFace](https://huggingface.co), models from [OpenML](https://openml.org), and many more. + +The REST API is available at [`https://api.aiod.eu`](https://api.aiod.eu) and documentation on endpoints +is available on complementary [Swagger](https://api.aiod.eu/docs) and [ReDoc](https://api.aiod.eu/redoc) pages. + +To use the REST API, simply make HTTP requests to the different endpoints. +Generally, these are `GET` requests when retrieving data, `PUT` requests when modifying data, `POST` requests when adding data, and `DEL` requests when deleting data. +Here are some examples on how to list datasets in different environments: + +=== "Python (requests)" + + This example uses the [`requests`](https://requests.readthedocs.io/en/latest/) library to list datasets. + + ``` python + import requests + response = requests.get("https://api.aiod.eu/datasets/v1?schema=aiod&offset=0&limit=10") + print(response.json()) + ``` + +=== "CLI (curl)" + + This example uses [curl](https://curl.se/) to retrieve data from the command line. + + ``` commandline + curl -X 'GET' \ + 'https://api.aiod.eu/datasets/v1?schema=aiod&offset=0&limit=10' \ + -H 'accept: application/json' + ``` + +Additionally, we also provide an [`aiondemand` package](https://aiondemand.github.io/aiondemand/) for Python +to simplify access to the REST API. You can see an example of that below, and we refer to their dedicated +documentation pages for full installation and usage instructions. + +```python +import aiod +aiod.datasets.get_list() +``` + + +## Exploring REST API Endpoints +By navigating to the [Swagger documentation](https://api.aiod.eu/docs), you can find information and examples on how to access the different endpoints. + +### Retrieving Information +For example, if we navigate to the [`GET /datasets/v1`](https://api.aiod.eu/docs#/datasets/List_datasets_datasets_v1_get) +endpoint and expand the documentation by clicking on the down chevron (`v`), we can see the different query parameters +and can execute a call directly on the API: + +![The Swagger documentation allows you to directly query the REST API from your browser.](media/swagger.webp) + +Click the `Try it out` button to be able to modify the parameter values and then click the `execute` button to make the request directly from the documentation page. +Under `response` you will also see an example on how to make the request through the command line using `curl`, e.g.: + +```bash +curl -X 'GET' \ + 'https://api.aiod.eu/datasets/v1?schema=aiod&offset=0&limit=10' \ + -H 'accept: application/json' +``` + +Below the example, you will find a section `Server Response` which displays the actual response from the service (if you clicked `execute`). +Normally, this should look similar to the image below; a [HTTP Status Code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status), +and data (in JSON). + +![After executing a query, Swagger shows the JSON response.](media/response.webp) + +Below the actual server response is a `response` section which lists information about the possible responses, including +for example different error codes. + +### Modifying Information + +!!! tip + + When exploring these endpoints, prefer to connect to the test server instead to avoid editing production data. + You can find the test API at [https://aiod-dev.i3a.es](https://aiod-dev.i3a.es). + +The `POST` and `PUT` endpoints allow the addition or modification of assets on the platform. +You can explore them in a similar way as with the `GET` endpoints, with two important differences. + +The first is that they require authentication. +To authenticate within the Swagger pages, navigate to the top and click `Authorize` and log in. +Scroll up to `OpenIdConnect (OAuth2, authorization_code with PKCE)` and click `Authorize` to be taken to +the keycloak login page. Log in with your preferred identity provider through `EGI Check-in`. + +The second important distinction as that you will provide data through a JSON body instead of individual parameters. +The documentation page will prepopulate example data to help you know what information to provide under +the `Example Value` tab of the `Request Body` section. To know what values are accepted, you can click the +`Schema` tab instead. + +![The "schema" tab in Swagger shows allowed types](media/post.webp) + + +### Alternative Documentation (ReDoc) +The [ReDoc documentation](https://api.aiod.eu/redoc) provides pretty similar functionality to the Swagger documentation. +The main difference is that the Swagger page allows you to run queries against the REST API, whereas the ReDoc documentation does not. +However, some people prefer the organisation of ReDoc, +especially with respect to documentation of the expected responses and the schema documentation. + +## REST API using CURL +The Swagger documentation gives examples on how to use CURL for the various endpoints. +To see examples, simply expand the endpoint's documentation and click `Try it out`, fill in any parameters, and click `Execute`. +The query will be executed, but it will also generate a `curl` command which matches the query. + +For example, listing the first 10 datasets: + +```bash +curl -X 'GET' \ + 'http://api.aiod.eu/datasets/v1?schema=aiod&offset=0&limit=10' \ + -H 'accept: application/json' +``` \ No newline at end of file diff --git a/docs/developer/auth.md b/docs/developer/auth.md new file mode 100644 index 00000000..094860d6 --- /dev/null +++ b/docs/developer/auth.md @@ -0,0 +1,3 @@ +# Authentication + +--8<-- "./authentication/README.md" \ No newline at end of file diff --git a/docs/developer/code.md b/docs/developer/code.md new file mode 100644 index 00000000..e33c82c6 --- /dev/null +++ b/docs/developer/code.md @@ -0,0 +1,3 @@ +# Code/Architecture + +--8<-- "./src/README.md" diff --git a/docs/developer/migration.md b/docs/developer/migration.md new file mode 100644 index 00000000..f40ce0a5 --- /dev/null +++ b/docs/developer/migration.md @@ -0,0 +1,3 @@ +# Database Schema Migrations + +--8<-- "./alembic/README.md" \ No newline at end of file diff --git a/docs/developer/scripts.md b/docs/developer/scripts.md new file mode 100644 index 00000000..8648b070 --- /dev/null +++ b/docs/developer/scripts.md @@ -0,0 +1,3 @@ +# Scripts + +--8<-- "scripts/README.md" \ No newline at end of file diff --git a/media/AIoD_Metadata_Model.drawio b/docs/media/AIoD_Metadata_Model.drawio similarity index 100% rename from media/AIoD_Metadata_Model.drawio rename to docs/media/AIoD_Metadata_Model.drawio diff --git a/media/AIoD_Metadata_Model.drawio.png b/docs/media/AIoD_Metadata_Model.drawio.png similarity index 100% rename from media/AIoD_Metadata_Model.drawio.png rename to docs/media/AIoD_Metadata_Model.drawio.png diff --git a/media/GetDatasetUML.drawio b/docs/media/GetDatasetUML.drawio similarity index 100% rename from media/GetDatasetUML.drawio rename to docs/media/GetDatasetUML.drawio diff --git a/media/GetDatasetUML.png b/docs/media/GetDatasetUML.png similarity index 100% rename from media/GetDatasetUML.png rename to docs/media/GetDatasetUML.png diff --git a/docs/media/post.webp b/docs/media/post.webp new file mode 100644 index 0000000000000000000000000000000000000000..fdc373e5a104f641cb4b93817475ab5e339987fd GIT binary patch literal 14646 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 L08{qwPt*SbxgnyB literal 0 HcmV?d00001 diff --git a/docs/media/response.webp b/docs/media/response.webp new file mode 100644 index 0000000000000000000000000000000000000000..f0a6fdff70513b6e92ef4835c3a3d782d3f2fd74 GIT binary patch literal 15108 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

hc$a*b1}#<`)qWIl>2m9L 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 literal 0 HcmV?d00001 diff --git a/docs/media/swagger.webp b/docs/media/swagger.webp new file mode 100644 index 0000000000000000000000000000000000000000..9c1a871501702aa26f741bbb4f29ecc171c49ea1 GIT binary patch literal 19150 zcmaI5V~}Re)-C#!jV^TAwr$(CZQFL2ZFkwWZQHhe-@U(m&e``w+`E3Pm^s&qjGP){ zW~QQqsOYdH0H7u!D6cBdj^F-|jOYlI4Ma%*;swkbFPbe?Tv$R_uwYT!iv(q1`$>(> z-cOIqZya*4^LkR(>SAy;`Q%yrJIdF|`cdbb<1q7l>a^6uXf|*hVia$q6V5mFEAxKf zS+v_R;KtZnI~} zFW?#MGxJUFP49XqQ4d28`P=A|&k;WUJMo+E^+sP$nK$4E`BUzlZe7l5NAm~n8*Q;> z`lrq>@B8dc>lx@X>^=3p=5i-?htV(NR{B%!ZDu{!pYHf)qvygeZ+v8{5Cr8SE|dkqTyRv1B*Q-YG-+_n*a%tsUEaqzJa1vLb-8#FlU;b^~t2bVGLOL1sV)mtgvks3N% z{BVbI@7RE%}QAyk$B+h<`mw30p>#uC)u zMp#F6!B5(Uxf5kbq;JmHU1YI1@Z%Ak4nKs?D>uPv>vKj2>z(y5M*X8lg{pGxsx4RN z1gklUNSnP(oQwK`*UO07>_9qj$lnl;%jQQsaF5^29Rt zryQRD`Jt(W0{@5W|4I$Yf33IEFmS-NusR67B=_=5hObj9!_PI^=-cv%|59cIxixG} zC$7}5K$(jmi(ZfQT~q&zp(e23TH@3jxHnNUe(69a{-xFhNG_(-YGo|kaW6? z;6);b4K#f-3cgwYEf55$Qr>Iy!ERg~<`vOg8NsY)$zse z&=bs8ppt1^asUjz!&KV5K#pT*B1$S5-=b5&z2LJJBg^rj@wtSi@!IE)RqE4OHt6Rm zNgu}5IUCf~(}KNnqG8$OXzc$+guaL)V&92Bz1u2ZacoUh#bPb`S&riQYG14qg$U(m z?kYL8O*%CwD(e!8G=YftDZdOtmkYbAGG#wvL8>ljLtW7^SSX$jRU|xKom{j$IW3mW zh3kzy&yiw#pi>0)@@;Ub0rkLMQ+J-tiWEu5&p-MwjMULBeEk@3<6@Q2|Df8xV#Q8! zN7^xHROzlYYhR z8mkMQgsFFmkFM=zB<$ui@moF3x7$ z87NZXn+x#2@vu-%N%u8-w=QV#_cffYbaM6g*UdsM1K;Ly^;^i{tpj8V-r7g%WOkAJF+WAf`uzW? zAz`TG4rlwD^}8u8K^^GZX>f={%|;E?8w~vj7XxD>7V(4s!ujZd&fjbxTd7deCd(LS zjIzB*^)sqxly=B&1%QI8|3c}iHu0ld(y8b4@N&+rfVlp7z31T~&ZkLiZCJ>B_TUgY zmgw48(AcC1D$Q`MHI%WL&LH!N@uuu*iCaFWHTBI757_8T{fv@$?b=Jggga z1uShoPWTcy=z|ePhFjVfkgABcR+3lmZEPewJB5pu+4sFp90V7TB&!lrWT*QB$aGT8T<-5=jMiZPAKujH8Oh z5s*%qOfP zrbYJwbiRALU>ExTxZ%Ws1pX^AT1XY2dTL*$p;vn?HG2vHh z|5(mi;A9H~kI1_NTEf4D^8ZB%V`%UfJQWiqaa4p87J@dC6KLPmq=RB9p~+@ zL~*!koqbf!sr&PCsd)h%WEdS%w=+6YOfZ4T2-_P9nz(LaOTP5PgTU(d#1j#N#|78H z@Sd{-OY&h`xIMU#O`6Ycj9Jk@SKSQ@tQ5h;yOQGRj|XMzI%-p8Gnv(VjBJBR0#kpG zul{R`lfEfVe*=^mqo(9<&UGY@B}-3;qcawle1|Q9`5Ug?y&E(0#{x<9cwvGi4JFq; zlA?4@w=mn>A|@C0yyXL?@>6y&Hn|#var6Z^Y!nz6d|!6R=J{7nbbro&IEvDt`rn<+ z(sIZc(|A}l9*b8-t$n+ZD%}@4e8QQnM6Q{9JQv}Ru9T8?&Ko%m2jgZ&!~dZ@BUoLp z3lFLQa5aX+8i~C&L>5fU_sH`A(e-H05Xv8q+_4NkIFf1$f2q_rndn-LXny~)%HKwa z1Y=zPDOzU!bPb#eoZ`zkG5X^O!!ZXQK{z>dk=O@*G(juv|0Wg6*TV<@3b21#tAF^@ zDcnhZD2j}94t#PLpI=!Oh9Mjg6*aK?ztWIP^?$M0e^GUq3A<3dih9=nOZA`Tt}o(n z4gym(v{L1;iDm32A^87CDDr}b-cuRaZ9oqIQc$PO)w~;DYx}QD>Zi) zTvr4GjAR*IL3&ZZk;s-oCqPK`v&ze+7)We=!h3ak9Bb5P0qLRU zy z%DBbSugyZjelvS2emD{a${NkY;5egkrgd)vA)%GaWq9rC`iB8RDK5Y$FrZ(2G#8T~ zBIF6#4?Kl@6NE?Mb@C-8y#t~VO)yuMntk{>L4hjA^GA)v^==I4uJPIKZ8C5htGE5~o zTsDW5^DvTbDG@t-o#IN$E}up^gB3IVd`utC*wU{L-Jw1T&fK5$Riu$KO(Xh^=fuli zBx*^5l|v1CPsm=D6JJDMBNiicaD`wZB=X?!%U*Tg>4&FS_y_CZNXSYLeY~4srkg&k zq`+a#qy{ktYM+ecl`{?dm?7EZWR&aBI_WstRXH@l9dz^T;kzZ8Hc{JGOY}E;eeVhP zm=H&lQx~k@gyaA3De|=ob{B(qCKzCwCO$4BF{Ou`MBl z;})PK48Pc3jeH0ycY*0??0j{q9+J( z^%O(Xkw8E82n%_(`-EpO7)dH?9Dw1O%C%MBp)i!3bbJf}^^AYYqX%X^Tx6%;@gCB_ zA7n3UVE%L@ZM&N3hN43nI$fTlA|dz@{d$ZV7y5ne0MbhV8pBri78o*_&<)!dq~T>7 zIw|QfO=XlevuvVR$M?r+n(OL(NvXHs^-{SjZ%%TdRY-}-69!J70V65VG>!Ty0v{Kq{&FSYurT@%?M5Jo+G3mBV9b3r+&s68O#UiJ!@#1#ZwWILm#U;WILkui@B|~34dx|j- z2(^3VREHG2ArE-!XH6RRE#opZT*>gF$9V8TPV;#F-W+3dEpl}CdGl&)#o0B?ZzAB^ z|2w~mCpF!2U;PaA{QT_D?4A^P1(GKYv`I1x@$n{>Ge_?BC|4RvEE>#`mSAWad z3+nNZxU6u4;Bd;a|8m(VKa4!gXvoW;+hHNbasZW1zDaN4kXQ@O!j}Th?41U-hG_J1 zbENcCQYGJGcXb}Lay`G}MTA>8)rIWbK915#DE zm^$XS^A}>FshZr(?Q=WZfvk;gtp%oy432sc!7FNUr+LAYk*atr)=HNx~7j?T+G%xF_$=J>S>Wosm5$ZN^++zwgqbb15lvZwFr_s$t z_!vZJy)$zBp5?p4yFx4HROHb_y+F{dq?H}G8!aLz3Pl!zWD1&k?EVEaM&Zyu-GXn;$~C;>fstuz!dsrIH;8o5SWKRp0x(gx~=u8(US7>+vZ;i_r7DH2ucjaJr{y%Djf!g0=Q7NWvDR` z+$p$7D>j=HA-#iO2`gE&krUL)vzRB}e{+h;C{`RypWC}Il_+7@HhN_{D*b!3kY#i~Ce`ckFDQdvz+we*Qaq{-jr*n8;N+aL^ z+^rOAib)hHi>A60apfN~1Yvuuc=w{zdh!gc7#Kn7S5fkkzd1YFx$SK~l}#`Xm<6KC zI-=AxJRN-FvjA zl6V0xUQBh(B`-dSFK`dW5g@FjpLlS^%p}w*2^dzp_I~apEBKz&E(i*vcDBcpD&RvR z3HcaBd8Gl;M&YwtWcy9j{v<#cfCLfL$qZP8U3;M+(XizYSw8qlYNUZVj!2^>;@clu zS(w;?rcSCoU*7h~{pG-^>5;621?FNWt~a$TgQL`a2{%Yuzz&wjOT)$ATO&ZnXgGNntIQJXAWgh`^M0x9}nZo+4EsyZRY z!+j};SG1k{HIjQm)K*lxF^qhD&GxsNGr_yf`AM*MpK&Gwl@cdOSlSW>y2Exes{HFH z0pl@19(w8 zaKAMnqdijdBc`5$Jx8M|U_YMh53HW4ao3H*DO$asXZa5XF}D;{_3KH(O0i-EhR8ic zABJ%60orhJ{w-j^Xhh{@8>%7Rr46=u7NHLK^3E@TIR11R@P&6XhL+nT;q7F}CG<_* zh-`+%9T3p>vH4qU=}Eqo@BW>Fh3~kYO|-nJYqAZ{K7Q=4zYrA;If(RdTX`8A(o#m%Z!(dUzfmZ@@K~-ZwnaFkAy|BxC zb{2OtK_c03`qmGs6mW;qwb=3IAbfeJey{{4gZRspL|eUuEcBSPHPC7G>I?BC$%ono z0h58jYK5f|Z)X>IQf|eu`8xrNVu(!zu?Ct<@vcO&=5yiv000~*v!o@YKLCJ*J59(D z4gf&+E}V)%|B{fnRN!G)=9=0p$2ne*HiT`*g9Y@aUEmyFE5|-qlrVtnAcO++rCnkl z+$hC78W+%mXu}2o^rW049v#U)HFzf7J`G35)!$_y7Hwxu+Fr6!^vP1rc08$ zM)wCRVkSr<=F~S`CZsR&>j{CY%4Pu|52sw?YcyKO!c(QN+H5T#>~B&psRT_@wS_ z?Y0h{8ZjD${Lr*sh-_CIX7c;&EBaxhcT|{&qNxo~K4m79zE>U$t`koUnGjXoa-s&H z@cxk_GfQ8ULstw&jVoWJY^}`<(&erJBEXj$&V(#xP%g4UPmn#kmv)9(R`@GOEs*mT zKg|SUc-o$rJ1Rr&jsI?=$$+OSuij9{anX%Azz=bZM74G#Ne7;-+m(cv*frJRWp&PV zs3Y&+%mI{ArA1T?eIX31Sy9yG=PDt#Y8~((B{yIYsR?|#PoNT)gKM4{xkF9IN=>Fj z2P^cUrkP4n)3dgurl^sHm9&ZwXT22FR+BP>{}w5Y-CnupH$D9wulwyzs#CEoVowx~i|O0WdYG^ark6rq=)EoBW&AST=;@5O z;*sdv2S{4As>)g@yP4!1%D!~MSXk9hB}Bm8FbnsB_ewR5n@G7?g^w5h0h>ej@5TDA*_>E`pxU)f5J z9j^Y~!5$qPjI=M3UXGGd1$@N8tzr1sIS%FkJA(oG;?1Ijkbd<@nDOww2D2a*u*;;_ zXAZ{0=D=rWd2N+zEh5(ee2o^h_+U0UCaVpxHUR)*-2*q6sjjs`0D?f$nRiT=Ag_mU zmxoJB18#%vj1d_%Atl7q`D71U2f&aZ!Yk0OW*TXdE(J$gy$EnyE8f1ONGA%gRB+C zKc9hq)&&XPd7)ZEl=KdnoMtMu9yhKBWrhwLUYdYP+?W)JN#0^S5!gltBo|-*g39-= zP`(C;c2cV@|l55vO-dxw+=~jW1&3GIk57( z5d7q>jSy(`2!agsLMLsKZ4XBy_fdI81BcxpbHKbVT1UyhjB|Xn zc*)b79B`qUwp7Ki`Pwsh=p3d`8|Qz~w8@{x*wg>i&#xVP?fWu$3Smu7(LohmXh4a~ z?Jr+Wx8&yk?vdJI-K|(O(@m(R9Yjl$!dn6UK0C~H%BF}E*^-pz>eaTtnsANQQ1X46 zbUPRf01geiQ9XJnY~Bg*3O9%%qY7~|O3C#nji%USQe5}XJ-tnUn3JoT_NnHJYs5mH zmR+;#f?S$NFXP{!NXC9aX`B5k-t;bCbL8s}E21Cw4xLqv`rhy+IyQnGHv^G3QCvOI zNI$7j_LG9Rd7Wf5hzHc@g z5}f*2S7p6goH1OIQ!QVQ7RPH9c}eC>vk+zbuZV8b#dSQyxa+pbAk^fexc7nvm?B+z z!3q!KraYp{SyYYC9N}FKkZ~;z)v9WdApk`OQYg(;J==m+aKu434uSU-0*8dmcb}xO z)vKo+;&iO7T3beX+}}naFj};jZuN+CW8qR!y6m)ST1yL7 z6WE@Uho&n)Q<}WMd=g|c5n^cR^t2?$;t@gB{8412q&taCe%zwii?-{sF3;z11P0Sw zNKMD>W^!>jhjAlbVi6puQUK-qj}p=1ep6( zqu4aya@h#rQ8r`aQ$D@=7@Vej*lHhw1;p^_?u(h?^qJrn>%S?8_eBo3b?tcd`l>O=^vjCGCdqUW zO&L+*QE2U()(sPGvn85JJILZmw1gJH(C3r1+Y2mnN_Xc4O8SXqa+L9l6?Xr7RT{69 z5p73XoFcbQTYkABT`Ud$fjUlGfd2>SRauWDyq=JuI%VchA|6MQKdzo=OboTVc1txh z8^*jIB|Hw6!r;Pt+hLr7>q7=nhf|n+WFzlB_0Y&G-ajq!(;Qq=<<2Y6$-QdRx~?(M z=*!cxg)DVn)!1KHTOF)(CGb7?*brj5dJioTaYGTM>}RQ~elB(sq^i4?u!1X5Nad$1 zZoZ_0HW1*5F^Z-=?*(ea;#HF0Y?BA<1F8x{c7-)gn&Z;L_kw!~Sw;FcFhDr6?#SFM z;!Gy*pepW*M3tBz@NrGj3Ip7q)R%KZ?F-T?)#12K3Mr0hK|g}jQnnb+tG`^`R}`Ou zB1|u=89)$PXqq<-UDkADro?r;9vVd#$Z?ov6XF=t>@>^pX##v=wP=$9;*UVNbgz!4 ztlhe^vy#aQ*cp^x$bF5Bt&+gT6mNF;&Ou_rvY<<}$BJwfSWVETp2b~fYX z_27G<{F1rskQ`*G%gIsBi~F^nUHya4f?dwJyt!BqV#6bo+Tn@Y$7Oi7I1Pg`&gK=t zx^C)pG;UJT5kULWv|tR{DX>A3sJ@$sIk)JrM&xd6`Qjh@q$+>!lCs$BcQ7kNr(q8s zP(sy{Sag$^!kW-B%seZNXH-2Q}h zMYs<72{WtSn-O+s5B8w=lYRsUeS4fDrfUI81MzO=WDI^U9zpH;!4vW;m)*7yVBG$_ zG8@q+Lhjw1BiBI4twPJ!noD?}q8iA$Jb085f4OeMx(c4LDaC~$^|kk;ruw=edTJ7h zb62~^>TBh#O5-cl13rGTG6PDm*#&s*7r8TmDTpt_eU^q>iD0~@ID6Uh2j#9eD(^mY zs;iyXA={u4rsHleulwmgOUa}8hwZ|? zRq3VOnoLfEl$=5qe!~b;Yx;v+|Ge1e&sSLbM%p0APwx)ajz*VV3^e*b6A^&mIJO{2H38YjhapevgO`rENZs129?{g_PDn|| z1Ba7zSp^Nb8`J*0a(T+1kq})LNb~|Z?XynaWY{4X1fyV5;7-eIebA&6MBd^hM z5-wz=fo=LV6^Zg%TbDf!Ptf3;mnH7Rm3QBzX0B~ZiGbBh0TRk#k4!zEp^2tN|6`)g z5K=F5TMW%99sDMKXdO;bkM9rdmh~Q=L_k9N9J6MwZ&noInbrbarueHY(B%RprS#BD z&{f18eGnFm%H9h!ge;k2D$@cO#0mWzg~IBkG1g}%y^m;zrvnM!y`>7`7Qqs163b3W z*PxUzO~)PvmRPu~{@C#kez(s4E9!j*-}S?3HM->IzzC#5QA-|c@*uBzFwt(bKpS@c zqbh{NvL>U~oB|!4E|-z-7S>8hJYxaHdos>?qJ>ja>< ztqw*k_kSTqek-^{U$n3}yFF17K=RL}6ls>S!umo^&+uQQ2*&A7ke5;EI`5fF4VyQ? zCNh6!3I{}HX;lnvNJ!f5cK-Ges*~OV_w99zFq<7JIhbk%F~80na6BGULJviS$+B4i z%}ggCNcTopgaO4T-9RSWHw!wJm`V~&KP(sL#|nbfO!eH+L~4U}o+ zn);E;ZE!QT+sRp^9jaI`#FAJe7p5CzCKFAUpY(Aise(-)Ka6nU|42?!)u-3~ z$f|}U*!0hdg_%L`qFIZD$o_#_*d|k&8r-hZdRo5$C@M)T!-7Dy!fM^(j*NPz8o=Ee z{2;1Al$Zmy{{Pn zjCLb>px$ec!|fIC*-P5H%<3tZ==h9W4@ViHhS?&Tui|5>)TojNrBS$O)c6wnOP{oC z+t_xFG0ObU=|Ty8+Yif(;xfX{9L)8*RhWsG*To@(rHj}?E1d6^roo9vUD@}`gX6q$ z|7x_Y(J!*|O5 z!ee*4g}7tYTf*24w$uYjpBn$kwG}q1OUJ2ajH4kdCfk=7^-m=-g1`N1w-x*Z(C-V+ zGo$RPMlA2LtsDm7K_69CTi}y2&hO++&vEjOf8iN63<1M+yV~V%@^*b_xmVEd@o+!NM-_9TRT_H zUK?Q)P}5(_B`U-&NyX6&5O`Sghy@05pzQd5ua1eX<)doqqK_?r*gLw6(3tXhtBfL$-uyLV_D7I_m&h#it?n*&=Q!-G#8fSsKC&B(={$HaOvke2=g)q3 zJuI-#C0O>gzeA8H07X1v`kdj2cixCwhWKo-pS%sdUwq3ZwG73QY{rNnlvICoe@6`q zA1K70cSrasU`~1(1mErPG;>A@PH~7_n0MGqLpp?{d$z|o7t?>V8KkJFNW zyQi-pe^GObw>f`ZeCLTK-7p|jH73flfVx|Va2^rU=L(~KAWm2OxXOkbDcDqrN637^>7EtvyUR_G+T za5xQkln$Ytwm}pL%vSuN>M8g+UY3=-!9%0K&&g+_D95C0pup2Z_{Ux&5gzBxfVB3q zvE#4hDYrSRn2*#uP6I67`(TlQOw>F?Q*i%#6$l$K<9s>m z!ifhS^#=zS1Bi+Tn9eLEe#^ifwT;oSW|?ISMs!YIz+DWqPADTCg3kH7MA!EdkU;Zi z2Ecfm^5CD%h}Nh~exjGnM@aiQJ50V%rA?H8&nC3CBGmzFArS_IrsbD|Mc~LjpL_vv zx4ZKJCF2&Qzw^!yLkkT?U~8HV(1X!hslVe!$x1ouJKPyIE0k8#<+Yl?AL26{)!lE5 zU$^Pu(5e&O2aF2slY!F}{-(8^Mw@+)AQWh8u=%1J*xAv{pl2k&+l^6=$FK1R^US2vw8QxAAy76=;NoP3d_Q@D+mp!i;Q>U)H;GU*mvsUF2CX9neY1i?DS%;JN6J!H;%_e^R5uXOV_5nl~$Qh#a9(#II+8qe#;T1G7 z0p7X{Ge%sr{~&>AVQ#X;ljW!gR%NLm{Dn+YM+au4fc>F+<2Y9+RG zaSHN5n0=)MKAV~R}^ejO$R+qIX|`p|a6A~?pwm|Ih%Wm4rg?U;$p60s+V8k}qbL$5W4kA2lQv*G-myBtK7iSeN{oW-ccIN;a2zAd~$iMVa`e zN)9OK=KUd2!9Qo936i9Js;F)o>J=tGm@C}VTg5exi_y`;Y zGJ}T;u3({J*0s^NS5|P$LBQgcF|`TECjd9=r360*tS=w5bwhp_z0yVu)OR6UKW807tZ(9;WK^X=_9U!1R&8l|+k#e#A1(TOM= zA1Qxb5-L)YKHd=ZXe2~C{O~A$EOUe6ER{cqTzN`rir}YGogRORSz+zuI@u#A!1)xlw>~9BB`O3R?9AF;P|n!gAvLf)(?S4;dQZly?MR#nqfQpb zf|Lwmcu8v2?g>Lg*wDqa`tg*HfZ9D04poRFg98g0X2x zmlFJ+TCyh36coMu1mxaix*BP=qeX~Jc%yb<$(qnS$%f7oo5F(xqMS&7#m^9j5a4ZyRV)(=;Ve>czjuj(Z#~{N+I1n`96X`y)3EYx-p%(PH@hU)@AQU z-^?2UqbnL4f9cQ6ij9S7lJ};w>+2o4Q4akkgLDQ3?gZ|_j&lA2?sQcm1}k^s8>C?xFo#85C|kGA*LX&ZBA$GZz(vbE-j_*!5}{z%#xsfw2D{Dpuj ztds>g_WdmH$`K+HzUB73Y}Qq()IVF(k6kf}(rCWPziu zawvHy7M@4aFDse^LQ9jEKk z&czxPWT4@k(x3;8#9{Xf;^i@5pF%=tB>O;B29^uP_aVwE8)v$XS6M4#>f3<)T-TAo z=|J+4cxxoirO&CewL0WaZAJcOcnKbr2kq@ya*H?$g&oNm$5mR97A5|{_NB>YbUGOe+>gpE?q^wf-P2>HtRvp8 z&O6HoGy&cb9x6@*U_&iWyLZks>bewh$t;XVHCP6^U^vbL1)X?UD=K+aX5KqB@nRm` z`R;t*Yinb=jB>CRiG*FCv_8Z%sk^HEd4|w$nbuft`_LlZIOmhpat49%T-0{CgR_>< z$m8-gkd~~wFrEA%kfepvX}jD^1rU5&{;0uq>SgKLfuGOI0nY&DtHKUvP2R-`;kjwo zp*FkO^}{Oh1J0YC9;KUZ$Mx8<(t!7YiM}mowu*ZEjinolBe6dCpe&zTUx|QJE7Vw) zf-DeAqRG`eSU)S*T>I<^vk*4>9byQ^IF*H{K-nIc*#1O)7$LW+MgVb2A@^l@I;Xl1-TG|O!=ba_5vhf4l zk#W1=SfzZSq}7C9!76VdZt2whVi{6w3&KBxh^f+QiYKWgBX+M9Tdul!zcQN~&)Ua2 z4&g9V{Iz8JX(S}BSQc`*W2g!=Uob4C(>XiLsPi+04CihJnhQGnBPIw)G(o+Ka5aI2 z<}T`4%T9WICxw+e8&WDLw8(RHueTZlFa>fj>6N#F^KU zoD-?j|F#mzY+5^c*LDZ&Uuy>X$TK&OyLI?+M^<9Q;AO#9K0~UP6Q-A3rfu8vHYFM3 z!bJ*1R!#`0^{lBonT5dK1L|K^gM%mtrwvMp4iYjJTH;U-YGeAz>0k@eKgH8apnf~e z0HM|?D|;bgq`Kf3#P=>3-V44=$^6FoIw?}qBr8>I=c?ka+rpnNQQ_Vx7?CCe$`puZ z^)$AM&xJ?b!zG%fUHDz18L{;DFaE~dJHtG#-a_5hE`o|#jkuN5WJch~-;hFKFi+Ak zkceiK=jt>vq{oFuE-us~pusis#r*jIy+meFsZAl1ZJxrTb6#iVt`$Q_EKQ?iv1z@r z0?~~Q2A5|TR01&2@{EcHHVb^DgIQEBPRK!Ia$?|Kow{5vOk6uS$D|i;_h~4Ol@!Wh zt47j%rnEoSD)h{@k($N9F1qoJneHx3K?UZ2O;slsqsCOF93ep@-?j2vBiaq^ReFl~ z@sK_ayP05Tqnz`=-$Q5~Eh4P5ht|=lax9CKuAu3AgvO7}GujDe$Ps~_5FwK>5T5vpa zeJr@$WUb;FIr_Ju8Rhhb((GJAXn!W3_O-!Q5iSui{l?GdKAqc5VaVv7nn_I!dqyn! zVjwj}c1)lEMHVjIIX8lXCVdcHFHtFWcG+<2Y3eUJj$o0S?3~85MxqtF*&@%SE77`5 z+xr0g_6|XAi(1HfF3Gz{Z!y1>6@d+3Nj~QG!kg}=Q z=>l^p;X8=(6;5dr(v`K}9%w$QiYs$t;d_4K#hpi%QIU}eAbhqFhvMqKx4`Lb$ zq<%tp#2T~!QhnqTiLUjZ;!TE2nI+DN_g3lR1KKx5oKbbI^qIsEFGT*iWttRoATiwj zRor&Po7s|Ht;tuwxy5pte)rzw_FydebjWyx3yG4fC<46ereIrwM%QZ617da>7lJyy z$6`fQud_^^vuX=}BN5hYv=9IuFn=Y1hc(Ertsl~cS`F&FK=$r4Z@_)Bc@l-BX~hYx z^?F{{=E6zw^J^}^U`(pz`RV4enh0AP`!sir)WcvP=TbPHjzZ#a^>hvLGKxPDttZ(b zx4FyP*>vCdx0;OD+--6lNFEfHmKGhdw*Z?+_=r5CgNPy6hiPm1QTJ4G24k`2t2nSQ zlq{<}V>7D94{UGx5UWp$Cahv`QwX&xfpNL@SZ}On-t_?H=qhO{db=n}hjj4%(+lKT z|DUiz5%6Z>X2n}7cnBp{kLp_)07&0@U0TvUeFheT`hGBG09Z;JyAy3DtB4yubOOeV zMnb)b7`YmwqDNz5hf~gK2E4N@^!7oWBJB>El3}lq5_t0$=7T< zzFZ35Elbh#^Xw|^?`mTLEgYhXh7z*OC+EV&^uUJ_f6Bu+878bm+37_Wwrie?i z^NO8ntS5JH3fGEjb`!WZs(7B##fu@0k-NDr&-fvvXmeGwF1bljcP(2k>SZ6;Z$)mx z1jAV60KcSP*-#kwvsLAOF>QjkKY2}6X@L-XtSCWu*@X`tN zm7s{+3D>P-CYeLEF}=EQwO%DAZfFl1L(S!NkCr@j5PRmuOLsDcLncaiJSXjbpW(M5 z{mH_i3w|dorT-@x(jK#mBT66ySo0sLRimTDb>U^XW7Y9Mo~2J@6_=lS3%)N}QAS15VgPAUSKuBaQfGOZ08fo>mD$6rY6 zz-D%-N@pD^m#LDHLHLH!r*Y4g9%8CZm`}s0>|6587N(}hvT-YxH%CPbQDMF|1c8q+ z&SITs%1VSu!71M#i9K}nR#yYAU z605Txg6u&1Tgjh&PY;bdNg;PyQ&7F*|7qMjquF2-Fr1Xc7pqE&Xo4EGXQ@raY>E$G zOGM2mDxbY6MXV^zXOz^aJ!-3#qN?_&8Wq&mNL8$&_Po94+;e~4bKhUjd4In@pZC{K z6a7JL{lqUh8BNyA{su*x*BE!?S+$&`+8u`5P11!Dv|b8t73u2@&-bzRCe~|L#;KmG z{E?}31Zx3Sj2Q&J8t`&NVeU1_?nIqRL{m&$gxZhWaC)ZXSA+{uVwvEV;8dptj#GN2 z-K@=;vjgsJk$h?=kGajBEkxB)RNbhBb3h;K)gROS4Ju^?jAqiwiP#xnDCanK6czux z@PQ*;s$WiFWoq5z<|qM7!~{P5QAe;uwsw0+G$6kjJ)t5pF2_K#A+->3HxobgzlHYK z%kMBB)f7E&2TpC!6dLUuF|d-eb^TG1U>a|t(RkTGXFza_*LP-wwzTzHPotSdI~zP* zY-yaPpv#UGAUMW5o!A#P^bl@;hdRD^GxwvtDh|%wSojf^`t>;ZVQ_`(;fS;5(NZ|K zAoFE{tQ6y1gwj%hGBVQJEBJbtdr87j8TD#&{Y&X1?WaIAs5AF+mPpt-as5>dV_8_J_*p6un9MgI9b?n&hy`gZu!XTLGMEO|REdiNoLbf%AF-3LzD4+}sh zird0T@;Vqe=i#>mfTIMB=kDA(E~+#~I`F~OH(XmAvW?mlLzb!6GHSKZpTc*D)AjfC z?)3s}In1}FBkS~~fw8)PA8+Op`_h`h3bs)O;^o~kS1q|-Eso|WYG+r~>ii>t6rC4h zoL>1D#8!&S6By^0UF*-_d9sX0!|W07v8~?p8HQH|-w^p!5^c`e6I3198E^yqzh)uX z^dbiWjzdn6tN`YqrSDu3b}X)KrBljPg8C#W4i`21^jw|_;(+@D`sL;%JGY3s+G{uT zqOUN^fDH>Q5hIUY^mLyQTzp^6bgvfz9%Bz}OsD&*2R!l}0=+R^k8YJ0zHYEh(R{SK zlBaq+q5y`5r-s6S@_kG_6K?nOwP2jlP#Z*9rkp*Y7N6rY`0JXVstG6qIpglXq+aBE z*j?kCs<9dy(OwCkSyjT_o>;uE;dtM!OkY*_s6(zZM{8tVZT@xAdf<{2;M!umPISTaT3HW_JbXz&@$wmLzV(pZ;PhsVIM2YYb&Rl_xS=tf1CgTt>THfPXbN^Oj z*8?Xv>a&eTWIehO&#@3j^`L$IG%7Ua;#CZCMlWBX4RhbC?!(9805+>U3Vn$b% zal}?=s@2RqBz0$&;CxC^9oH+BcTC{~xPyQJu&BM-uHE4 z-$Jq17~g>9a{TRECW+4U3#P}Le(%+fDNk1O_M4Ln*N?R3Enugl-2hE&f??CAHfAW3 zm*+9Mf{-NBZunQ>&@Hesd?7U62kqUKP79h`y?J(e{gyX9q^ieio8!hER4<~>dAr9) zaiRh3I`o&_;JbD0?LFZ>WgmOb)T1 zoq`b`(t;(D8q@;AhLW-Lxrnz>UG(BK@h7}iISs^S@i~;` zQYCIH!*?VrZt7ay-81e?~+|N9mH{^m!dc?jS~3zdGYasuG8_3cUDtjgz_*6%)3QPo>biY zEIVjVSvYTUp3dF+$BT$;M(k|Qwh@_`$TCQOh}^_tC6~4eQn-_sU$^~JBS(^lsn>lD zHcnlX2B>u>XcX`7295$Vy71z?Cs2Lu74U;o{D{ zg&4tJWWiFfoG7akj?6EF68V-$SVC2{I0pq z2ggg{Q=X9v+mb2lD$06}{JkdB@wchb76QzEo5t2w|Eb8USVnm}$8OdDL!SMgY7jqGSe*v3^2HyYx literal 0 HcmV?d00001 diff --git a/mkdocs.yaml b/mkdocs.yaml new file mode 100644 index 00000000..57bc4bcc --- /dev/null +++ b/mkdocs.yaml @@ -0,0 +1,25 @@ +site_name: AI-on-Demand REST API +site_url: https://api.aiod.eu/docs +theme: + name: material + features: + - content.code.copy + +nav: + - Using the API: Using.md + - Hosting the API: Hosting.md + - 'Developer Resources': README.md + - 'Unorganized Docs': + - 'Code Advice': developer/code.md + - 'Keycloak': developer/auth.md + - 'DB Schema Migration': developer/migration.md + - 'Scripts': developer/scripts.md + +markdown_extensions: + - pymdownx.snippets: + check_paths: true + - admonition + - pymdownx.details + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f1f917c9..f693d8b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ authors = [ { name = "Taniya Das", email = "t.das@tue.nl" } ] dependencies = [ + "mkdocs-material", "urllib3== 2.1.0", "bibtexparser==1.4.1", "huggingface_hub==0.23.4",