pax_global_header00006660000000000000000000000064151566025440014522gustar00rootroot0000000000000052 comment=0b67d47637a9e831287447a6691d1c8c37a6eccb vitalik-django-ninja-0b67d47/000077500000000000000000000000001515660254400160615ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/.dockerignore000066400000000000000000000001021515660254400205260ustar00rootroot00000000000000*.pyc .venv* .vscode .mypy_cache .coverage htmlcov dist test.py vitalik-django-ninja-0b67d47/.github/000077500000000000000000000000001515660254400174215ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/.github/FUNDING.yml000066400000000000000000000001131515660254400212310ustar00rootroot00000000000000# polar: django-ninja custom: ["https://www.buymeacoffee.com/djangoninja"] vitalik-django-ninja-0b67d47/.github/ISSUE_TEMPLATE/000077500000000000000000000000001515660254400216045ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000010661515660254400243010ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: "[BUG] " labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **Versions (please complete the following information):** - Python version: [e.g. 3.6] - Django version: [e.g. 4.0] - Django-Ninja version: [e.g. 0.16.2] - Pydantic version: [e.g. 1.9.0] Note you can quickly get this by runninng in `./manage.py shell` this line: ``` import django; import pydantic; import ninja; django.__version__; ninja.__version__; pydantic.__version__ ``` vitalik-django-ninja-0b67d47/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000005551515660254400253360ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. vitalik-django-ninja-0b67d47/.github/ISSUE_TEMPLATE/question.md000066400000000000000000000004061515660254400237750ustar00rootroot00000000000000--- name: Question about: Having troubles implementing something ? title: '' labels: '' assignees: '' --- Please describe what you are trying to achieve Please include code examples (like models code, schemes code, view function) to help understand the issue vitalik-django-ninja-0b67d47/.github/dependabot.yml000066400000000000000000000001661515660254400222540ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: monthly vitalik-django-ninja-0b67d47/.github/workflows/000077500000000000000000000000001515660254400214565ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/.github/workflows/close-old-issues.yml000066400000000000000000000137301515660254400253770ustar00rootroot00000000000000name: Close Old Issues on: workflow_dispatch: inputs: days_old: description: 'Close issues older than N days' required: true default: '365' type: number dry_run: description: 'Dry run mode (preview only, do not close)' required: true default: true type: boolean comment_on_close: description: 'Add comment when closing issues' required: true default: true type: boolean jobs: close-old-issues: runs-on: ubuntu-latest permissions: issues: write steps: - name: Close or list old issues uses: actions/github-script@v8 with: script: | const daysOld = ${{ inputs.days_old }}; const dryRun = ${{ inputs.dry_run }}; const addComment = ${{ inputs.comment_on_close }}; const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - daysOld); console.log(`Looking for issues older than ${daysOld} days (before ${cutoffDate.toISOString()})`); console.log(`Dry run mode: ${dryRun ? 'YES (no changes will be made)' : 'NO (issues will be closed)'}`); console.log('---'); let page = 1; let issuesClosed = 0; let issuesToClose = []; while (true) { const issues = await github.rest.issues.listForRepo({ owner: context.repo.owner, repo: context.repo.repo, state: 'open', sort: 'created', direction: 'asc', per_page: 100, page: page }); if (issues.data.length === 0) { break; } for (const issue of issues.data) { // Skip pull requests if (issue.pull_request) { continue; } const createdAt = new Date(issue.created_at); const updatedAt = new Date(issue.updated_at); // Check if issue is old enough based on last update if (updatedAt < cutoffDate) { const daysOldCalculated = Math.floor((Date.now() - updatedAt.getTime()) / (1000 * 60 * 60 * 24)); issuesToClose.push({ number: issue.number, title: issue.title, created_at: createdAt.toISOString().split('T')[0], updated_at: updatedAt.toISOString().split('T')[0], days_old: daysOldCalculated, url: issue.html_url }); } } page++; } console.log(`\nFound ${issuesToClose.length} issue(s) to close:\n`); for (const issue of issuesToClose) { console.log(`#${issue.number}: ${issue.title}`); console.log(` Created: ${issue.created_at}`); console.log(` Last updated: ${issue.updated_at} (${issue.days_old} days ago)`); console.log(` URL: ${issue.url}`); console.log(''); if (!dryRun) { try { // Add a comment before closing (if enabled) if (addComment) { await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number, body: `This issue has been automatically closed due to inactivity (no updates for ${issue.days_old} days). If you believe this issue is still relevant, please feel free to reopen it or create a new issue.` }); } // Close the issue await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number, state: 'closed', state_reason: 'not_planned' }); issuesClosed++; console.log(` ✓ Closed issue #${issue.number}`); } catch (error) { console.error(` ✗ Failed to close issue #${issue.number}: ${error.message}`); } } } console.log('\n---'); if (dryRun) { console.log(`DRY RUN: Would close ${issuesToClose.length} issue(s)`); console.log('To actually close these issues, run this workflow again with dry_run set to false'); } else { console.log(`Successfully closed ${issuesClosed} out of ${issuesToClose.length} issue(s)`); } // Set output for summary core.summary .addHeading(dryRun ? 'Dry Run Results' : 'Close Old Issues Results') .addRaw(`**Mode:** ${dryRun ? '🔍 Dry Run (Preview Only)' : '✅ Live Run'}\n`) .addRaw(`**Cutoff Date:** Issues last updated before ${cutoffDate.toISOString().split('T')[0]}\n`) .addRaw(`**Days Old Threshold:** ${daysOld} days\n`) .addRaw(`**Issues ${dryRun ? 'Found' : 'Closed'}:** ${dryRun ? issuesToClose.length : issuesClosed}\n\n`); if (issuesToClose.length > 0) { core.summary.addHeading('Issues', 3); const tableData = issuesToClose.map(issue => [ `#${issue.number}`, issue.title.substring(0, 80) + (issue.title.length > 80 ? '...' : ''), issue.updated_at, `${issue.days_old} days`, `[View](${issue.url})` ]); core.summary.addTable([ ['Issue', 'Title', 'Last Updated', 'Age', 'Link'], ...tableData ]); } else { core.summary.addRaw('\nNo issues found matching the criteria.'); } await core.summary.write(); vitalik-django-ninja-0b67d47/.github/workflows/docs.yml000066400000000000000000000003531515660254400231320ustar00rootroot00000000000000name: Docs on: workflow_dispatch: jobs: docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Docs update run: git push origin master:docs vitalik-django-ninja-0b67d47/.github/workflows/publish.yml000066400000000000000000000011511515660254400236450ustar00rootroot00000000000000name: Publish on: release: types: [published] workflow_dispatch: jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 - name: Install Flit run: pip install flit - name: Install Dependencies run: flit install --symlink - name: Publish env: # FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }} # FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }} FLIT_USERNAME: __token__ FLIT_PASSWORD: ${{ secrets.PYPI_TOKEN }} run: flit publish vitalik-django-ninja-0b67d47/.github/workflows/test.yml000066400000000000000000000010571515660254400231630ustar00rootroot00000000000000name: Test Coverage on: push: branches: - master jobs: test_coverage: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install Flit run: pip install flit "django>=5.1" - name: Install Dependencies run: flit install --symlink - name: Test run: pytest --cov=ninja --cov-report=xml tests - name: Coverage uses: codecov/codecov-action@v4.4.1 vitalik-django-ninja-0b67d47/.github/workflows/test_full.yml000066400000000000000000000053151515660254400242060ustar00rootroot00000000000000name: Full Test on: push: workflow_dispatch: pull_request: types: [assigned, opened, synchronize, reopened] jobs: test: runs-on: ubuntu-22.04 strategy: matrix: python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] django-version: ['<3.2', '<3.3', '<4.2', '<4.3', '<5.1', '<5.2', '<5.3', '<6.1'] exclude: - python-version: '3.7' django-version: '<5.1' - python-version: '3.8' django-version: '<5.1' - python-version: '3.9' django-version: '<5.1' - python-version: '3.12' django-version: '<3.2' - python-version: '3.12' django-version: '<3.3' - python-version: '3.13' django-version: '<3.2' - python-version: '3.13' django-version: '<3.3' # as of oct 2025 looks like django < 5.2 does not support python 3.14 - python-version: '3.14' django-version: '<3.2' - python-version: '3.14' django-version: '<3.3' - python-version: '3.14' django-version: '<4.2' - python-version: '3.14' django-version: '<4.3' - python-version: '3.14' django-version: '<5.1' - python-version: '3.14' django-version: '<5.2' steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install core run: pip install "Django${{ matrix.django-version }}" "pydantic<3" - name: Install tests run: pip install pytest pytest-asyncio pytest-django psycopg2-binary - name: Test run: pytest coverage: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: 3.12 - name: Install Flit run: pip install flit "django>=5.2" - name: Install Dependencies run: flit install --symlink - name: Test run: pytest --cov=ninja codestyle: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: 3.12 - name: Install Flit run: pip install flit - name: Install Dependencies run: flit install --symlink - name: Ruff format run: ruff format --check ninja tests - name: Ruff lint run: ruff check ninja tests - name: mypy run: mypy ninja tests/mypy_test.py vitalik-django-ninja-0b67d47/.gitignore000066400000000000000000000002061515660254400200470ustar00rootroot00000000000000*.pyc .venv* .vscode .mypy_cache .coverage htmlcov /coverage.xml dist test.py docs/site .DS_Store .idea .python-version *.local.md vitalik-django-ninja-0b67d47/.pre-commit-config.yaml000066400000000000000000000010331515660254400223370ustar00rootroot00000000000000repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.2.0 hooks: - id: check-yaml # - id: end-of-file-fixer # - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.7.1 hooks: - id: mypy additional_dependencies: ["django-stubs", "pydantic"] exclude: (tests|docs)/ - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.4.2 hooks: - id: ruff-format - id: ruff args: [--fix, --exit-non-zero-on-fix] vitalik-django-ninja-0b67d47/CONTRIBUTING.md000066400000000000000000000023511515660254400203130ustar00rootroot00000000000000# Contributing Django Ninja uses Flit to build, package and publish the project. to install it use: ``` pip install flit ``` Once you have it - to install all dependencies required for development and testing use this command: ``` flit install --deps develop --symlink ``` Once done you can check if all works with ``` pytest . ``` or using Makefile: ``` make test ``` Now you are ready to make your contribution When you're done please make sure you to test your functionality and check the coverage of your contribution. ``` pytest --cov=ninja --cov-report term-missing tests ``` or using Makefile: ``` make test-cov ``` ## Code style Django Ninja uses `ruff`, and `mypy` for style checks. Run `pre-commit install` to create a git hook to fix your styles before you commit. Alternatively, manually check your code with: ``` ruff format --check ninja tests ruff check ninja tests mypy ninja ``` or using Makefile: ``` make lint ``` Or reformat your code with: ``` ruff format ninja tests ruff check ninja tests --fix ``` or using Makefile: ``` make fmt ``` ## Docs Please do not forget to document your contribution Django Ninja uses `mkdocs`: ``` cd docs/ mkdocs serve ``` and go to browser to see changes in real time vitalik-django-ninja-0b67d47/LICENSE000066400000000000000000000020761515660254400170730ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2025 Vitaliy Kucheryaviy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. vitalik-django-ninja-0b67d47/Makefile000066400000000000000000000014001515660254400175140ustar00rootroot00000000000000.DEFAULT_GOAL := help .PHONY: help help: @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' .PHONY: install install: ## Install dependencies flit install --deps develop --symlink .PHONY: lint lint: ## Run code linters ruff format --check ninja tests ruff check ninja tests mypy ninja .PHONY: fmt format fmt format: ## Run code formatters ruff format ninja tests ruff check --fix ninja tests .PHONY: test test: ## Run tests pytest . .PHONY: test-cov test-cov: ## Run tests with coverage pytest --cov=ninja --cov-report term-missing tests .PHONY: docs docs: ## Serve documentation locally pip install -r docs/requirements.txt cd docs && mkdocs serve -a localhost:8090 vitalik-django-ninja-0b67d47/README.md000066400000000000000000000073601515660254400173460ustar00rootroot00000000000000SCR-20230123-m1t ^ Please read ^

Fast to learn, fast to code, fast to run

![Test](https://github.com/vitalik/django-ninja/actions/workflows/test_full.yml/badge.svg) ![Coverage](https://img.shields.io/codecov/c/github/vitalik/django-ninja) [![PyPI version](https://badge.fury.io/py/django-ninja.svg)](https://badge.fury.io/py/django-ninja) [![Downloads](https://static.pepy.tech/personalized-badge/django-ninja?period=month&units=international_system&left_color=black&right_color=brightgreen&left_text=downloads/month)](https://pepy.tech/project/django-ninja) # Django Ninja - Fast Django REST Framework **Django Ninja** is a web framework for building APIs with **Django** and Python 3.6+ **type hints**. **Key features:** - **Easy**: Designed to be easy to use and intuitive. - **FAST execution**: Very high performance thanks to **Pydantic** and **async support**. - **Fast to code**: Type hints and automatic docs lets you focus only on business logic. - **Standards-based**: Based on the open standards for APIs: **OpenAPI** (previously known as Swagger) and **JSON Schema**. - **Django friendly**: (obviously) has good integration with the Django core and ORM. - **Production ready**: Used by multiple companies on live projects (If you use django-ninja and would like to publish your feedback, please email ppr.vitaly@gmail.com). ![Django Ninja REST Framework](docs/docs/img/benchmark.png) **Documentation**: https://django-ninja.dev --- ## Installation ``` pip install django-ninja ``` ## Usage In your django project next to urls.py create new `api.py` file: ```Python from ninja import NinjaAPI api = NinjaAPI() @api.get("/add") def add(request, a: int, b: int): return {"result": a + b} ``` Now go to `urls.py` and add the following: ```Python hl_lines="3 7" ... from .api import api urlpatterns = [ path("admin/", admin.site.urls), path("api/", api.urls), # <---------- ! ] ``` **That's it !** Now you've just created an API that: - receives an HTTP GET request at `/api/add` - takes, validates and type-casts GET parameters `a` and `b` - decodes the result to JSON - generates an OpenAPI schema for defined operation ### Interactive API docs Now go to http://127.0.0.1:8000/api/docs You will see the automatic interactive API documentation (provided by Swagger UI or Redoc): ![Swagger UI](docs/docs/img/index-swagger-ui.png) ## Sponsors sendcloud-logo Become a sponsor ## What next? - Read the full documentation here - https://django-ninja.dev - To support this project, please give star it on Github. ![github star](docs/docs/img/github-star.png) - Share it [via Twitter](https://twitter.com/intent/tweet?text=Check%20out%20Django%20Ninja%20-%20Fast%20Django%20REST%20Framework%20-%20https%3A%2F%2Fdjango-ninja.dev) - If you already using django-ninja, please share your feedback to ppr.vitaly@gmail.com vitalik-django-ninja-0b67d47/docs/000077500000000000000000000000001515660254400170115ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/000077500000000000000000000000001515660254400177415ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/chat.md000066400000000000000000000012651515660254400212060ustar00rootroot00000000000000# Ask AI Please feel free to share any questions or describe any problems you're encountering. Simply enter your text in the chat, and I'll be happy to assist you.
vitalik-django-ninja-0b67d47/docs/docs/extra.css000066400000000000000000000024031515660254400215750ustar00rootroot00000000000000.doc-module code { white-space: nowrap; } /* Ask AI Button Styles */ .ask-ai-button-container { display: flex; align-items: center; margin-left: auto; margin-right: 1rem; } .ask-ai-button { background-color: white !important; color: #4caf50 !important; /* Material green-500 */ padding: 0.4rem 0.5rem !important; border-radius: 0.25rem; font-weight: 500; text-decoration: none; font-size: 0.9rem; border: 2px solid #4caf50; transition: all 0.2s ease-in-out; white-space: nowrap; margin-left: 8px; } .ask-ai-button:hover { background-color: #4caf50 !important; color: white !important; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } /* Dark mode support */ [data-md-color-scheme="slate"] .ask-ai-button { background-color: white !important; color: #4caf50 !important; } [data-md-color-scheme="slate"] .ask-ai-button:hover { background-color: #4caf50 !important; color: white !important; } /* Responsive adjustments */ @media screen and (max-width: 76.1875em) { .ask-ai-button-container { margin-right: 0.5rem; } .ask-ai-button { padding: 0.4rem 0.8rem !important; font-size: 0.85rem; } } @media screen and (max-width: 60em) { .ask-ai-button-container { display: none; /* Hide on mobile to save space */ } } vitalik-django-ninja-0b67d47/docs/docs/guides/000077500000000000000000000000001515660254400212215ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/guides/api-docs.md000066400000000000000000000106321515660254400232440ustar00rootroot00000000000000# API Docs ## OpenAPI docs Once you configured your Ninja API and started runserver - go to http://127.0.0.1:8000/api/docs You will see the automatic, interactive API documentation (provided by the OpenAPI / Swagger UI ## CDN vs staticfiles You are not required to put django ninja to `INSTALLED_APPS`. In that case the interactive UI is hosted by CDN. To host docs (Js/css) from your own server - just put "ninja" to INSTALLED_APPS - in that case standard django staticfiles mechanics will host it. ## Switch to Redoc ```python from ninja import Redoc api = NinjaAPI(docs=Redoc()) ``` Then you will see the alternative automatic documentation (provided by Redoc). ## Changing docs display settings To set some custom settings for Swagger or Redocs you can use `settings` param on the docs class ```python from ninja import Redoc, Swagger api = NinjaAPI(docs=Swagger(settings={"persistAuthorization": True})) ... api = NinjaAPI(docs=Redoc(settings={"disableSearch": True})) ``` Settings reference: - [Swagger configuration](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/) - [Redoc configuration](https://redocly.com/docs/api-reference-docs/configuration/functionality/) ## Hiding docs ### Hiding the interactive docs viewer To hide only the interactive documentation UI (Swagger or Redoc) while keeping the OpenAPI schema accessible, set `docs_url` to `None`: ```python api = NinjaAPI(docs_url=None) ``` This disables the `/docs` endpoint but the OpenAPI schema remains available at `/openapi.json`. This is useful when you want to: - Disable the interactive UI but keep the schema for API clients or code generators - Use external documentation tools that consume the OpenAPI spec ### Disabling the OpenAPI schema endpoint To disable the OpenAPI schema endpoint, set `openapi_url` to `None`: ```python api = NinjaAPI(openapi_url=None) ``` This disables the `/openapi.json` endpoint. Since the docs viewer depends on the OpenAPI schema, this also disables the docs viewer - no documentation URLs will be registered. ### Summary | Configuration | `/openapi.json` | `/docs` | Use Case | |---------------|-----------------|---------|----------| | Default | Available | Available | Development | | `docs_url=None` | Available | Hidden | Hide UI, keep schema for clients | | `openapi_url=None` | Hidden | Hidden | Completely hide all documentation | ## Protecting docs To protect docs with authentication (or decorate for some other use case) use `docs_decorator` argument: ```python from django.contrib.admin.views.decorators import staff_member_required api = NinjaAPI(docs_decorator=staff_member_required) ``` ## Extending OpenAPI Spec with custom attributes You can extend OpenAPI spec with custom attributes, for example to add `termsOfService` ```python api = NinjaAPI( openapi_extra={ "info": { "termsOfService": "https://example.com/terms/", } }, title="Demo API", description="This is a demo API with dynamic OpenAPI info section" ) ``` ## Resolving the doc's url The url for the api's documentation view can be reversed by referencing the view's name `openapi-view`. In Python code, for example: ```python from django.urls import reverse reverse('api-1.0.0:openapi-view') >>> '/api/docs' ``` In a Django template, for example: ```Html API Docs API Docs ``` ## Creating custom docs viewer To create your own view for OpenAPI - create a class inherited from DocsBase and overwrite `render_page` method: ```python from ninja.openapi.docs import DocsBase class MyDocsViewer(DocsBase): def render_page(self, request, api): ... # return http response ... api = NinjaAPI(docs=MyDocsViewer()) ``` ## Using a custom favicon The django-ninja OpenAPI docs contain a default favicon, the ninja star. To use your own, overwrite the `ninja/favicon.html` django template. ```html {% load static %} {% block favicons %} {% endblock %} ``` for more information, see the [Django documentation on overriding templates](https://docs.djangoproject.com/en/5.2/howto/overriding-templates/). vitalik-django-ninja-0b67d47/docs/docs/guides/async-support.md000066400000000000000000000150701515660254400243750ustar00rootroot00000000000000## Intro Since **version 3.1**, Django comes with **async views support**. This allows you run efficient concurrent views that are network and/or IO bound. ``` pip install Django>=3.1 django-ninja ``` Async views work more efficiently when it comes to: - calling external APIs over the network - executing/waiting for database queries - reading/writing from/to disk drives **Django Ninja** takes full advantage of async views and makes it very easy to work with them. ## Quick example ### Code Let's take an example. We have an API operation that does some work (currently just sleeps for provided number of seconds) and returns a word: ```python hl_lines="5" import time @api.get("/say-after") def say_after(request, delay: int, word: str): time.sleep(delay) return {"saying": word} ``` To make this code asynchronous, all you have to do is add the **`async`** keyword to a function (and use async aware libraries for work processing - in our case we will replace the stdlib `sleep` with `asyncio.sleep`): ```python hl_lines="1 4 5" import asyncio @api.get("/say-after") async def say_after(request, delay: int, word: str): await asyncio.sleep(delay) return {"saying": word} ``` ### Run To run this code you need an ASGI server like Uvicorn or Daphne. Let's use Uvicorn for, example: To install Uvicorn, use: ``` pip install uvicorn ``` Then start the server: ``` uvicorn your_project.asgi:application --reload ``` > > *Note: replace `your_project` with your project package name*
> *`--reload` flag used to automatically reload server if you do any changes to the code (do not use on production)* >
!!! note You can run async views with `manage.py runserver`, but it does not work well with some libraries, so at this time (July 2020) it is recommended to use ASGI servers like Uvicorn or Daphne. ### Test Go to your browser and open http://127.0.0.1:8000/api/say-after?delay=3&word=hello (**delay=3**) After a 3-second wait you should see the "hello" message. Now let's flood this operation with **100 parallel requests**: ``` ab -c 100 -n 100 "http://127.0.0.1:8000/api/say-after?delay=3&word=hello" ``` which will result in something like this: ``` Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 1.1 1 4 Processing: 3008 3063 16.2 3069 3082 Waiting: 3008 3062 15.7 3068 3079 Total: 3008 3065 16.3 3070 3083 Percentage of the requests served within a certain time (ms) 50% 3070 66% 3072 75% 3075 80% 3076 90% 3081 95% 3082 98% 3083 99% 3083 100% 3083 (longest request) ``` Based on the numbers, our service was able to handle each of the 100 concurrent requests with just a little overhead. To achieve the same concurrency with WSGI and sync operations you would need to spin up about 10 workers with 10 threads each! ## Mixing sync and async operations Keep in mind that you can use **both sync and async operations** in your project, and **Django Ninja** will route it automatically: ```python hl_lines="2 7" @api.get("/say-sync") def say_after_sync(request, delay: int, word: str): time.sleep(delay) return {"saying": word} @api.get("/say-async") async def say_after_async(request, delay: int, word: str): await asyncio.sleep(delay) return {"saying": word} ``` ## Elasticsearch example Let's take a real world use case. For this example, let's use the latest version of Elasticsearch that now comes with async support: ``` pip install elasticsearch>=7.8.0 ``` And now instead of the `Elasticsearch` class, use the `AsyncElasticsearch` class and `await` the results: ```python hl_lines="2 7 11 12" from ninja import NinjaAPI from elasticsearch import AsyncElasticsearch api = NinjaAPI() es = AsyncElasticsearch() @api.get("/search") async def search(request, q: str): resp = await es.search( index="documents", body={"query": {"query_string": {"query": q}}}, size=20, ) return resp["hits"] ``` ## Using ORM Currently, certain key parts of Django are not able to operate safely in an async environment, as they have global state that is not coroutine-aware. These parts of Django are classified as “async-unsafe”, and are protected from execution in an async environment. **The ORM** is the main example, but there are other parts that are also protected in this way. Learn more about async safety here in the official Django docs. So, if you do this: ```python hl_lines="3" @api.get("/blog/{post_id}") async def search(request, post_id: int): blog = Blog.objects.get(pk=post_id) ... ``` it throws an error. Until the async ORM is implemented, you can use the `sync_to_async()` adapter: ```python hl_lines="1 3 9" from asgiref.sync import sync_to_async @sync_to_async def get_blog(post_id): return Blog.objects.get(pk=post_id) @api.get("/blog/{post_id}") async def search(request, post_id: int): blog = await get_blog(post_id) ... ``` or even shorter: ```python hl_lines="3" @api.get("/blog/{post_id}") async def search(request, post_id: int): blog = await sync_to_async(Blog.objects.get)(pk=post_id) ... ``` There is a common **GOTCHA**: Django querysets are lazily evaluated (database query happens only when you start iterating), so this will **not** work: ```python all_blogs = await sync_to_async(Blog.objects.all)() # it will throw an error later when you try to iterate over all_blogs ... ``` Instead, use evaluation (with `list`): ```python all_blogs = await sync_to_async(list)(Blog.objects.all()) ... ``` Since Django **version 4.1**, Django comes with asynchronous versions of ORM operations. These eliminate the need to use `sync_to_async` in most cases. The async operations have the same names as their sync counterparts but are prepended with *a*. So using the example above, you can rewrite it as: ```python hl_lines="3" @api.get("/blog/{post_id}") async def search(request, post_id: int): blog = await Blog.objects.aget(pk=post_id) ... ``` When working with querysets, use `async for` paired with list comprehension: ```python all_blogs = [blog async for blog in Blog.objects.all()] ... ``` Learn more about the async ORM interface in the official Django docs. vitalik-django-ninja-0b67d47/docs/docs/guides/authentication.md000066400000000000000000000145321515660254400245670ustar00rootroot00000000000000# Authentication ## Intro **Django Ninja** provides several tools to help you deal with authentication and authorization easily, rapidly, in a standard way, and without having to study and learn all the security specifications. The core concept is that when you describe an API operation, you can define an authentication object. ```python hl_lines="2 7" {!./src/tutorial/authentication/code001.py!} ``` In this example, the client will only be able to call the `pets` method if it uses Django session authentication (the default is cookie based), otherwise an HTTP-401 error will be returned. If you need to authorize only a superuser, you can use `from ninja.security import django_auth_superuser` instead. ## Automatic OpenAPI schema Here's an example where the client, in order to authenticate, needs to pass a header: `Authorization: Bearer supersecret` ```python hl_lines="4 5 6 7 10" {!./src/tutorial/authentication/bearer01.py!} ``` Now go to the docs at http://localhost:8000/api/docs. ![Swagger UI Auth](../img/auth-swagger-ui.png) Now, when you click the **Authorize** button, you will get a prompt to input your authentication token. ![Swagger UI Auth](../img/auth-swagger-ui-prompt.png) When you do test calls, the Authorization header will be passed for every request. ## Global authentication In case you need to secure **all** methods of your API, you can pass the `auth` argument to the `NinjaAPI` constructor: ```python hl_lines="11 19" from ninja import NinjaAPI, Form from ninja.security import HttpBearer class GlobalAuth(HttpBearer): def authenticate(self, request, token): if token == "supersecret": return token api = NinjaAPI(auth=GlobalAuth()) # @api.get(...) # def ... # @api.post(...) # def ... ``` And, if you need to overrule some of those methods, you can do that on the operation level again by passing the `auth` argument. In this example, authentication will be disabled for the `/token` operation: ```python hl_lines="19" {!./src/tutorial/authentication/global01.py!} ``` ## Available auth options ### Custom function The "`auth=`" argument accepts any Callable object. **NinjaAPI** passes authentication only if the callable object returns a value that can be **converted to boolean `True`**. This return value will be assigned to the `request.auth` attribute. ```python hl_lines="1 2 3 6" {!./src/tutorial/authentication/code002.py!} ``` ### API Key Some API's use API keys for authorization. An API key is a token that a client provides when making API calls to identify itself. The key can be sent in the query string: ``` GET /something?api_key=abcdef12345 ``` or as a request header: ``` GET /something HTTP/1.1 X-API-Key: abcdef12345 ``` or as a cookie: ``` GET /something HTTP/1.1 Cookie: X-API-KEY=abcdef12345 ``` **Django Ninja** comes with built-in classes to help you handle these cases. #### in Query ```python hl_lines="1 2 5 6 7 8 9 10 11 12" {!./src/tutorial/authentication/apikey01.py!} ``` In this example we take a token from `GET['api_key']` and find a `Client` in the database that corresponds to this key. The Client instance will be set to the `request.auth` attribute. Note: **`param_name`** is the name of the GET parameter that will be checked for. If not set, the default of "`key`" will be used. #### in Header ```python hl_lines="1 4" {!./src/tutorial/authentication/apikey02.py!} ``` #### in Cookie ```python hl_lines="1 4" {!./src/tutorial/authentication/apikey03.py!} ``` ### Django Session Authentication **Django Ninja** provides built-in session authentication classes that leverage Django's existing session framework: #### SessionAuth Uses Django's default session authentication - authenticates any logged-in user: ```python from ninja.security import SessionAuth @api.get("/protected", auth=SessionAuth()) def protected_view(request): return {"user": request.auth.username} ``` #### SessionAuthSuperUser Authenticates only users with superuser privileges: ```python from ninja.security import SessionAuthSuperUser @api.get("/admin-only", auth=SessionAuthSuperUser()) def admin_view(request): return {"message": "Hello superuser!"} ``` #### SessionAuthIsStaff Authenticates users who are either superusers or staff members: ```python from ninja.security import SessionAuthIsStaff @api.get("/staff-area", auth=SessionAuthIsStaff()) def staff_view(request): return {"message": "Hello staff member!"} ``` These authentication classes automatically use Django's `SESSION_COOKIE_NAME` setting and check the user's authentication status through the standard Django session framework. ### HTTP Bearer ```python hl_lines="1 4 5 6 7" {!./src/tutorial/authentication/bearer01.py!} ``` ### HTTP Basic Auth ```python hl_lines="1 4 5 6 7" {!./src/tutorial/authentication/basic01.py!} ``` ## Multiple authenticators The **`auth`** argument also allows you to pass multiple authenticators: ```python hl_lines="18" {!./src/tutorial/authentication/multiple01.py!} ``` In this case **Django Ninja** will first check the API key `GET`, and if not set or invalid will check the `header` key. If both are invalid, it will raise an authentication error to the response. ## Router authentication Use `auth` argument on Router to apply authenticator to all operations declared in it: ```python api.add_router("/events/", events_router, auth=BasicAuth()) ``` or using router constructor ```python router = Router(auth=BasicAuth()) ``` This overrides any API level authentication. To allow router operations to not use the API-level authentication by default, you can explicitly set the router's `auth=None`. ## Custom exceptions Raising an exception that has an exception handler will return the response from that handler in the same way an operation would: ```python hl_lines="1 4" {!./src/tutorial/authentication/bearer02.py!} ``` ## Async authentication **Django Ninja** has basic support for asynchronous authentication. While the default authentication classes are not async-compatible, you can still define your custom asynchronous authentication callables and pass them in using `auth`. ```python async def async_auth(request): ... @api.get("/pets", auth=async_auth) def pets(request): ... ``` See [Handling errors](errors.md) for more information. vitalik-django-ninja-0b67d47/docs/docs/guides/decorators.md000066400000000000000000000244111515660254400237120ustar00rootroot00000000000000# Decorators Django Ninja provides flexible decorator support to wrap your API operations with additional functionality like caching, logging, authentication checks, or any custom logic. ## Understanding Decorator Modes Django Ninja supports two modes for applying decorators: ### OPERATION Mode (Default) - Applied **after** Django Ninja's validation - Wraps the operation function with validated data - Has access to parsed and validated parameters - Useful for: business logic, logging with validated data, post-validation checks ### VIEW Mode - Applied **before** Django Ninja's validation - Wraps the entire Django view function - Has access to the raw Django request - Useful for: caching, rate limiting, Django middleware-like functionality - Similar to Django's standard view decorators ## Using `@decorate_view` The `@decorate_view` decorator allows you to apply Django view decorators to individual endpoints. These decorators are always executed in VIEW mode: ```python from django.views.decorators.cache import cache_page from ninja import NinjaAPI from ninja.decorators import decorate_view api = NinjaAPI() @api.get("/cached") @decorate_view(cache_page(60 * 15)) # Cache for 15 minutes def cached_endpoint(request): return {"data": "This response is cached"} ``` You can apply multiple decorators: ```python from django.views.decorators.cache import cache_page from django.views.decorators.vary import vary_on_headers @api.get("/multi") @decorate_view(cache_page(300), vary_on_headers("User-Agent")) def multi_decorated(request): return {"data": "Multiple decorators applied"} ``` ## Using `add_decorator` The `add_decorator` method allows you to apply decorators to multiple endpoints at once. By default, they are executed in OPERATION mode; however, you can switch them to VIEW mode. ### Router-Level Decorators Apply decorators to all endpoints in a router: ```python from ninja import Router router = Router() # Add logging to all operations in this router def log_operation(func): def wrapper(request, *args, **kwargs): print(f"Calling {func.__name__}") result = func(request, *args, **kwargs) print(f"Result: {result}") return result return wrapper router.add_decorator(log_operation) # OPERATION mode by default @router.get("/users") def list_users(request): return {"users": ["Alice", "Bob"]} @router.get("/users/{user_id}") def get_user(request, user_id: int): return {"user_id": user_id} ``` ### API-Level Decorators Apply decorators to all endpoints in your entire API: ```python from ninja import NinjaAPI api = NinjaAPI() # Add CORS headers to all responses (VIEW mode) def cors_headers(func): def wrapper(request, *args, **kwargs): response = func(request, *args, **kwargs) response["Access-Control-Allow-Origin"] = "*" return response return wrapper api.add_decorator(cors_headers, mode="view") # Now all endpoints will have CORS headers @api.get("/data") def get_data(request): return {"data": "example"} ``` ## Practical Examples ### Example 1: Request Timing ```python import time from functools import wraps def timing_decorator(func): @wraps(func) def wrapper(request, *args, **kwargs): start = time.time() result = func(request, *args, **kwargs) duration = time.time() - start if isinstance(result, dict): result["_timing"] = f"{duration:.3f}s" return result return wrapper router = Router() router.add_decorator(timing_decorator) @router.get("/slow") def slow_endpoint(request): time.sleep(1) return {"message": "done"} # Returns: {"message": "done", "_timing": "1.001s"} ``` ### Example 2: Authentication Check (OPERATION mode) ```python from functools import wraps def require_feature_flag(flag_name): def decorator(func): @wraps(func) def wrapper(request, *args, **kwargs): if not request.user.has_feature(flag_name): return {"error": f"Feature {flag_name} not enabled"} return func(request, *args, **kwargs) return wrapper return decorator router = Router() router.add_decorator(require_feature_flag("new_api")) @router.get("/new-feature") def new_feature(request): return {"feature": "enabled"} ``` ### Example 3: Response Caching (VIEW mode) ```python from django.core.cache import cache from functools import wraps import hashlib def cache_response(timeout=300): def decorator(func): @wraps(func) def wrapper(request, *args, **kwargs): # Create cache key from request cache_key = hashlib.md5( f"{request.path}{request.GET.urlencode()}".encode() ).hexdigest() # Try to get from cache cached = cache.get(cache_key) if cached: return cached # Call the view response = func(request, *args, **kwargs) # Cache the response cache.set(cache_key, response, timeout) return response return wrapper return decorator router = Router() router.add_decorator(cache_response(600), mode="view") ``` ## Decorator Execution Order When multiple decorators are applied, they execute in this order: 1. API-level decorators (outermost) 2. Parent router decorators 3. Child router decorators 4. Individual endpoint decorators (innermost) Be aware that VIEW mode decorators are executed before OPERATION mode decorators. ```python api = NinjaAPI() parent_router = Router() child_router = Router() api.add_decorator(api_decorator) parent_router.add_decorator(parent_decorator) child_router.add_decorator(child_decorator) @child_router.get("/test") @decorate_view(endpoint_decorator) def endpoint(request): return {"result": "ok"} parent_router.add_router("/child", child_router) api.add_router("/parent", parent_router) # Execution order: # 1. endpoint_decorator (view) # 1. api_decorator (operational) # 2. parent_decorator (operational) # 3. child_decorator (operational) # 5. endpoint function ``` ## Async Support Decorators work with both sync and async views. When you have mixed sync/async endpoints in the same router, you need to create universal decorators that handle both cases. ### Universal Decorators for Mixed Sync/Async Routers When you have a router with both sync and async endpoints, use `asyncio.iscoroutinefunction()` to detect the function type: ```python import asyncio from functools import wraps def universal_decorator(func): if asyncio.iscoroutinefunction(func): # Handle async functions @wraps(func) async def async_wrapper(request, *args, **kwargs): # Your async logic here result = await func(request, *args, **kwargs) if isinstance(result, dict): result["decorated"] = True result["type"] = "async" return result return async_wrapper else: # Handle sync functions @wraps(func) def sync_wrapper(request, *args, **kwargs): # Your sync logic here result = func(request, *args, **kwargs) if isinstance(result, dict): result["decorated"] = True result["type"] = "sync" return result return sync_wrapper router = Router() router.add_decorator(universal_decorator) @router.get("/async") async def async_endpoint(request): await asyncio.sleep(0.1) return {"endpoint": "async"} @router.get("/sync") def sync_endpoint(request): return {"endpoint": "sync"} ``` ### Async-Only Decorators For routers with only async endpoints, you can use async decorators directly: ```python def async_timing_decorator(func): @wraps(func) async def wrapper(request, *args, **kwargs): start = time.time() result = await func(request, *args, **kwargs) duration = time.time() - start if isinstance(result, dict): result["_timing"] = f"{duration:.3f}s" return result return wrapper router = Router() router.add_decorator(async_timing_decorator) @router.get("/async") async def async_endpoint(request): await asyncio.sleep(1) return {"message": "async done"} ``` ### Sync Decorators on Async Views You can also use sync decorators on async views by handling coroutines: ```python def sync_decorator(func): @wraps(func) def wrapper(request, *args, **kwargs): result = func(request, *args, **kwargs) if asyncio.iscoroutine(result): # Handle async functions async def async_wrapper(): actual_result = await result if isinstance(actual_result, dict): actual_result["sync_decorated"] = True return actual_result return async_wrapper() else: # Handle sync functions if isinstance(result, dict): result["sync_decorated"] = True return result return wrapper ``` ## When to Use Each Mode ### Use VIEW Mode When: - You need access to the raw Django request - Implementing caching at the HTTP level - Adding/modifying HTTP headers - Implementing rate limiting - Working with Django middleware patterns ### Use OPERATION Mode When: - You need access to validated/parsed data - Implementing business logic decorators - Adding data to responses - Logging with type-safe parameters - Post-validation security checks ## Best Practices 1. **Use `functools.wraps`**: Always use `@wraps(func)` to preserve function metadata 2. **Handle mixed sync/async routers**: When your router has both sync and async endpoints, use `asyncio.iscoroutinefunction(func)` to create universal decorators 3. **Choose the right approach for async**: - **Universal decorators**: Best for mixed routers (detect with `iscoroutinefunction`) - **Async-only decorators**: Best for async-only routers (simpler, cleaner) - **Sync decorators with coroutine handling**: Useful for legacy decorators 4. **Be mindful of performance**: Decorators add overhead, especially in VIEW mode 5. **Document side effects**: Clearly document what your decorators modify 6. **Keep decorators focused**: Each decorator should have a single responsibility 7. **Test both sync and async**: When using universal decorators, test both sync and async endpoints vitalik-django-ninja-0b67d47/docs/docs/guides/errors.md000066400000000000000000000111101515660254400230510ustar00rootroot00000000000000# Handling errors **Django Ninja** allows you to install custom exception handlers to deal with how you return responses when errors or handled exceptions occur. ## Custom exception handlers Let's say you are making API that depends on some external service that is designed to be unavailable at some moments. Instead of throwing default 500 error upon exception - you can handle the error and give some friendly response back to the client (to come back later) To achieve that you need: 1. create some exception (or use existing one) 2. use api.exception_handler decorator Example: ```python hl_lines="9 10" api = NinjaAPI() class ServiceUnavailableError(Exception): pass # initializing handler @api.exception_handler(ServiceUnavailableError) def service_unavailable(request, exc): return api.create_response( request, {"message": "Please retry later"}, status=503, ) # some logic that throws exception @api.get("/service") def some_operation(request): if random.choice([True, False]): raise ServiceUnavailableError() return {"message": "Hello"} ``` Exception handler function takes 2 arguments: - **request** - Django http request - **exc** - actual exception function must return http response ## Override the default exception handlers **Django Ninja** registers default exception handlers for the types shown below. You can register your own handlers with `@api.exception_handler` to override the default handlers. #### `ninja.errors.AuthenticationError` Raised when authentication data is not valid #### `ninja.errors.AuthorizationError` Raised when authentication data is valid, but doesn't allow you to access the resource #### `ninja.errors.ValidationError` Raised when request data does not validate #### `ninja.errors.HttpError` Used to throw http error with status code from any place of the code #### `django.http.Http404` Django's default 404 exception (can be returned f.e. with `get_object_or_404`) #### `Exception` Any other unhandled exception by application. Default behavior - **if `settings.DEBUG` is `True`** - returns a traceback in plain text (useful when debugging in console or swagger UI) - **else** - default django exception handler mechanism is used (error logging, email to ADMINS) ## Customizing request validation errors Requests that fail validation raise `ninja.errors.ValidationError` (not to be confused with `pydantic.ValidationError`). `ValidationError`s have a default exception handler that returns a 422 (Unprocessable Content) JSON response of the form: ```json { "detail": [ ... ] } ``` You can change this behavior by overriding the default handler for `ValidationError`s: ```python hl_lines="1 4" from ninja.errors import ValidationError ... @api.exception_handler(ValidationError) def validation_errors(request, exc): return HttpResponse("Invalid input", status=422) ``` If you need even more control over validation errors (for example, if you need to reference the schema associated with the model that failed validation), you can supply your own `validation_error_from_error_contexts` in a `NinjaAPI` subclass: ```python hl_lines="4" from ninja.errors import ValidationError, ValidationErrorContext from typing import Any, Dict, List class CustomNinjaAPI(NinjaAPI): def validation_error_from_error_contexts( self, error_contexts: List[ValidationErrorContext], ) -> ValidationError: custom_error_infos: List[Dict[str, Any]] = [] for context in error_contexts: model = context.model pydantic_schema = model.__pydantic_core_schema__ param_source = model.__ninja_param_source__ for e in context.pydantic_validation_error.errors( include_url=False, include_context=False, include_input=False ): custom_error_info = { # TODO: use `e`, `param_source`, and `pydantic_schema` as desired } custom_error_infos.append(custom_error_info) return ValidationError(custom_error_infos) api = CustomNinjaAPI() ``` Now each `ValidationError` raised during request validation will contain data from your `validation_error_from_error_contexts`. ## Throwing HTTP responses with exceptions As an alternative to custom exceptions and writing handlers for it - you can as well throw http exception that will lead to returning a http response with desired code ```python from ninja.errors import HttpError @api.get("/some/resource") def some_operation(request): if True: raise HttpError(503, "Service Unavailable. Please retry later.") ``` vitalik-django-ninja-0b67d47/docs/docs/guides/input/000077500000000000000000000000001515660254400223605ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/guides/input/body.md000066400000000000000000000111671515660254400236450ustar00rootroot00000000000000# Request Body Request bodies are typically used with “create” and “update” operations (POST, PUT, PATCH). For example, when creating a resource using POST or PUT, the request body usually contains the representation of the resource to be created. To declare a **request body**, you need to use **Django Ninja `Schema`**. !!! info Under the hood **Django Ninja** uses Pydantic models with all their power and benefits. The alias `Schema` was chosen to avoid confusion in code when using Django models, as Pydantic's model class is called Model by default, and conflicts with Django's Model class. ## Import Schema First, you need to import `Schema` from `ninja`: ```python hl_lines="2" {!./src/tutorial/body/code01.py!} ``` ## Create your data model Then you declare your data model as a class that inherits from `Schema`. Use standard Python types for all the attributes: ```python hl_lines="5 6 7 8 9" {!./src/tutorial/body/code01.py!} ``` Note: if you use **`None`** as the default value for an attribute, it will become optional in the request body. For example, this model above declares a JSON "`object`" (or Python `dict`) like: ```JSON { "name": "Katana", "description": "An optional description", "price": 299.00, "quantity": 10 } ``` ...as `description` is optional (with a default value of `None`), this JSON "`object`" would also be valid: ```JSON { "name": "Katana", "price": 299.00, "quantity": 10 } ``` ## Declare it as a parameter To add it to your *path operation*, declare it the same way you declared the path and query parameters: ```python hl_lines="13" {!./src/tutorial/body/code01.py!} ``` ... and declare its type as the model you created, `Item`. ## Results With just that Python type declaration, **Django Ninja** will: * Read the body of the request as JSON. * Convert the corresponding types (if needed). * Validate the data. * If the data is invalid, it will return a nice and meaningful error, indicating exactly where and what the incorrect data was. * Give you the received data in the parameter `item`. * Because you declared it in the function to be of type `Item`, you will also have all the editor support (completion, etc.) for all the attributes and their types. * Generate JSON Schema definitions for your models, and you can also use them anywhere else you like if it makes sense for your project. * Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentation UI's. ## Automatic docs The JSON Schemas of your models will be part of your OpenAPI generated schema, and will be shown in the interactive API docs: ![Openapi schema](../../img/body-schema-doc.png) ... and they will be also used in the API docs inside each *path operation* that needs them: ![Openapi schema](../../img/body-schema-doc2.png) ## Editor support In your editor, inside your function you will get type hints and completion everywhere (this wouldn't happen if you received a `dict` instead of a Schema object): ![Type hints](../../img/body-editor.gif) The previous screenshots were taken with Visual Studio Code. You would get the same editor support with PyCharm and most of the other Python editors. ## Request body + path parameters You can declare path parameters **and** body requests at the same time. **Django Ninja** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared with `Schema` should be **taken from the request body**. ```python hl_lines="11 12" {!./src/tutorial/body/code02.py!} ``` ## Request body + path + query parameters You can also declare **body**, **path** and **query** parameters, all at the same time. **Django Ninja** will recognize each of them and take the data from the correct place. ```python hl_lines="11 12" {!./src/tutorial/body/code03.py!} ``` The function parameters will be recognized as follows: * If the parameter is also declared in the **path**, it will be used as a path parameter. * If the parameter is of a **singular type** (like `int`, `float`, `str`, `bool`, etc.), it will be interpreted as a **query** parameter. * If the parameter is declared to be of the type of **Schema** (or Pydantic `BaseModel`), it will be interpreted as a request **body**. vitalik-django-ninja-0b67d47/docs/docs/guides/input/file-params.md000066400000000000000000000102411515660254400251000ustar00rootroot00000000000000# File uploads Handling files are no different from other parameters. ```python hl_lines="1 2 5" from ninja import NinjaAPI, File from ninja.files import UploadedFile @api.post("/upload") def upload(request, file: File[UploadedFile]): data = file.read() return {'name': file.name, 'len': len(data)} ``` `UploadedFile` is an alias to [Django's UploadFile](https://docs.djangoproject.com/en/stable/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile) and has all the methods and attributes to access the uploaded file: - read() - multiple_chunks(chunk_size=None) - chunks(chunk_size=None) - name - size - content_type - content_type_extra - charset - etc. ## Uploading array of files To **upload several files** at the same time, just declare a `List` of `UploadedFile`: ```python hl_lines="1 6" from typing import List from ninja import NinjaAPI, File from ninja.files import UploadedFile @api.post("/upload-many") def upload_many(request, files: File[List[UploadedFile]]): return [f.name for f in files] ``` ## Uploading files with extra fields Note: The HTTP protocol does not allow you to send files in `application/json` format by default (unless you encode it somehow to JSON on client side) To send files along with some extra attributes, you need to send bodies with `multipart/form-data` encoding. You can do it by simply marking fields with `Form`: ```python hl_lines="14" from ninja import NinjaAPI, Schema, UploadedFile, Form, File from datetime import date api = NinjaAPI() class UserDetails(Schema): first_name: str last_name: str birthdate: date @api.post('/users') def create_user(request, details: Form[UserDetails], file: File[UploadedFile]): return [details.dict(), file.name] ``` Note: in this case all fields should be send as form fields You can as well send payload in single field as JSON - just remove the Form mark from: ```python @api.post('/users') def create_user(request, details: UserDetails, file: File[UploadedFile]): return [details.dict(), file.name] ``` this will expect from the client side to send data as `multipart/form-data with 2 fields: - details: JSON as string - file: file ### List of files with extra info ```python @api.post('/users') def create_user(request, details: Form[UserDetails], files: File[list[UploadedFile]]): return [details.dict(), [f.name for f in files]] ``` ### Optional file input If you would like the file input to be optional, all that you have to do is to pass `None` to the `File` type, like so: ```python @api.post('/users') def create_user(request, details: Form[UserDetails], avatar: File[UploadedFile] = None): user = add_user_to_database(details) if avatar is not None: set_user_avatar(user) ``` ## Handling request.FILES in PUT/PATCH Requests **Problem** ```python @api.put("/upload") # !!!! def upload(request, file: File[UploadedFile]): ... ``` For some [historical reasons Django’s](https://groups.google.com/g/django-users/c/BeBKj_6qNsc) `request.FILES` is populated only for POST requests by default. When using HTTP PUT or PATCH methods with file uploads (e.g., multipart/form-data), request.FILES will not contain uploaded files. This is a known Django behavior, not specific to Django Ninja. As a result, views expecting files in PUT or PATCH requests may not behave correctly, since request.FILES will be empty. **Solution** Django Ninja provides a built-in middleware to automatically fix this behavior: `ninja.compatibility.files.fix_request_files_middleware` This middleware will manually parse multipart/form-data for PUT and PATCH requests and populate request.FILES, making file uploads work as expected across all HTTP methods. **Usage** To enable the middleware, add the following to your Django settings: ```python MIDDLEWARE = [ # ... your existing middleware ... "ninja.compatibility.files.fix_request_files_middleware", ] ``` **Auto-detection** When Django Ninja detects a PUT or PATCH etc methods with multipart/form-data and expected FILES - it will throw an error message suggesting you install the compatibility middleware: Note: This middleware does not interfere with normal POST behavior or any other methods. vitalik-django-ninja-0b67d47/docs/docs/guides/input/filtering.md000066400000000000000000000211401515660254400246630ustar00rootroot00000000000000# Filtering If you want to allow the user to filter your querysets by a number of different attributes, it makes sense to encapsulate your filters into a `FilterSchema` class. `FilterSchema` is a regular `Schema`, so it's using all the necessary features of Pydantic, but it also adds some bells and whistles that ease the translation of the user-facing filtering parameters into database queries. Start off with defining a subclass of `FilterSchema`: ```python hl_lines="6 7 8 9" from ninja import FilterSchema from typing import Optional from datetime import datetime class BookFilterSchema(FilterSchema): name: Optional[str] = None author: Optional[str] = None created_after: Optional[datetime] = None ``` Next, use this schema in conjunction with `Query` in your API handler: ```python hl_lines="2" @api.get("/books") def list_books(request, filters: BookFilterSchema = Query(...)): books = Book.objects.all() books = filters.filter(books) return books ``` Just like described in [defining query params using schema](./query-params.md#using-schema), Django Ninja converts the fields defined in `BookFilterSchema` into query parameters. You can use a shorthand one-liner `.filter()` to apply those filters to your queryset: ```python hl_lines="4" @api.get("/books") def list_books(request, filters: Query[BookFilterSchema]): books = Book.objects.all() books = filters.filter(books) return books ``` Under the hood, `FilterSchema` converts its fields into [Q expressions](https://docs.djangoproject.com/en/3.1/topics/db/queries/#complex-lookups-with-q-objects) which it then combines and uses to filter your queryset. Alternatively to using the `.filter` method, you can get the prepared `Q`-expression and perform the filtering yourself. That can be useful, when you have some additional queryset filtering on top of what you expose to the user through the API: ```python hl_lines="5 8" @api.get("/books") def list_books(request, filters: Query[BookFilterSchema]): # Never serve books from inactive publishers and authors q = Q(author__is_active=True) | Q(publisher__is_active=True) # But allow filtering the rest of the books q &= filters.get_filter_expression() return Book.objects.filter(q) ``` By default, the filters will behave the following way: * `None` values will be ignored and not filtered against; * Every non-`None` field will be converted into a `Q`-expression based on the `Field` definition of each field; * All `Q`-expressions will be merged into one using `AND` logical operator; * The resulting `Q`-expression is used to filter the queryset and return you a queryset with a `.filter` clause applied. ## Customizing Fields By default, `FilterSet` will use the field names to generate Q expressions: ```python class BookFilterSchema(FilterSchema): name: Optional[str] = None ``` The `name` field will be converted into `Q(name=...)` expression. When your database lookups are more complicated than that, you can annotate your fields with an instance of `FilterLookup` where you specify how you wish your field to be looked up for filtering: ```python hl_lines="5" from ninja import FilterSchema, FilterLookup from typing import Annotated class BookFilterSchema(FilterSchema): name: Annotated[Optional[str], FilterLookup("name__icontains")] = None ``` You can even specify multiple lookups as a list: ```python hl_lines="3 4 5" class BookFilterSchema(FilterSchema): search: Annotated[Optional[str], FilterLookup( ["name__icontains", "author__name__icontains", "publisher__name__icontains"] )] ``` By default, field-level expressions are combined using `"OR"` connector, so with the above setup, a query parameter `?search=foobar` will search for books that have "foobar" in either of their name, author or publisher. And to make generic fields, you can make the field name implicit by skipping it: ```python hl_lines="1 4" IContainsField = Annotated[Optional[str], FilterLookup('__icontains')] class BookFilterSchema(FilterSchema): name: IContainsField = None ``` ??? note "Deprecated syntax" In previous versions, database lookups were specified using `Field(q=...)` syntax: ```python from ninja import FilterSchema, Field class BookFilterSchema(FilterSchema): name: Optional[str] = Field(None, q="name__icontains") ``` This approach is still supported, but it is considered **deprecated** and **not recommended** for new code because: - Poor IDE support (IDEs don't recognize custom `Field` arguments) - Uses deprecated Pydantic features (`**extra`) - Less type-safe and harder to maintain The new `FilterLookup` annotation provides better developer experience with full IDE support and type safety. Prefer using `FilterLookup` for new projects. ## Combining expressions By default, * Field-level expressions are joined together using `OR` operator. * The fields themselves are joined together using `AND` operator. So, with the following `FilterSchema`... ```python class BookFilterSchema(FilterSchema): search: Annotated[ Optional[str], FilterLookup(["name__icontains", "author__name__icontains"])] = None popular: Optional[bool] = None ``` ...and the following query parameters from the user ``` http://localhost:8000/api/books?search=harry&popular=true ``` the `FilterSchema` instance will look for popular books that have `harry` in the book's _or_ author's name. You can customize this behavior using an `expression_connector` argument in field-level and class-level definition: ```python hl_lines="12" from ninja import FilterConfigDict, FilterLookup, FilterSchema class BookFilterSchema(FilterSchema): active: Annotated[ Optional[bool], FilterLookup( ["is_active", "publisher__is_active"], expression_connector="AND" )] = None name: Annotated[Optional[str], FilterLookup("name__icontains")] = None model_config = FilterConfigDict(expression_connector="OR") ``` An expression connector can take the values of `"OR"`, `"AND"` and `"XOR"`, but the latter is only [supported](https://docs.djangoproject.com/en/4.1/ref/models/querysets/#xor) in Django starting with 4.1. Now, a request with these query parameters ``` http://localhost:8000/api/books?name=harry&active=true ``` ...shall search for books that have `harry` in their name _or_ are active themselves _and_ are published by active publishers. ## Filtering by Nones You can make the `FilterSchema` treat `None` as a valid value that should be filtered against. This can be done on a field level with a `ignore_none` kwarg: ```python hl_lines="3" class BookFilterSchema(FilterSchema): name: Annotated[Optional[str], FilterLookup("name__icontains")] = None tag: Annotated[Optional[str], FilterLookup("tag", ignore_none=False)] = None ``` This way when no other value for `"tag"` is provided by the user, the filtering will always include a condition `tag=None`. You can also specify this setting for all fields at the same time in `model_config`: ```python hl_lines="5" class BookFilterSchema(FilterSchema): name: Annotated[Optional[str], FilterLookup("name__icontains")] = None tag: Optional[str] = None model_config = FilterConfigDict(ignore_none=False) ``` ## Custom expressions Sometimes you might want to have complex filtering scenarios that cannot be handled by individual Field annotations. For such cases you can implement your field filtering logic as a custom method. Simply define a method called `filter_` which takes a filter value and returns a Q expression: ```python hl_lines="5" class BookFilterSchema(FilterSchema): tag: Optional[str] = None popular: Optional[bool] = None def filter_popular(self, value: bool) -> Q: return Q(view_count__gt=1000) | Q(download_count__gt=100) if value else Q() ``` Such field methods take precedence over what is specified in the `Field()` definition of the corresponding fields. If that is not enough, you can implement your own custom filtering logic for the entire `FilterSet` class in a `custom_expression` method: ```python hl_lines="5" class BookFilterSchema(FilterSchema): name: Optional[str] = None popular: Optional[bool] = None def custom_expression(self) -> Q: q = Q() if self.name: q &= Q(name__icontains=self.name) if self.popular: q &= ( Q(view_count__gt=1000) | Q(downloads__gt=100) | Q(tag='popular') ) return q ``` The `custom_expression` method takes precedence over any other definitions described earlier, including `filter_` methods. vitalik-django-ninja-0b67d47/docs/docs/guides/input/form-params.md000066400000000000000000000034431515660254400251320ustar00rootroot00000000000000# Form data **Django Ninja** also allows you to parse and validate `request.POST` data (aka `application/x-www-form-urlencoded` or `multipart/form-data`). ## Form Data as params ```python hl_lines="1 4" from ninja import NinjaAPI, Form @api.post("/login") def login(request, username: Form[str], password: Form[str]): return {'username': username, 'password': '*****'} ``` Note the following: 1) You need to import the `Form` class from `ninja` ```python from ninja import Form ``` 2) Use `Form` as default value for your parameter: ```python username: Form[str] ``` ## Using a Schema In a similar manner to [Body](body.md#declare-it-as-a-parameter), you can use a Schema to organize your parameters. ```python hl_lines="12" {!./src/tutorial/form/code01.py!} ``` ## Request form + path + query parameters In a similar manner to [Body](body.md#request-body-path-query-parameters), you can use Form data in combination with other parameter sources. You can declare query **and** path **and** form field, **and** etc... parameters at the same time. **Django Ninja** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared with `Form(...)` should be **taken from the request form fields**, etc. ```python hl_lines="12" {!./src/tutorial/form/code02.py!} ``` ## Mapping Empty Form Field to Default Form fields that are optional, are often sent with an empty value. This value is interpreted as an empty string, and thus may fail validation for fields such as `int` or `bool`. This can be fixed, as described in the Pydantic docs, by using [Generic Classes as Types](https://pydantic-docs.helpmanual.io/usage/types/#generic-classes-as-types). ```python hl_lines="15 16 23-25" {!./src/tutorial/form/code03.py!} ``` vitalik-django-ninja-0b67d47/docs/docs/guides/input/operations.md000066400000000000000000000023611515660254400250670ustar00rootroot00000000000000# HTTP Methods ## Defining operations An `operation` can be one of the following [HTTP methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods): - GET - POST - PUT - DELETE - PATCH **Django Ninja** comes with a decorator for each operation: ```python hl_lines="1 5 9 13 17" @api.get("/path") def get_operation(request): ... @api.post("/path") def post_operation(request): ... @api.put("/path") def put_operation(request): ... @api.delete("/path") def delete_operation(request): ... @api.patch("/path") def patch_operation(request): ... ``` See the [operations parameters](../../reference/operations-parameters.md) reference docs for information on what you can pass to any of these decorators. ## Handling multiple methods If you need to handle multiple methods with a single function for a given path, you can use the `api_operation` decorator: ```python hl_lines="1" @api.api_operation(["POST", "PATCH"], "/path") def mixed_operation(request): ... ``` This feature can also be used to implement other HTTP methods that don't have corresponding **Django Ninja** methods, such as `HEAD` or `OPTIONS`. ```python hl_lines="1" @api.api_operation(["HEAD", "OPTIONS"], "/path") def mixed_operation(request): ... ``` vitalik-django-ninja-0b67d47/docs/docs/guides/input/path-params.md000066400000000000000000000100611515660254400251150ustar00rootroot00000000000000# Path parameters You can declare path "parameters" with the same syntax used by Python format-strings (which luckily also matches the OpenAPI path parameters): ```python hl_lines="1 2" {!./src/tutorial/path/code01.py!} ``` The value of the path parameter `item_id` will be passed to your function as the argument `item_id`. So, if you run this example and go to http://localhost:8000/api/items/foo, you will see this response: ```JSON {"item_id":"foo"} ``` ### Path parameters with types You can declare the type of path parameter in the function using standard Python type annotations: ```python hl_lines="2" {!./src/tutorial/path/code02.py!} ``` In this case,`item_id` is declared to be an **`int`**. This will give you editor and linter support for error checks, completion, etc. If you run this in your browser with http://localhost:8000/api/items/3, you will see this response: ```JSON {"item_id":3} ``` !!! tip Notice that the value your function received (and returned) is **3**, as a Python `int` - not a string `"3"`. So, with just that type declaration, **Django Ninja** gives you automatic request "parsing" and validation. ### Data validation On the other hand, if you go to the browser at http://localhost:8000/api/items/foo *(`"foo"` is not int)*, you will see an HTTP error like this: ```JSON hl_lines="8" { "detail": [ { "loc": [ "path", "item_id" ], "msg": "value is not a valid integer", "type": "type_error.integer" } ] } ``` ### Django Path Converters You can use [Django Path Converters](https://docs.djangoproject.com/en/stable/topics/http/urls/#path-converters) to help parse the path: ```python hl_lines="1" @api.get("/items/{int:item_id}") def read_item(request, item_id): return {"item_id": item_id} ``` In this case,`item_id` will be parsed as an **`int`**. If `item_id` is not a valid `int`, the url will not match. (e.g. if no other path matches, a *404 Not Found* will be returned) !!! tip Notice that, since **Django Ninja** uses a default type of `str` for unannotated parameters, the value the function above received (and returned) is `"3"`, as a Python `str` - not an integer **3**. To receive an `int`, simply declare `item_id` as an `int` type annotation in the function definition as normal: ```python hl_lines="2" @api.get("/items/{int:item_id}") def read_item(request, item_id:int): return {"item_id": item_id} ``` #### Path params with slashes Django's `path` converter allows you to handle path-like parameters: ```python hl_lines="1" @api.get('/dir/{path:value}') def someview(request, value: str): return value ``` you can query this operation with `/dir/some/path/with-slashes` and your `value` will be equal to `some/path/with-slashes` ### Multiple parameters You can pass as many variables as you want into `path`, just remember to have unique names and don't forget to use the same names in the function arguments. ```python @api.get("/events/{year}/{month}/{day}") def events(request, year: int, month: int, day: int): return {"date": [year, month, day]} ``` ### Using Schema You can also use Schema to encapsulate path parameters that depend on each other (and validate them as a group): ```python hl_lines="1 2 5 6 7 8 9 10 11 15" {!./src/tutorial/path/code010.py!} ``` !!! note Notice that here we used a `Path` source hint to let **Django Ninja** know that this schema will be applied to path parameters. ### Documentation Now, when you open your browser at http://localhost:8000/api/docs, you will see the automatic, interactive, API documentation. ![Django Ninja Swagger](../../img/tutorial-path-swagger.png) vitalik-django-ninja-0b67d47/docs/docs/guides/input/query-params.md000066400000000000000000000060101515660254400253250ustar00rootroot00000000000000# Query parameters When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters. ```python hl_lines="5" {!./src/tutorial/query/code01.py!} ``` To query this operation, you use a URL like: ``` http://localhost:8000/api/weapons?offset=0&limit=10 ``` By default, all GET parameters are strings, and when you annotate your function arguments with types, they are converted to that type and validated against it. The same benefits that apply to path parameters also apply to query parameters: - Editor support (obviously) - Data "parsing" - Data validation - Automatic documentation !!! Note if you do not annotate your arguments, they will be treated as `str` types ```python hl_lines="2" @api.get("/weapons") def list_weapons(request, limit, offset): # type(limit) == str # type(offset) == str ``` ### Defaults As query parameters are not a fixed part of a path, they are optional and can have default values: ```python hl_lines="2" @api.get("/weapons") def list_weapons(request, limit: int = 10, offset: int = 0): return weapons[offset : offset + limit] ``` In the example above we set default values of `offset=0` and `limit=10`. So, going to the URL: ``` http://localhost:8000/api/weapons ``` would be the same as going to: ``` http://localhost:8000/api/weapons?offset=0&limit=10 ``` If you go to, for example: ``` http://localhost:8000/api/weapons?offset=20 ``` the parameter values in your function will be: - `offset=20` (because you set it in the URL) - `limit=10` (because that was the default value) ### Required and optional parameters You can declare required or optional GET parameters in the same way as declaring Python function arguments: ```python hl_lines="5" {!./src/tutorial/query/code02.py!} ``` In this case, **Django Ninja** will always validate that you pass the `q` param in the GET, and the `offset` param is an optional integer. ### GET parameters type conversion Let's declare multiple type arguments: ```python hl_lines="5" {!./src/tutorial/query/code03.py!} ``` The `str` type is passed as is. For the `bool` type, all the following: ``` http://localhost:8000/api/example?b=1 http://localhost:8000/api/example?b=True http://localhost:8000/api/example?b=true http://localhost:8000/api/example?b=on http://localhost:8000/api/example?b=yes ``` or any other case variation (uppercase, first letter in uppercase, etc.), your function will see the parameter `b` with a `bool` value of `True`, otherwise as `False`. Date can be both date string and integer (unix timestamp):
http://localhost:8000/api/example?d=1577836800  # same as 2020-01-01
http://localhost:8000/api/example?d=2020-01-01
### Using Schema You can also use Schema to encapsulate GET parameters: ```python hl_lines="1 2 5 6 7 8" {!./src/tutorial/query/code010.py!} ``` For more complex filtering scenarios please refer to [filtering](./filtering.md). vitalik-django-ninja-0b67d47/docs/docs/guides/input/request-parsers.md000066400000000000000000000032761515660254400260570ustar00rootroot00000000000000# Request parsers In most cases, the default content type for REST API's is JSON, but in case you need to work with other content types (like YAML, XML, CSV) or use faster JSON parsers, **Django Ninja** provides a `parser` configuration. ```python api = NinjaAPI(parser=MyYamlParser()) ``` To create your own parser, you need to extend the `ninja.parser.Parser` class, and override the `parse_body` method. ## Example YAML Parser Let's create our custom YAML parser: ```python hl_lines="4 8 9" import yaml from typing import List from ninja import NinjaAPI from ninja.parser import Parser class MyYamlParser(Parser): def parse_body(self, request): return yaml.safe_load(request.body) api = NinjaAPI(parser=MyYamlParser()) class Payload(Schema): ints: List[int] string: str f: float @api.post('/yaml') def operation(request, payload: Payload): return payload.dict() ``` If you now send YAML like this as the request body: ```YAML ints: - 0 - 1 string: hello f: 3.14 ``` it will be correctly parsed, and you should have JSON output like this: ```JSON { "ints": [ 0, 1 ], "string": "hello", "f": 3.14 } ``` ## Example ORJSON Parser [orjson](https://github.com/ijl/orjson#orjson) is a fast, accurate JSON library for Python. It benchmarks as the fastest Python library for JSON and is more accurate than the standard `json` library or other third-party libraries. ``` pip install orjson ``` Parser code: ```python hl_lines="1 8 9" import orjson from ninja import NinjaAPI from ninja.parser import Parser class ORJSONParser(Parser): def parse_body(self, request): return orjson.loads(request.body) api = NinjaAPI(parser=ORJSONParser()) ``` vitalik-django-ninja-0b67d47/docs/docs/guides/response/000077500000000000000000000000001515660254400230575ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/guides/response/config-pydantic.md000066400000000000000000000036371515660254400264700ustar00rootroot00000000000000# Overriding Pydantic Config There are many customizations available for a **Django Ninja `Schema`**, via the schema's [Pydantic `model_config`](https://docs.pydantic.dev/latest/api/config/). !!! info Under the hood **Django Ninja** uses [Pydantic Models](https://pydantic-docs.helpmanual.io/usage/models/) with all their power and benefits. The alias `Schema` was chosen to avoid confusion in code when using Django models, as Pydantic's model class is called Model by default, and conflicts with Django's Model class. ## Example Camel Case mode One interesting config attribute is [`alias_generator`](https://docs.pydantic.dev/latest/api/config/?query=alias_generator#pydantic.config.ConfigDict.alias_generator). Using Pydantic's example in **Django Ninja** can look something like: ```python hl_lines="10" from pydantic import ConfigDict from ninja import Schema def to_camel(string: str) -> str: words = string.split('_') return words[0].lower() + ''.join(word.capitalize() for word in words[1:]) class CamelModelSchema(Schema): model_config = ConfigDict(alias_generator=to_camel) str_field_name: str float_field_name: float ``` Keep in mind that when you want modify output for field names (like camel case) - you need to set as well `populate_by_name` and `by_alias` ```python hl_lines="6 14" from pydantic import ConfigDict class UserSchema(ModelSchema): model_config = ConfigDict( alias_generator = to_camel populate_by_name = True, # !!!!!! <-------- ) class Meta: model = User fields = ["id", "email", "is_staff"] @api.get("/users", response=list[UserSchema], by_alias=True) # !!!!!! <-------- by_alias def get_users(request): return User.objects.all() ``` results: ```JSON [ { "id": 1, "email": "tim@apple.com", "isStaff": true }, { "id": 2, "email": "sarah@smith.com", "isStaff": false } ... ] ``` vitalik-django-ninja-0b67d47/docs/docs/guides/response/django-pydantic-create-schema.md000066400000000000000000000054741515660254400311650ustar00rootroot00000000000000# Using create_schema Under the hood, [`ModelSchema`](django-pydantic.md#modelschema) uses the `create_schema` function. This is a more advanced (and less safe) method - please use it carefully. ## `create_schema` **Django Ninja** comes with a helper function `create_schema`: ```python def create_schema( model, # django model name = "", # name for the generated class, if empty model names is used depth = 0, # if > 0 schema will also be created for the nested ForeignKeys and Many2Many (with the provided depth of lookup) fields: list[str] = None, # if passed - ONLY these fields will added to schema exclude: list[str] = None, # if passed - these fields will be excluded from schema optional_fields: list[str] | str = None, # if passed - these fields will not be required on schema (use '__all__' to mark ALL fields required) custom_fields: list[tuple(str, Any, Any)] = None, # if passed - this will override default field types (or add new fields) ) ``` Take this example: ```python hl_lines="2 4" from django.contrib.auth.models import User from ninja.orm import create_schema UserSchema = create_schema(User) # Will create schema like this: # # class UserSchema(Schema): # id: int # username: str # first_name: str # last_name: str # password: str # last_login: datetime # is_superuser: bool # email: str # ... and the rest ``` !!! Warning By default `create_schema` builds a schema with ALL model fields. This can lead to accidental unwanted data exposure (like hashed password, in the above example).
**Always** use `fields` or `exclude` arguments to explicitly define list of attributes. ### Using `fields` ```python hl_lines="1" UserSchema = create_schema(User, fields=['id', 'username']) # Will create schema like this: # # class UserSchema(Schema): # id: int # username: str ``` ### Using `exclude` ```python hl_lines="1 2" UserSchema = create_schema(User, exclude=[ 'password', 'last_login', 'is_superuser', 'is_staff', 'groups', 'user_permissions'] ) # Will create schema without excluded fields: # # class UserSchema(Schema): # id: int # username: str # first_name: str # last_name: str # email: str # is_active: bool # date_joined: datetime ``` ### Using `depth` The `depth` argument allows you to introspect the Django model into the Related fields(ForeignKey, OneToOne, ManyToMany). ```python hl_lines="1 7" UserSchema = create_schema(User, depth=1, fields=['username', 'groups']) # Will create the following schema: # # class UserSchema(Schema): # username: str # groups: List[Group] ``` Note here that groups became a `List[Group]` - many2many field introspected 1 level deeper and created schema as well for group: ```python class Group(Schema): id: int name: str permissions: List[int] ``` vitalik-django-ninja-0b67d47/docs/docs/guides/response/django-pydantic.md000066400000000000000000000114021515660254400264520ustar00rootroot00000000000000# Schemas from Django models Schemas are very useful to define your validation rules and responses, but sometimes you need to reflect your database models into schemas and keep changes in sync. ## ModelSchema `ModelSchema` is a special base class that can automatically generate schemas from your models. All you need is to set `model` and `fields` attributes on your schema `Meta`: ```python hl_lines="2 5 6 7" from django.contrib.auth.models import User from ninja import ModelSchema class UserSchema(ModelSchema): class Meta: model = User fields = ['id', 'username', 'first_name', 'last_name'] # Will create schema like this: # # class UserSchema(Schema): # id: int # username: str # first_name: str # last_name: str ``` !!! note You can also specify the model using a [Django Absolute Lazy relationship](https://docs.djangoproject.com/en/stable/ref/models/fields/#absolute). In the above example, it would be `model = 'auth.User'`. ### Using ALL model fields To use all fields from a model - you can pass `__all__` to `fields`: ```python hl_lines="4" class UserSchema(ModelSchema): class Meta: model = User fields = "__all__" ``` !!! Warning Using __all__ is not recommended.
This can lead to accidental unwanted data exposure (like hashed password, in the above example).
General advice - use `fields` to explicitly define list of fields that you want to be visible in API. ### Excluding model fields To use all fields **except** a few, you can use `exclude` configuration: ```python hl_lines="4" class UserSchema(ModelSchema): class Meta: model = User exclude = ['password', 'last_login', 'user_permissions'] # Will create schema like this: # # class UserSchema(Schema): # id: int # username: str # first_name: str # last_name: str # email: str # is_superuser: bool # ... and the rest ``` ### Overriding fields To change default annotation for some field, or to add a new field, just use annotated attributes as usual. ```python hl_lines="1 2 3 4 8" class GroupSchema(ModelSchema): class Meta: model = Group fields = ['id', 'name'] class UserSchema(ModelSchema): groups: List[GroupSchema] = [] class Meta: model = User fields = ['id', 'username', 'first_name', 'last_name'] ``` ### Making fields optional Pretty often for PATCH API operations you need to make all fields of your schema optional. To do that, you can use config fields_optional ```python hl_lines="5" class PatchGroupSchema(ModelSchema): class Meta: model = Group fields = ['id', 'name', 'description'] # Note: all these fields are required on model level fields_optional = '__all__' ``` Also, you can define a subset of optional fields instead of `__all__`: ```python fields_optional = ['description'] ``` When you process input data, you need to tell Pydantic to avoid setting undefined fields to `None`: ```python @api.patch("/patch/{pk}") def patch(request, pk: int, payload: PatchGroupSchema): # Notice that we set exclude_unset=True updated_fields = payload.dict(exclude_unset=True) obj = MyModel.objects.get(pk=pk) for attr, value in updated_fields.items(): setattr(obj, attr, value) obj.save() ``` ### Custom fields types For each Django field it encounters, `ModelSchema` uses the default `Field.get_internal_type` method to find the correct representation in Pydantic schema (python type). This process works fine for the built-in field types, but there are cases where the user wants to create or use a custom field, with its own mapping to python type. In this case you should use `register_field` method to tell django-ninja which type should this django field represent: ```python hl_lines="4 7 8 9" # models.py class MyModel(models.Model): embedding = pgvector.VectorField() # schemas.py from ninja.orm import register_field register_field('VectorField', list[float]) ``` #### PatchDict Another way to work with patch request data is a `PatchDict` container which allows you to make a schema with all optional fields and get a dict with **only** fields that was provide ```Python hl_lines="1 11" from ninja import PatchDict class GroupSchema(Schema): # You do not have to make fields optional it will be converted by PatchDict name: str description: str due_date: date @api.patch("/patch/{pk}") def modify_data(request, pk: int, payload: PatchDict[GroupSchema]): obj = MyModel.objects.get(pk=pk) for attr, value in payload.items(): setattr(obj, attr, value) obj.save() ``` in this example the `payload` argument will be of type `dict` and only contain fields that were passed in the request and validated using `GroupSchema` vitalik-django-ninja-0b67d47/docs/docs/guides/response/index.md000066400000000000000000000276341515660254400245240ustar00rootroot00000000000000# Response Schema **Django Ninja** allows you to define the schema of your responses both for validation and documentation purposes. Imagine you need to create an API operation that creates a user. The **input** parameter would be **username+password**, but **output** of this operation should be **id+username** (**without** the password). Let's create the input schema: ```python hl_lines="3 5" from ninja import Schema class UserIn(Schema): username: str password: str @api.post("/users/") def create_user(request, data: UserIn): user = User(username=data.username) # User is django auth.User user.set_password(data.password) user.save() # ... return ? ``` Now let's define the output schema, and pass it as a `response` argument to the `@api.post` decorator: ```python hl_lines="8 9 10 13 18" from ninja import Schema class UserIn(Schema): username: str password: str class UserOut(Schema): id: int username: str @api.post("/users/", response=UserOut) def create_user(request, data: UserIn): user = User(username=data.username) user.set_password(data.password) user.save() return user ``` **Django Ninja** will use this `response` schema to: - convert the output data to declared schema - validate the data - add an OpenAPI schema definition - it will be used by the automatic documentation systems - and, most importantly, it **will limit the output data** only to the fields only defined in the schema. ## Nested objects There is also often a need to return responses with some nested/child objects. Imagine we have a `Task` Django model with a `User` ForeignKey: ```python hl_lines="6" from django.db import models class Task(models.Model): title = models.CharField(max_length=200) is_completed = models.BooleanField(default=False) owner = models.ForeignKey("auth.User", null=True, blank=True) ``` Now let's output all tasks, and for each task, output some fields about the user. ```python hl_lines="13 16" from typing import List from ninja import Schema class UserSchema(Schema): id: int first_name: str last_name: str class TaskSchema(Schema): id: int title: str is_completed: bool owner: UserSchema = None # ! None - to mark it as optional @api.get("/tasks", response=List[TaskSchema]) def tasks(request): queryset = Task.objects.select_related("owner") return list(queryset) ``` If you execute this operation, you should get a response like this: ```JSON hl_lines="6 7 8 9 16" [ { "id": 1, "title": "Task 1", "is_completed": false, "owner": { "id": 1, "first_name": "John", "last_name": "Doe", } }, { "id": 2, "title": "Task 2", "is_completed": false, "owner": null }, ] ``` ## Aliases Instead of a nested response, you may want to just flatten the response output. The Ninja `Schema` object extends Pydantic's `Field(..., alias="")` format to work with dotted responses. Using the models from above, let's make a schema that just includes the task owner's first name inline, and also uses `completed` rather than `is_completed`: ```python hl_lines="1 7-9" from ninja import Field, Schema class TaskSchema(Schema): id: int title: str # The first Field param is the default, use ... for required fields. completed: bool = Field(..., alias="is_completed") owner_first_name: str = Field(None, alias="owner.first_name") ``` Aliases also support django template syntax variables access: ```python hl_lines="2" class TaskSchema(Schema): last_message: str = Field(None, alias="message_set.0.text") ``` ```python hl_lines="3" class TaskSchema(Schema): type: str = Field(None) type_display: str = Field(None, alias="get_type_display") # callable will be executed ``` ## Resolvers You can also create calculated fields via resolve methods based on the field name. The method must accept a single argument, which will be the object the schema is resolving against. When creating a resolver as a standard method, `self` gives you access to other validated and formatted attributes in the schema. ```python hl_lines="5 7-11" class TaskSchema(Schema): id: int title: str is_completed: bool owner: Optional[str] = None lower_title: str @staticmethod def resolve_owner(obj): if not obj.owner: return return f"{obj.owner.first_name} {obj.owner.last_name}" def resolve_lower_title(self, obj): return self.title.lower() ``` ### Accessing extra context Pydantic v2 allows you to process an extra context that is passed to the serializer. In the following example you can have resolver that gets request object from passed `context` argument: ```python hl_lines="6" class Data(Schema): a: int path: str = "" @staticmethod def resolve_path(obj, context): request = context["request"] return request.path ``` if you use this schema for incoming requests - the `request` object will be automatically passed to context. You can as well pass your own context: ```python data = Data.model_validate({'some': 1}, context={'request': MyRequest()}) ``` ## Returning querysets In the previous example we specifically converted a queryset into a list (and executed the SQL query during evaluation). You can avoid that and return a queryset as a result, and it will be automatically evaluated to List: ```python hl_lines="3" @api.get("/tasks", response=List[TaskSchema]) def tasks(request): return Task.objects.all() ``` !!! warning If your operation is async, this example will not work because the ORM query needs to be called safely. ```python hl_lines="2" @api.get("/tasks", response=List[TaskSchema]) async def tasks(request): return Task.objects.all() ``` See the [async support](../async-support.md#using-orm) guide for more information. ## FileField and ImageField **Django Ninja** by default converts files and images (declared with `FileField` or `ImageField`) to `string` URL's. An example: ```python hl_lines="3" class Picture(models.Model): title = models.CharField(max_length=100) image = models.ImageField(upload_to='images') ``` If you need to output to response image field, declare a schema for it as follows: ```python hl_lines="3" class PictureSchema(Schema): title: str image: str ``` Once you output this to a response, the URL will be automatically generated for each object: ```JSON { "title": "Zebra", "image": "/static/images/zebra.jpg" } ``` ## Multiple Response Schemas Sometimes you need to define more than response schemas. In case of authentication, for example, you can return: - **200** successful -> token - **401** -> Unauthorized - **402** -> Payment required - **403** -> Forbidden - etc.. In fact, the [OpenAPI specification](https://swagger.io/docs/specification/describing-responses/) allows you to pass multiple response schemas. You can pass to a `response` argument a dictionary where: - key is a response code - value is a schema for that code Also, when you return the result - you have to also pass a status code to tell **Django Ninja** which schema should be used for validation and serialization. An example: ```python hl_lines="1 9 12 14 16" from ninja import Status class Token(Schema): token: str expires: date class Message(Schema): message: str @api.post('/login', response={200: Token, 401: Message, 402: Message}) def login(request, payload: Auth): if auth_not_valid: return Status(401, {'message': 'Unauthorized'}) if negative_balance: return Status(402, {'message': 'Insufficient balance amount. Please proceed to a payment page.'}) return Status(200, {'token': xxx, ...}) ``` !!! warning "Deprecated: tuple syntax" Returning `(status_code, body)` tuples is deprecated and will be removed in a future version. Use `Status(status_code, body)` instead. ## Multiple response codes In the previous example you saw that we basically repeated the `Message` schema twice: ``` ...401: Message, 402: Message} ``` To avoid this duplication you can use multiple response codes for a schema: ```python hl_lines="2 3 6 9 11" ... from ninja import Status from ninja.responses import codes_4xx @api.post('/login', response={200: Token, codes_4xx: Message}) def login(request, payload: Auth): if auth_not_valid: return Status(401, {'message': 'Unauthorized'}) if negative_balance: return Status(402, {'message': 'Insufficient balance amount. Please proceed to a payment page.'}) return Status(200, {'token': xxx, ...}) ``` **Django Ninja** comes with the following HTTP codes: ```python from ninja.responses import codes_1xx from ninja.responses import codes_2xx from ninja.responses import codes_3xx from ninja.responses import codes_4xx from ninja.responses import codes_5xx ``` You can also create your own range using a `frozenset`: ```python my_codes = frozenset({416, 418, 425, 429, 451}) @api.post('/login', response={200: Token, my_codes: Message}) def login(request, payload: Auth): ... ``` ## Empty responses Some responses, such as [204 No Content](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204), have no body. To indicate the response body is empty mark `response` argument with `None` instead of Schema: ```python hl_lines="1 3" @api.post("/no_content", response={204: None}) def no_content(request): return Status(204, None) ``` ## Error responses Check [Handling errors](../errors.md) for more information. ## Self-referencing schemes Sometimes you need to create a schema that has reference to itself, or tree-structure objects. To do that you need: - set a type of your schema in quotes - use `model_rebuild` method to apply self referencing types ```python hl_lines="3 6" class Organization(Schema): title: str part_of: 'Organization' = None #!! note the type in quotes here !! Organization.model_rebuild() # !!! this is important @api.get('/organizations', response=List[Organization]) def list_organizations(request): ... ``` ## Self-referencing schemes from `create_schema()` To be able to use the method `model_rebuild()` from a schema generated via `create_schema()`, the "name" of the class needs to be in our namespace. In this case it is very important to pass the `name` parameter to `create_schema()` ```python hl_lines="3" UserSchema = create_schema( User, name='UserSchema', # !!! this is important for model_rebuild() fields=['id', 'username'] custom_fields=[ ('manager', 'UserSchema', None), ] ) UserSchema.model_rebuild() ``` ## Serializing Outside of Views Serialization of your objects can be done directly in code through the use of the `.from_orm()` method on the schema object. Consider the following model: ```python class Person(models.Model): name = models.CharField(max_length=50) ``` Which can be accessed using this schema: ```python class PersonSchema(Schema): name: str ``` Direct serialization can be performed using the `.from_orm()` method on the schema. Once you have an instance of the schema object, the `.dict()` and `.json()` methods allow you to get at both dictionary output and string JSON versions. ```python >>> person = Person.objects.get(id=1) >>> data = PersonSchema.from_orm(person) >>> data PersonSchema(id=1, name='Mr. Smith') >>> data.dict() {'id':1, 'name':'Mr. Smith'} >>> data.json() '{"id":1, "name":"Mr. Smith"}' ``` Multiple Items: or a queryset (or list) ```python >>> persons = Person.objects.all() >>> data = [PersonSchema.from_orm(i).dict() for i in persons] [{'id':1, 'name':'Mr. Smith'},{'id': 2, 'name': 'Mrs. Smith'}...] ``` ## Django HTTP responses It is also possible to return regular django http responses: ```python from django.http import HttpResponse from django.shortcuts import redirect @api.get("/http") def result_django(request): return HttpResponse('some data') # !!!! @api.get("/something") def some_redirect(request): return redirect("/some-path") # !!!! ``` vitalik-django-ninja-0b67d47/docs/docs/guides/response/pagination.md000066400000000000000000000211561515660254400255370ustar00rootroot00000000000000# Pagination **Django Ninja** comes with a pagination support. This allows you to split large result sets into individual pages. To apply pagination to a function - just apply `paginate` decorator: ```python hl_lines="1 4" from ninja.pagination import paginate @api.get('/users', response=List[UserSchema]) @paginate def list_users(request): return User.objects.all() ``` That's it! Now you can query users with `limit` and `offset` GET parameters ``` /api/users?limit=10&offset=0 ``` by default limit is set to `100` (you can change it in your settings.py using `NINJA_PAGINATION_PER_PAGE`) ## Built in Pagination Classes ### LimitOffsetPagination (default) This is the default pagination class (You can change it in your settings.py using `NINJA_PAGINATION_CLASS` path to a class) ```python hl_lines="1 4" from ninja.pagination import paginate, LimitOffsetPagination @api.get('/users', response=List[UserSchema]) @paginate(LimitOffsetPagination) def list_users(request): return User.objects.all() ``` Example query: ``` /api/users?limit=10&offset=0 ``` this class has two input parameters: - `limit` - defines a number of queryset on the page (default = 100, change in NINJA_PAGINATION_PER_PAGE) - `offset` - set's the page window offset (default: 0, indexing starts with 0) ### PageNumberPagination ```python hl_lines="1 4" from ninja.pagination import paginate, PageNumberPagination @api.get('/users', response=List[UserSchema]) @paginate(PageNumberPagination) def list_users(request): return User.objects.all() ``` Example query: ``` /api/users?page=2 ``` this class has one parameter `page` and outputs 100 queryset per page by default (can be changed with settings.py) Page numbering start with 1 you can also set custom page_size value individually per view: ```python hl_lines="2" @api.get("/users") @paginate(PageNumberPagination, page_size=50) def list_users(... ``` In addition to the `page` parameter, you can also use the `page_size` parameter to dynamically adjust the number of records displayed per page: Example query: ``` /api/users?page=2&page_size=20 ``` This allows you to temporarily override the page size setting in your request. The request will use the specified `page_size` value if provided. Otherwise, it will use either the value specified in the decorator or the value from `PAGINATION_MAX_PER_PAGE_SIZE` in settings.py if no decorator value is set. ### CursorPagination Cursor-based pagination provides stable pagination for datasets that may change frequently. Cursor pagination uses base64 encoded tokens to mark positions in the dataset, ensuring consistent results even when items are added or removed. ```python hl_lines="1 4" from ninja.pagination import paginate, CursorPagination @api.get('/events', response=List[EventSchema]) @paginate(CursorPagination) def list_events(request): return Event.objects.all() ``` Example query: ``` /api/events?cursor=eyJwIjoiMjAyNC0wMS0wMSIsInIiOmZhbHNlLCJvIjowfQ== ``` this class has two input parameters: - `cursor` - base64 token representing the current position (optional, starts from beginning if not provided) - `page_size` - number of items per page (optional) You can specify the `page_size` value to temporarily override in the request: ``` /api/events?cursor=eyJwIjoiMjAyNC0wMS0wMSIsInIiOmZhbHNlLCJvIjowfQ==&page_size=5 ``` This class has a few parameters, which determine how the cursor position is ascertained and the parameter encoded: - `ordering` - tuple of field names to order the queryset. Use `-` prefix for descending order. The first one of which will be used to encode the position. The ordering field should be unique if possible. A string representation of this field will be used to point to the current position of the cursor. Timestamps work well if each item in the collection is created independently. The paginator can handle some non-uniqueness by adding an offset. Defaults to `("-pk",)`, change in `NINJA_PAGINATION_DEFAULT_ORDERING` - `page_size` - default page size for endpoint. Defaults to `100`, change in `NINJA_PAGINATION_PER_PAGE` - `max_page_size` - maximum allowed page size for endpoint. Defaults to `100`, change in `NINJA_PAGINATION_MAX_PER_PAGE_SIZE` Finally, there is a `NINJA_PAGINATION_MAX_OFFSET` setting to limit malicious cursor requests. It defaults to `100`. The class parameters can be set globally via settings as well as per view: ```python hl_lines="2" @api.get("/events") @paginate(CursorPagination, ordering=("start_date", "end_date"), page_size=20, max_page_size=100) def list_events(request): return Event.objects.all() ``` The response includes navigation links and results: ```json { "next": "http://api.example.com/events?cursor=eyJwIjoiMjAyNC0wMS0wMiIsInIiOmZhbHNlLCJvIjowfQ==", "previous": "http://api.example.com/events?cursor=eyJwIjoiMjAyNC0wMS0wMSIsInIiOnRydWUsIm8iOjB9", "results": [ { "id": 1, "title": "Event 1", "start_date": "2024-01-01" }, { "id": 2, "title": "Event 2", "start_date": "2024-01-02" } ] } ``` ## Accessing paginator parameters in view function If you need access to `Input` parameters used for pagination in your view function - use `pass_parameter` argument In that case input data will be available in `**kwargs`: ```python hl_lines="2 4" @api.get("/someview") @paginate(pass_parameter="pagination_info") def someview(request, **kwargs): page = kwargs["pagination_info"].page return ... ``` ## Creating Custom Pagination Class To create a custom pagination class you should subclass `ninja.pagination.PaginationBase` and override the `Input` and `Output` schema classes and `paginate_queryset(self, queryset, request, **params)` method: - The `Input` schema is a Schema class that describes parameters that should be passed to your paginator (f.e. page-number or limit/offset values). - The `Output` schema describes schema for page output (f.e. count/next-page/items/etc). - The `paginate_queryset` method is passed the initial queryset and should return an iterable object that contains only the data in the requested page. This method accepts the following arguments: - `queryset`: a queryset (or iterable) returned by the api function - `pagination` - the paginator.Input parameters (parsed and validated) - `**params`: kwargs that will contain all the arguments that decorated function received Example: ```python hl_lines="7 11 16 26" from ninja.pagination import paginate, PaginationBase from ninja import Schema class CustomPagination(PaginationBase): # only `skip` param, defaults to 5 per page class Input(Schema): skip: int class Output(Schema): items: List[Any] # `items` is a default attribute total: int per_page: int def paginate_queryset(self, queryset, pagination: Input, **params): skip = pagination.skip return { 'items': queryset[skip : skip + 5], 'total': queryset.count(), 'per_page': 5, } @api.get('/users', response=List[UserSchema]) @paginate(CustomPagination) def list_users(request): return User.objects.all() ``` Tip: You can access request object from params: ```python def paginate_queryset(self, queryset, pagination: Input, **params): request = params["request"] ``` #### Async Pagination Standard **Django Ninja** pagination classes support async. If you wish to handle async requests with a custom pagination class, you should subclass `ninja.pagination.AsyncPaginationBase` and override the `apaginate_queryset(self, queryset, request, **params)` method. ### Output attribute By default page items are placed to `'items'` attribute. To override this behaviour use `items_attribute`: ```python hl_lines="4 8" class CustomPagination(PaginationBase): ... class Output(Schema): results: List[Any] total: int per_page: int items_attribute: str = "results" ``` ## Apply pagination to multiple operations at once There is often a case when you need to add pagination to all views that returns querysets or list You can use a builtin router class (`RouterPaginated`) that automatically injects pagination to all operations that defined `response=List[SomeSchema]`: ```python hl_lines="1 3 6 10" from ninja.pagination import RouterPaginated router = RouterPaginated() @router.get("/items", response=List[MySchema]) def items(request): return MyModel.objects.all() @router.get("/other-items", response=List[OtherSchema]) def other_items(request): return OtherModel.objects.all() ``` In this example both operations will have pagination enabled to apply pagination to main `api` instance use `default_router` argument: ```python api = NinjaAPI(default_router=RouterPaginated()) @api.get(... ``` vitalik-django-ninja-0b67d47/docs/docs/guides/response/response-renderers.md000066400000000000000000000062551515660254400272360ustar00rootroot00000000000000# Response renderers The most common response type for a REST API is usually JSON. **Django Ninja** also has support for defining your own custom renderers, which gives you the flexibility to design your own media types. ## Create a renderer To create your own renderer, you need to inherit `ninja.renderers.BaseRenderer` and override the `render` method. Then you can pass an instance of your class to `NinjaAPI` as the `renderer` argument: ```python hl_lines="5 8 9" from ninja import NinjaAPI from ninja.renderers import BaseRenderer class MyRenderer(BaseRenderer): media_type = "text/plain" def render(self, request, data, *, response_status): return ... # your serialization here api = NinjaAPI(renderer=MyRenderer()) ``` The `render` method takes the following arguments: - request -> HttpRequest object - data -> object that needs to be serialized - response_status as an `int` -> the HTTP status code that will be returned to the client You need also define the `media_type` attribute on the class to set the content-type header for the response. ## ORJSON renderer example: [orjson](https://github.com/ijl/orjson#orjson) is a fast, accurate JSON library for Python. It benchmarks as the fastest Python library for JSON and is more accurate than the standard `json` library or other third-party libraries. It also serializes dataclass, datetime, numpy, and UUID instances natively. Here's an example renderer class that uses `orjson`: ```python hl_lines="9 10" import orjson from ninja import NinjaAPI from ninja.renderers import BaseRenderer class ORJSONRenderer(BaseRenderer): media_type = "application/json" def render(self, request, data, *, response_status): return orjson.dumps(data) api = NinjaAPI(renderer=ORJSONRenderer()) ``` ## XML renderer example: This is how you create a renderer that outputs all responses as XML: ```python hl_lines="8 11" from io import StringIO from django.utils.encoding import force_str from django.utils.xmlutils import SimplerXMLGenerator from ninja import NinjaAPI from ninja.renderers import BaseRenderer class XMLRenderer(BaseRenderer): media_type = "text/xml" def render(self, request, data, *, response_status): stream = StringIO() xml = SimplerXMLGenerator(stream, "utf-8") xml.startDocument() xml.startElement("data", {}) self._to_xml(xml, data) xml.endElement("data") xml.endDocument() return stream.getvalue() def _to_xml(self, xml, data): if isinstance(data, (list, tuple)): for item in data: xml.startElement("item", {}) self._to_xml(xml, item) xml.endElement("item") elif isinstance(data, dict): for key, value in data.items(): xml.startElement(key, {}) self._to_xml(xml, value) xml.endElement(key) elif data is None: # Don't output any value pass else: xml.characters(force_str(data)) api = NinjaAPI(renderer=XMLRenderer()) ``` *(Copyright note: this code is basically copied from [DRF-xml](https://jpadilla.github.io/django-rest-framework-xml/))* vitalik-django-ninja-0b67d47/docs/docs/guides/response/temporal_response.md000066400000000000000000000026341515660254400271470ustar00rootroot00000000000000# Altering the Response Sometimes you'll want to change the response just before it gets served, for example, to add a header or alter a cookie. To do this, simply declare a function parameter with a type of `HttpResponse`: ```python from django.http import HttpRequest, HttpResponse @api.get("/cookie/") def feed_cookiemonster(request: HttpRequest, response: HttpResponse): # Set a cookie. response.set_cookie("cookie", "delicious") # Set a header. response["X-Cookiemonster"] = "blue" return {"cookiemonster_happy": True} ``` ## Temporal response object This response object is used for the base of all responses built by Django Ninja, including error responses. This object is *not* used if a Django `HttpResponse` object is returned directly by an operation. Obviously this response object won't contain the content yet, but it does have the `content_type` set (but you probably don't want to be changing it). The `status_code` will get overridden depending on the return value (200 by default, or the status code if a two-part tuple is returned). ## Changing the base response object You can alter this temporal response object by overriding the `NinjaAPI.create_temporal_response` method. ```python def create_temporal_response(self, request: HttpRequest) -> HttpResponse: response = super().create_temporal_response(request) # Do your magic here... return response ```vitalik-django-ninja-0b67d47/docs/docs/guides/routers.md000066400000000000000000000127271515660254400232570ustar00rootroot00000000000000# Routers Real world applications can almost never fit all logic into a single file. **Django Ninja** comes with an easy way to split your API into multiple modules using Routers. Let's say you have a Django project with a structure like this: ``` ├── myproject │ └── settings.py ├── events/ │ ├── __init__.py │ └── models.py ├── news/ │ ├── __init__.py │ └── models.py ├── blogs/ │ ├── __init__.py │ └── models.py └── manage.py ``` To add API's to each of the Django applications, create an `api.py` module in each app: ``` hl_lines="5 9 13" ├── myproject │ └── settings.py ├── events/ │ ├── __init__.py │ ├── api.py │ └── models.py ├── news/ │ ├── __init__.py │ ├── api.py │ └── models.py ├── blogs/ │ ├── __init__.py │ ├── api.py │ └── models.py └── manage.py ``` Now let's add a few operations to `events/api.py`. The trick is that instead of using the `NinjaAPI` class, you use the **Router** class: ```python hl_lines="1 4 6 13" from ninja import Router from .models import Event router = Router() @router.get('/') def list_events(request): return [ {"id": e.id, "title": e.title} for e in Event.objects.all() ] @router.get('/{event_id}') def event_details(request, event_id: int): event = Event.objects.get(id=event_id) return {"title": event.title, "details": event.details} ``` Then do the same for the `news` app with `news/api.py`: ```python hl_lines="1 4" from ninja import Router from .models import News router = Router() @router.get('/') def list_news(request): ... @router.get('/{news_id}') def news_details(request, news_id: int): ... ``` and then also `blogs/api.py`. Finally, let's group them together. In your top level project folder (next to `urls.py`), create another `api.py` file with the main `NinjaAPI` instance: ``` hl_lines="2" ├── myproject │ ├── api.py │ └── settings.py ├── events/ │ ... ├── news/ │ ... ├── blogs/ │ ... ``` It should look like this: ```python from ninja import NinjaAPI api = NinjaAPI() ``` Now we import all the routers from the various apps, and include them into the main API instance: ```python hl_lines="2 6 7 8" from ninja import NinjaAPI from events.api import router as events_router api = NinjaAPI() api.add_router("/events/", events_router) # You can add a router as an object api.add_router("/news/", "news.api.router") # or by Python path api.add_router("/blogs/", "blogs.api.router") ``` Now, include `api` to your urls as usual and open your browser at `/api/docs`, and you should see all your routers combined into a single API: ![Swagger UI Simple Routers](../img/simple-routers-swagger.png) ## Router authentication Use `auth` argument to apply authenticator to all operations declared by router: ```python api.add_router("/events/", events_router, auth=BasicAuth()) ``` or using router constructor ```python router = Router(auth=BasicAuth()) ``` ## Router tags You can use `tags` argument to apply tags to all operations declared by router: ```python api.add_router("/events/", events_router, tags=["events"]) ``` or using router constructor ```python router = Router(tags=["events"]) ``` ## Nested routers There are also times when you need to split your logic up even more. **Django Ninja** makes it possible to include a router into another router as many times as you like, and finally include the top level router into the main `api` instance. Basically, what that means is that you have `add_router` both on the `api` instance and on the `router` instance: ```python hl_lines="7 8 9 32 33 34" from django.contrib import admin from django.urls import path from ninja import NinjaAPI, Router api = NinjaAPI() first_router = Router() second_router = Router() third_router = Router() @api.get("/add") def add(request, a: int, b: int): return {"result": a + b} @first_router.get("/add") def add(request, a: int, b: int): return {"result": a + b} @second_router.get("/add") def add(request, a: int, b: int): return {"result": a + b} @third_router.get("/add") def add(request, a: int, b: int): return {"result": a + b} second_router.add_router("l3", third_router) first_router.add_router("l2", second_router) api.add_router("l1", first_router) urlpatterns = [ path("admin/", admin.site.urls), path("api/", api.urls), ] ``` Now you have the following endpoints: ``` /api/add /api/l1/add /api/l1/l2/add /api/l1/l2/l3/add ``` Great! Now go have a look at the automatically generated docs: ![Swagger UI Nested Routers](../img/nested-routers-swagger.png) ### Nested url parameters You can also use url parameters in nested routers by adding `= Path(...)` to the function parameters: ```python hl_lines="13 16" from django.contrib import admin from django.urls import path from ninja import NinjaAPI, Path, Router api = NinjaAPI() router = Router() @api.get("/add/{a}/{b}") def add(request, a: int, b: int): return {"result": a + b} @router.get("/multiply/{c}") def multiply(request, c: int, a: int = Path(...), b: int = Path(...)): return {"result": (a + b) * c} api.add_router("add/{a}/{b}", router) urlpatterns = [ path("admin/", admin.site.urls), path("api/", api.urls), ] ``` This will generate the following endpoints: ``` /api/add/{a}/{b} /api/add/{a}/{b}/multiply/{c} ```vitalik-django-ninja-0b67d47/docs/docs/guides/testing.md000066400000000000000000000051431515660254400232230ustar00rootroot00000000000000# Testing **Django Ninja** is fully compatible with standard [django test client](https://docs.djangoproject.com/en/dev/topics/testing/tools/) , but also provides a test client to make it easy to test just APIs without middleware/url-resolver layer making tests run faster. To test the following API: ```python from ninja import NinjaAPI, Schema api = NinjaAPI() router = Router() class HelloResponse(Schema): msg: str @router.get("/hello", response=HelloResponse) def hello(request): return {"msg": "Hello World"} api.add_router("", router) ``` You can use the Django test class: ```python from django.test import TestCase from ninja.testing import TestClient class HelloTest(TestCase): def test_hello(self): # don't forget to import router from code above client = TestClient(router) response = client.get("/hello") self.assertEqual(response.status_code, 200) self.assertEqual(response.json(), {"msg": "Hello World"}) ``` It is also possible to access the deserialized data using the `data` property: ```python self.assertEqual(response.data, {"msg": "Hello World"}) ``` ## Attributes Arbitrary attributes can be added to the request object by passing keyword arguments to the client request methods: ```python class HelloTest(TestCase): def test_hello(self): client = TestClient(router) # request.company_id will now be set within the view response = client.get("/hello", company_id=1) ``` ### Headers It is also possible to specify headers, both from the TestCase instantiation and the actual request: ```python client = TestClient(router, headers={"A": "a", "B": "b"}) # The request will be made with {"A": "na", "B": "b", "C": "nc"} headers response = client.get("/test-headers", headers={"A": "na", "C": "nc"}) ``` ### Cookies It is also possible to specify cookies, both from the TestCase instantiation and the actual request: ```python client = TestClient(router, COOKIES={"A": "a", "B": "b"}) # The request will be made with {"A": "na", "B": "b", "C": "nc"} cookies response = client.get("/test-cookies", COOKIES={"A": "na", "C": "nc"}) ``` ### Users It is also possible to specify a User for the request: ```python user = User.objects.create(...) client = TestClient(router) # The request will be made with user logged in response = client.get("/test-with-user", user=user) ``` ## Testing async operations To test operations in async context use `TestAsyncClient`: ```python from ninja.testing import TestAsyncClient client = TestAsyncClient(router) response = await client.post("/test/") ``` vitalik-django-ninja-0b67d47/docs/docs/guides/throttling.md000066400000000000000000000101231515660254400237360ustar00rootroot00000000000000# Throttling Throttles allows to control the rate of requests that clients can make to an API. Django Ninja allows to set custom throttlers globally (across all operations in NinjaAPI instance), on router level and each operation individually. !!! note The application-level throttling that Django Ninja provides should not be considered a security measure or protection against brute forcing or denial-of-service attacks. Deliberately malicious actors will always be able to spoof IP origins. The built-in throttling implementations are implemented using Django's cache framework, and use non-atomic operations to determine the request rate, which may sometimes result in some fuzziness. Django Ninja’s throttling feature is pretty much based on what Django Rest Framework (DRF) uses, which you can check out [here](https://www.django-rest-framework.org/api-guide/throttling/). So, if you’ve already got custom throttling set up for DRF, there’s a good chance it’ll work with Django Ninja right out of the box. The key difference is that you need to pass initialized Throttle objects instead of classes (which should give a better performance). You can specify a rate using the format requests/time-unit, where time-unit represents a number of units followed by an optional unit of time. If the unit is omitted, it defaults to seconds. For example, the following are equivalent and all represent "100 requests per 5 minutes": * 100/5m * 100/300s * 100/300 The following units are supported: * `s` or `sec` * `m` or `min` * `h` or `hour` * `d` or `day` ## Usage ### Global The following example will limit unauthenticated users to only 10 requests per second, while authenticated can make 100/s ```Python from ninja.throttling import AnonRateThrottle, AuthRateThrottle api = NinjaAPI( throttle=[ AnonRateThrottle('10/s'), AuthRateThrottle('100/s'), ], ) ``` !!! tip `throttle` argument accepts single object and list of throttle objects ### Router level Pass `throttle` argument either to `add_router` function ```Python api = NinjaAPI() ... api.add_router('/sensitive', 'myapp.api.router', throttle=AnonRateThrottle('100/m')) ``` or directly to init of the Router class: ```Python router = Router(..., throttle=[AnonRateThrottle('1000/h')]) ``` ### Operation level If `throttle` argument is passed to operation - it will overrule all global and router throttles: ```Python from ninja.throttling import UserRateThrottle @api.get('/some', throttle=[UserRateThrottle('10000/d')]) def some(request): ... ``` ## Builtin throttlers ### AnonRateThrottle Will only throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against. ### UserRateThrottle Will throttle users (**if you use django build-in user authentication**) to a given rate of requests across the API. The user id is used to generate a unique key to throttle against. Unauthenticated requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against. ### AuthRateThrottle Will throttle by Django ninja [authentication](authentication.md) to a given rate of requests across the API. Unauthenticated requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against. Note: the cache key in case of `request.auth` will be generated by `sha256(str(request.auth))` - so if you returning some custom objects inside authentication make sure to implement `__str__` method that will return a unique value for the user. ## Custom throttles To create a custom throttle, override `BaseThrottle` (or any of builtin throttles) and implement `.allow_request(self, request)`. The method should return `True` if the request should be allowed, and `False` otherwise. Example ```Python from ninja.throttling import AnonRateThrottle class NoReadsThrottle(AnonRateThrottle): """Do not throttle GET requests""" def allow_request(self, request): if request.method == "GET": return True return super().allow_request(request) ``` vitalik-django-ninja-0b67d47/docs/docs/guides/urls.md000066400000000000000000000033411515660254400225310ustar00rootroot00000000000000# Reverse Resolution of URLS A reverse URL name is generated for each method in a Django Ninja Schema (or `Router`). ## How URLs are generated The URLs are all contained within a namespace, which defaults to `"api-1.0.0"`, and each URL name matches the function it is decorated. For example: ```python api = NinjaAPI() @api.get("/") def index(request): ... index_url = reverse_lazy("api-1.0.0:index") ``` This implicit URL name will only be set for the first operation for each API path. If you *don't* want any implicit reverse URL name generated, just explicitly specify `url_name=""` (an empty string) on the method decorator. ### Changing the URL name Rather than using the default URL name, you can specify it explicitly as a property on the method decorator. ```python @api.get("/users", url_name="user_list") def users(request): ... users_url = reverse_lazy("api-1.0.0:user_list") ``` This will override any implicit URL name to this API path. #### Overriding default url names You can also override implicit url naming by overwriting the `get_operation_url_name` method: ```python class MyAPI(NinjaAPI): def get_operation_url_name(self, operation, router): return operation.view_func.__name__ + '_my_extra_suffix' api = MyAPI() ``` ### Customizing the namespace The default URL namespace is built by prepending the Schema's version with `"api-"`, however you can explicitly specify the namespace by overriding the `urls_namespace` attribute of the `NinjaAPI` Schema class. ```python api = NinjaAPI(auth=token_auth, version='2') api_private = NinjaAPI(auth=session_auth, urls_namespace='private_api') api_users_url = reverse_lazy("api-2:users") private_api_admins_url = reverse_lazy("private_api:admins") ``` vitalik-django-ninja-0b67d47/docs/docs/guides/versioning.md000066400000000000000000000027321515660254400237320ustar00rootroot00000000000000# Versioning ## Different API version numbers With **Django Ninja** it's easy to run multiple API versions from a single Django project. All you have to do is create two or more NinjaAPI instances with different `version` arguments: **api_v1.py**: ```python hl_lines="4" from ninja import NinjaAPI api = NinjaAPI(version='1.0.0') @api.get('/hello') def hello(request): return {'message': 'Hello from V1'} ``` api_**v2**.py: ```python hl_lines="4" from ninja import NinjaAPI api = NinjaAPI(version='2.0.0') @api.get('/hello') def hello(request): return {'message': 'Hello from V2'} ``` and then in **urls.py**: ```python hl_lines="8 9" ... from api_v1 import api as api_v1 from api_v2 import api as api_v2 urlpatterns = [ ... path('api/v1/', api_v1.urls), path('api/v2/', api_v2.urls), ] ``` Now you can go to different OpenAPI docs pages for each version: - http://127.0.0.1/api/**v1**/docs - http://127.0.0.1/api/**v2**/docs ## Different business logic In the same way, you can define a different API for different components or areas: ```python hl_lines="4 7" ... api = NinjaAPI(auth=token_auth, urls_namespace='public_api') ... api_private = NinjaAPI(auth=session_auth, urls_namespace='private_api') ... urlpatterns = [ ... path('api/', api.urls), path('internal-api/', api_private.urls), ] ``` !!! note If you use different **NinjaAPI** instances, you need to define different `version`s or different `urls_namespace`s. vitalik-django-ninja-0b67d47/docs/docs/help.md000066400000000000000000000027171515660254400212220ustar00rootroot00000000000000# Help / Get Help ## Do you like Django Ninja? If you like this project, there is a tiny thing you can do to let us know that we're moving in the right direction. Simply give django-ninja a star on github ![github star](img/github-star.png) or share this URL on social media: ``` https://django-ninja.dev ``` Follow updates on twitter @django_ninja ## Do you want to help us? Pull requests are always welcome. You can inspect our docs for typos and spelling mistakes, and create pull requests or open an issue. If you have any suggestions to improve **Django Ninja**, please create them as issues on GitHub. ## Do you need help? Do not hesitate. Go to GitHub issues and describe your question or problem. We'll attempt to address them quickly. Join the chat at our Discord server. [Code-on the webdesign and web development company](https://code-on.be/) gives commercial consulting for Django-Ninja. If you are looking for support please contact Code-on and we will be in touch with you soon. vitalik-django-ninja-0b67d47/docs/docs/img/000077500000000000000000000000001515660254400205155ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/img/auth-swagger-ui-prompt.png000066400000000000000000000667721515660254400255750ustar00rootroot00000000000000PNG  IHDRBSFiCCPICC Profile(c``I,(aa``+) rwRR` >@% 0|/]6vUܞ_B0գd Ӓ JSl): ȞbC@$XMH3}HHIBOGbCWP#C%VhʢG`(*x%(00s8,!00X|c``KABLe öCEp0~c)N36yXY}"߉^@o30p_CrOVeXIfMM*iDASCIIScreenshot+R5iTXtXML:com.adobe.xmp 702 Screenshot 394 <ک@IDATxx\Ն%KbcM@hB JH BKP$;ƽE%[?gVs}wujwZó{Nw۳gL6C:CAA&tM|BR @ P6i @9GsK€ @2A @ s9$  @ J @9GsK€ @2A @ s9$  @ J @9GsK€ @2A @ s9$  @ J @9GsK€ @2A @ s9$  @ J @9GsK€ @2A @ s9$  @ J @9GsK€ @2A8&fkk{U'%}o5kH{{ASm.zM2xxD @CDžoKYl7۲>u2oPĈAIYmjje^O4·ޫWq€(ҸB @ L# ܺkii%KWx @K /}|Z=Je}eؑ2tH{Q @E`'l:ZWM!·C[k[[[RڥɺX ~ ǟlZVSo ո]u2.O@ F!qT6#:ZWM!+ fq?XbU+( KYv,YR%msE #f9sKsKx>W~}eQ5RorMyRkV[VEUV60V-U4ϞлW hA4ybf͞/EEl#@ L(2L"}|2ydoNE-))u2nUѻ`.W!m0yKRk ѫV\mk{"GPzZq=ayW[ejVmF2 vF!@*dUƲvѫθ𭭫kzҪe]bEpn3[J824ҳxS-Z'UjIMaap*X{׷t-@K WfaŊF*y ʸ 2/s ^ב#GH0w|ii WC0oRzW_J>lw_k\(3nc=Wx}vcyęS cCcmCs#@ lp7!_D̨W}YܪuAVh*Cus}^ %%ƊajoXw^d|2~(eB[K =5̨W-PQa_ex5[yL z5/M jqƏK[AH @N_g֍lAkaګuCqq" %z>I9 "s@ `ůѓ4-BL 1h5O* --. . uy#qY:Hl(4V2S_]<ȵ6A @B@[n/Q[jÑϫuJu~4…ם/2! /B$ ; vyk#\8b=P @ г2*|'D sn UCuм>*|ׅeVSPu'4D>Tb]uH !j]][p'i#*bbez>kkOiv @  _#%˽!̝؜[jE hAeUZfEj#Ej<1ye}%W= ': D1g771"o|uRWU-bN(G@ }K9g]g:ѫᠠpaYzn*c T?Ɯ)"*vޔu*]Ч-ZLM,eؐuǧiEw'Du岲֞:ѝv @ Е@Z.'ƀ~}e1naLil֟6>cnj6(T<6H]Їc 2m:7%KǦՅba^Q" @#P0m4D$[͸C) jIM4]&˂G&ږF7=ϷT'!kŸFwÜ\TxKmPA #wuiH zE"AXHѸeTT8cOJ91y)7HE@ 0wu@ o[@ @f7A o[@ @f7A o[@ @f7A o[@ @f7A o[@ @f7A o[@ @f7A o[@ (NTQ @)HVLIVTts*C @ [pui @QO @"#[c@ @:\lS*zuW] |=_@ "ȍO餅-kEj[ imtM@ D'(wȀ>\5p9I _j,A2PtI @H@Ѻ k diChMJUֶ[&ү4yP @1 q-2[ߔNuhZ[ }KbL@ @ѝ?RӋ{CwS @ ;ӱ,i ,e @M:4ixn2Nȭ"L]ͩh.122@ Ni*zZ9<b )ʴ @@.H!K]X޵^ ۳ V1kTQ ~ЧIڵkQ֬YcSKJJU^z~4wG UPK |";V]V ]kk¢\1˕ @456ڬ>}Hy ojlѼʊJ}p=VgBJj@ dsoP[hV?b0_EbF{ @@vokksI&ߌjUMoشO) /5ؖʽemx/BBqO)Aќbm M߻-وU<@ k <$:UDWp Y|"*E$o(/xyדJ}C_ph!B[K"^B4Cubw3XAƦ&пw麵ҺoKV}rz  ̓՜˦ΠuӉ!VW~fFCkCShMÍ ^ZdS0do]ukLVc)֠_VJBeך3œn2 SPVlO ptɲeeV;v\TL+V4;F[]eDw}]V1O>l76Ϡ61| ?̗bW6CGśʕ+l5TVv (ʆ΀uÏ3(ٙNVK J57YڬhY kY\B/T?(TEC48h| zU /6?V#W˨Qm%Fl74khYB;.~͡i׾W,_n֠0-IE1.(ʹ-\3 OHXZ)7k6DJfZ\+Ud[CYY 0ͭ^{1uF bW?ƦV#PKd2)5cP¶ňArmփ(:T֘:CzmlJ0I*9jPSS'uFWAl.պVYl86F ϛH6h3"ãɂKL2;_{Khssnיv/kaͷc1b Ə1b2x7ĈFYJ6ި\ɾ/}\[̗2t@#>k|Ȇ'n[ ߸ݿ>!@'T( _0U`b(&@5 ƨ e`[ __ޛl2lcæ\QQa? (tIᦢXg+m#QZnx!ZmVXƶ6MMMnү˦v~y@=g*kUSTBMS᫂]- J"T᫂܌VƏuXb,ZVEc5V 7:n^ NbV4A_3zB>L -3cmhh03B~3ҊvoSj].*25M|"V] KVaRcļn ,~2l(۞- UPh.ONz O:[Uf:dXeq=AV%>*i5]Sx}֊VrRXR(CjZc0zk,mXҊ"Z+Sl6iP<U`ֵBlQūƽ%fEog^u TyB8)'`\6˹ Ec0/J2.^MfL͆Rcmh[ J꫙.^ ɪ̊ln @Y#`UC֝(|L5i %x0t# IP-K][aVO ƪ8:lZ%AZr*:UYe2\muK+UԘg3Ղa#AǢA-[Zi,n,hj-4k5FiP|:f<"RQQnͩkŽ]}yUVkW{{{a*2B^ǾϬa^-cǎ1}1tȬY_9jWٸ? mV4j+ ._FM3W+b7I;`kFK uY _j!aE*#mlW߫=D-*^Al~ޯ^GgtG{ucTc4W+-Knh~ {UKKR+PRm6iŝ]-ZiM}ˤj nzѣcPfıU\`Ԛ:sb`N75d :>f>gD-yT}Z_gäVz~Q SlӠ\ŵRmKGEK泡 rF׍yz}Mt.7_*eMsDbuC!`u)VBe//M'o,{Lr3Ot;@ <#T>s;dYINh2);`vn@ + OMl39*~> Uѫ?UWEz"v{gAC P-Pnj?mMaUN @Pm8eftJP$YW6qXtݔ7 @`%Eje"ⷛ TTS @`" 4FAS&ӐkHp @H@oL@l9V< @zO U _QtD  @"~Tzo"׍0ࠏ`kn y @,G> ȂT:Ŏ<@ ~I 1C9횦X':IJvi̯zo,.TH @$O+d$@ U!W8g8ěHȇ @k!]4jN&!UuWV!k]1̘ٮ1 @5Q7rl0SgwCA51(URgmb Cn @b3͡ D̤69RGmխf fHϔ @X ,XqUr;;H cn^s-E&|qspⷤCUnC] " @ 0ڰT՚NojkX$o„o2uݠ"SInNo Ǝc>Իts?gx ri'z\[`s3*ʝ<` 6DN<g\'}$[oyVGɌ^}=[{6Wx^_HQK d/,{G`+DI {/jPZ&&w[[V9l 7xGȁL*2uW޴{ݼ;;w·N| [ >ˑ_\||5\{%ҧOQ3/#g]Ν;[M7؎#Soo ӿm89ϗ&dߕ7@X/ wyrI'$sOM{sϕ뮻.,/HmҶ'|D=w}շ<%Y46u¹>eW[oo香#_ @,  b|ݬf Aɤ ⠴dLlQ+gdP1,fy\Vլ'PEJJǒ@uWE<DН2*u=$fZW1GyVX]^|mrYYk_uܫWʠA&k3[K~..\ļBVv]\׼Ɯb!C v\!@ O %W>#k:uZ5lr饗xwoL7(nYox=;9(˖ÇG{JGm|rˍWyX)S?шW_o]c/omԩ[QG|sY?kjK.ETۭ w oi[AEc 'ش7.}͚rOϖ7 .ﯿfZ[Qbp=!gqRT1o#Q7vdʔMU5rn]K{~Δ>.ZqqsL|Nyey۫oG]W| 5}G3^Wq{-w{mEwu۷\v~6rwŸ~\[Osͧ@S~Nt km; 8@|jyR{LlfλsӎY= @ ? 8?^'|7I!H8'%|DC2em3ZĿ壏?i/}!6U4iXx,Z&3AŏirV9mM^{?r]7ZѢXWa]--rԱg 2-'-V=zdX]?'rg}w M^'V GgSQ:xDf͚#WҷܟO*#ưv.Z!VD?8 6o]wb6-_!r{vZ9뜋G?ws#XzI?mǽ6r ^+ykI*ΕQ/q~q}guc6ܿddus3^ιP2x eW }9֛ڟM򄀺2<7bJ4-nAB5(;h Su}6j-]wAsWo~IO?{hMlh'ި삟PN?8  E#λxGg~bנ?nd}Í7Ƕ>?_G WoKRg:~ѫPvmg+/jÏ?OjT{Q'~n-3}Y>KSیPra?#4x _us[2x}m[o ۼȷL'.l"OE nկ/۬bUjO&|L9{Uf+~j?]g7{{5Cww ߝfҤ =᫾5>.藽S_VT[{ƮW@zjpG~({_5c{Nrd{ݶ;]p>0^x&F?r9b0ZH5|闢Hpa}rQчRr(2Qޙg_ DSP2jPgPX:,Y;o[M,XfG8M8G TU|afzTb3/?~еtA7]{a#渋}+kw:&a*A'E/(?y?pp?o1t[D׫gjPѫ';Uˤ_pHXB ߞfseE%~ٗ{W:^o켃 R"R˜~*&UyWO8j)cԲ?yV4DG;bJŋ?kп_P 9./k4[WWΙ31&d~#//FquW7s0ѫo켽ln6Pz)XRtwO!k^7z'3tO?QqM9@y'xbUzo7ez L$ULŲ\Fxww"TDR?\ǫ?x>s͏l>{~~⫮7.lTiS*!AuN* Ts;Ly6SXP߮ƓQQQ5A˄K EKr}g6 ߺuPzK=󶛮}?߶ ~[=>/n]"s}g̗v 귬>ŗ^NP}b\@-Tકם>BAyrVH- _=W S#6ߜ=z۴'Ï~xՇ6q8-Q\?z?Ď-D[aԥ#OzMAᗗ^-g?zzEtqD 4@Wr'Ky{^{*{K`yv6Wqc,{{`%@Js|dƴ;ͺ񖻌DfO8}'n Wް/׀YմFs,^R%ޱn4/s?%FfzzL{~Ѻ?_6` R @@,a+;ME&_څo.>с+g_f"&7w>;A;fc_ӌra,z ֙{%)c_X]ώ j =I+uIJ_t>,!2 z,=nM7rpյ7hֹڜ%wee׭tsգ&maDf\&~?D8w4{|Pv O~aimγZպϦr(%B]mȠ tG @&nd ^}[z9o<(=M_xu؎ggyڅ?Z+eUw5SC h"cJŻ炞Vr*16|d>9t|p#]S\;2膬f:Yz_iw9YN:Ȱre |gFkXUTf3LfmdP@DՇs֩afڿa-&{G͹<>dI\X/htZ?~LXF[W?q\!@9M`ڴiFh~V Q2~ƌgE@^_Ϟ'9QOҴ>j5TIFGn@ՉMm*z ֺV_]c#R긴Tx嵾|]{Wor1.m5w6gԪ7v90|Ҵe^YYaGԧD9=m5mh *29W8/և_D;΍+ @ *>}z-m"]]^e LWxwzu @ ^ _5HE_W:DN{@ #G|@ ^KVoa @Y%- Mu0*i: @)Ґ ߜ"` @ o Ш@  |{ߚ1b@  |SF@ '/0·׌@ d7  @ |{~  @@ |. @z·׀@ d7  @ |{~  @@gEUUU @ LȚ1bD#| ! 7 <K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2II @ 39  @ K @9C3K@ @2I8vryRPP M$U4 @@L<39ۜO]P*%KQ+2x )-) sϦ?}qۥs:Uvi[]H3wqcGK߾ !uxq Ə͡1@'߀՜9k:w~wjCOUUԎ9S8SGG\mG~`ku_cمmm.xo0,2ҽitHG>S;+\f>T:`;]w[qA@/'Xp ^U#KuIWѬJG~ Vn}͛PfΚ-vn>q nwe=WϵWeٗC#_7Z^~o5n?qA؟z9ill{S;m[ʫ7 B@/!CB͞=Ϧ6;9d-x%r-wZ[n+WҠVXi yŊ5VZZŇUm;#?X˭^]k#ns>.O}:]Բ#$u^s}ޛ_Vf:E6WϿƩV+>lZYJ1"j{mS6RZfowӶ8I/S3:o2Zv睶^~KO>V>6N^yÔ}CJoNfm?{ҧOW7Ȥ&zQWw۹Ȕ6fYzH}#Y`lF2u-c[eV=|)#KV[Dkc*Hl_.#Tn%bq7Q˯o7@@ |#H>m'#Gŀ_FTzq)$~o"[EFn FXl'a~ѫ_Jۦ6$gf(}UvSeEa߶Ə=1䛩'ok?eˮslSҳns_"O~o?V˯E"uCfKm{*v|넯kJuUۜ =V]Կ;3Bx~4覽M&mhurxD孯_YUU˭*>_~ML=p-2v(Yh7/yV֘  M>}OwŶ'l0 @ 7ȑ6tgkvIŖA _-*\5x1oAUhN8 ÆZ1Z|]}eYu#SnYz/ON:"woh;/Dkݬ%8Rk̔sdV޸wF_:TCd]wVPoz NSF!wb=^_NYR|о2qx4p`CbR+T(?zEEr*?! g)./BN.; /&(?O9ģlv6MŻ|?8qTT_HdUjе a3y @냦& jaTqyIˈTӎ.mBHd=Kupa3jУ\3X S$,ˮ>VygEk]qbԢ!Hkbi׺.. r,[.Ol*յu2zHӰqW{lܠtן^<&O͈Tm [ssw g#䖢?\suS~̜t}8'no9uղ]zrr<_27ن 4+pb/N _Eqji'_x"W%#'zQ.]-[BF_3Q ~pQwѰCR[+F.h;~^8;+]KFvmQdAaW?F%xRicvWw^<وZo9x?[M]-Zj}EOvP+:+ctZ?>KrxV.| {Ȋh_&( Vt@H'o'M~JĈy^yM9mLCmL똰K.% D2[`~:D0 !9d;/B.|^_+KsW=ׯ;7!꿬oqp!Ѿ\yw,Z0ڬm*IDAT Nl740=Frs缻ojnvQqdה>UƝBOT̫:ϼղ+]2ՠuXӴoC躐~VG65Zorw+.5 Sd_,x^΍dG&omye󋅲;>Z_vgع)hy\k}%27-vaO4 kroR*d>nr;zK/4GC}h}kc-kCw~R^^f6ʹ1r:ԙ+6y-WN=vC{oqWieW +R$qĺf;=m{jUߠ#bL86w̛ۼL}-[^^n S"R_OL>M-Ϲs?@n@+l3PKQ׳݂@H7,&J{9I@`^fd d.y@G!Lnb:.k|}>]OA d>J @q dWKB@ | ͇Ud @q |" @@>@*2@ qQ @  |a @@\߸(@  @ .o\D @|XE@ 7." @ o>"s @K @7V9@ % @@ @@ED@ | ͇Ud @q |" @@>@*2@ qQ @  |*.XHe_g[zMȏ-= @@@7nL8^WȜ47o#}˴d> @=N۹~{O{bYV~[廇,u\d5]~3"3gͱOy{O3g͖,yGzCr_@ ·瞻|]{}u=vGZ| 06Ly)?|ۢK䣏?Fl {_W['uV2i҆i?,Xؖ閻[7G @ VnJ]Ə#ooǺ9l3mKYVs+|6U4dΜrU o#JKKmRsK脇eWxEoG~~vm,7!2D @2Gc;i2f(Q_]=A4kEE_xcl 7)o<^bϿl$y湗D}d葲wO?@ `s[췷MǜnN>({=뜋dV 痻7vzmӷ6 _r 2H~}Uٖэp ^y" @%P0uT 6W}UcuYϘ1ɎR5Z] @nxkhlL5aUjQpiIIբ<' dv0޽YΥ ~*1eD bSw  @@v ]@ C=n!@K]@ C=n!@K]@ C=n!@K]@ C8anر @v Κoq„ 7@yOu׹j*<ћ{& o@H'o'Muo8p`: "&  t@vԟXqoHG :} @\H @3<[P@ L̅T@ <#ͳe: @\H @3<[P@ L̅T@ <#ͳe: @\H @3<[P@ L̅T@ <#ͳe: @\H @3<[P@ L̅T@ <#ͳe: @\H @3<[P@ L̅T@ <#ͳe: @\H @3<[P@ L̅T@ <#ͳe: @\H @3<[P@ L̅T@ <#\Biooϳe:ߢ$@I,4+**&li H[@@: |;i6Lo:?a$W E7I @q:m˄ d.ny5{o% jo@H'?~/( @@!_Vy@ $L@ |!͗d @1 |c! @ _ |e% @@LߘxȄ @|YI@ 7&2!@7_Vy@ $L@ |!͗d @1 |c! @ _ |e% @@L1sɄr@GG76K$ q^b]UȊBRd@ O |taV~Pe9Ҿ6'܋gקX0Q ٴr$*t.\(/̜9S֬YӋ)KJJdҤI{رc^9#IN,n,nU3+Wt/X@nvow~q었38Cƍw5@9DCP  vћV;|+9cd`IxU!5ky/3>v&JaaaT_w_***zhmCC<{=cC~̚Y@I{8ޠћe_Jt4 ZF4 zJ,_8(K 6uHeJA·7c!O/p떈2ΧKoرTCz%@ W |se%$?z/D/2@nƹ&6q@7ǺrjuCSȋ:/I@ )ߤpQ @@֕c @I8pQ'-ev2;>>[(EUj+ǵeQsL!!1uWeeH߾^噳fKKKl)//҉@Mi+z|Q~ Lj$,xU>+N:E6.W1 _Rm+|X 7> ^q _|M.)]$ӿMEˢK侻o&oV@e'z@c['zu6bH6kXx?7OtMeAOtWy'~!+~۩rIGˤ'ڹ7ɋy2 @J/@ &Vɚ6Y`-.<]ڸ,rm_>jEvxnZְU<}ihn(nz4hwUjϊ H|a2Bf7. ?{PF`MG+n,l[GzGw۶"nd\Z)y^f,XZeXi?9c^ǐ"MEM_ifV g~SO?'>]!}1KŗXw^r1'i7zW{UyweI[ˑ'!K.)m"'LzgK$@&o7RN੥!װ)RmKޑmz ¦jYZ's lҖ״ fkn[#Vb.EoyoT%~V~~V _?{j?5V>UR}k6#_%ܾF</[}խhBX=ge #nU2c(%ĥM%?]z7ޖvWQ"X_ VX[eY_wj)^:@$C:ir#ՂCCЗW|L8ٴr-)GU!;|MnX5h'v8_={GR9eZqO-,={ Snrh[ҪІE`U73JFe+WDE?;G|)ѫ1Yb^{*tv5ۮ;ISszSr{q{ @& |3A6!'[IiaL4 {vȜp]LvmXb_ḱߐF2x ߦ}\^ΔM!u!21c7~7kagm듍yWiqwʂ4běfYY'u|={W 0Ke[wZm_|u}C;{S~SeqmpU~[m$C @ \"1g^ H<m5 : ,kk;MW3ukLI[ UH]acSqlF\PVTb_Zn}C9sl{TKP^z]*g|xl--!vj..Bdcsoȹg_Ԃl O?v^sS4>S<6D X?~n'ts=oݔ?fI144nz*խxص'2"n6Uj?/L67 W=MÄC#jߪ'[dm͏AF}o m_x6b–Becw_yStvSe2g|أaܸ16ME瘍mګ;mOʪr.23/ȝw?`7y ^gvl`bD0@ |3Ev! I 8h6 !/\v0g:ѫ [sx|fCF"yꛫԹ/tdգ4Y!mĈбu<.OkE\h})֚PKZ|(?YR`ků?bLS݃ndWCHSzy??m&"˹3fyD$>i @VcS>8Pb4;lMڪи'DۊVNWGϘÞovm~,Ycrk|۬k&HKȎ7֩ *s:=96Rƻw,WW&@!$A@l,A+8$~D*2A_{2d+V\}E }E *sC\C @·, @owQ @@b @!=B ܮT(AOQ >Nn:啔'zHPYҒ#X:urPyzI@Xo^D@E]DĖxm~Z` D@*K 6uH#*A9Mrzy9|{v}> ګ/hvMf͚%}ūC~bګlYZ Л?po cz@@`oR1R0<5|LWNQGIK-eƌ#'xL:D,]I&駟.SL"[_ @ ԽA-*zgΜM4Hih^cr,/f#Ism5~/=@/,gP~wܜpyTe&zF+ pvDǟh9_)@褠2Ai2NIX@Ҵd]ZϽ\W@ p+sr>5x$WDuPS8I @YpU'(/(-V?ɖl+LjcɴgI{W'r ;z @@*z)</~2ehm _tuDf<Kg40m @ Qce[7`5/HFKs~AC @, -VhyҵXy~cŻ_m42Z;J'R' @ DxuGK^bE"V.7r{m8p2m:K @@f$ŢgLˋxe @'^KLтvmt@,m|m+rM @ "uY㕏d"|uh":Xm' Pm#@ N /|Hxe{NlT᫕ʻj32 ]AyA d@"Z,]eITlCZ^'K&S=W+ @dq@h/Z(Ssq4Y<0M 9ʵe-MFgOM ;r=5q֕ @ _g=O=e-GfoM,6?jE>G @\eQ^ߺ2Do{ϟ}>w @\6z~fǷm4;h]9?Z= @{3yn6u["FM|e#QJ _m#O|;%p!tqv^ @ ԣ+fko:#f٥#@/VꇃoX Q_Y @+a5s[X!g~z @^4o<<+֋dփ @_tU'z.2bfϖCȕ Yf˜,,#..()G\?͞#%ub/͘i[% @;r\_nYvǐ#w @ ,+O[ư_k @o D~9Ֆp @{^o 1t* @SΆO <|EZk @3[[>|E[A ڬ6vGn'@|OpߛgOQ0nż'@ e'{_9 @@XI @I,"lIENDB`vitalik-django-ninja-0b67d47/docs/docs/img/auth-swagger-ui.png000066400000000000000000000663741515660254400242540ustar00rootroot00000000000000PNG  IHDRZ8KiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*iG@IDATx|G'[-+RN+o޾uThŋwB6F@@    P,b1  T@@@b T@@@  KX|l  |@@@Xcc@@ ;   (#  A@@(AE@@*   @*   @Pw@@%@PQ,>6F@@    P,b1  T@@@b T@@@  KX|l  |@@@Xcc@@ ;   (#  A@@(AE@@*   @*   @Pw@@%@PQ,>6F@@    P,b1  T@@@b T@@@  KX|l  |@@@Xcc@@ ;   (#  @$sden&ٽ7IKäJiԠoRu=cYl=WRIVvV,LaSST$mj)_W( \ ,ۤr~^ h01|xٹ{oQV 8w &,{Fl-S9o(E Oٳ~p8KѫyR`[e ]4 vkr%B@2$2t18 BT=¤PkHB@`LEh^r}0-1R1$K|M"##F%q{圕q$&:nWzͷ+vyBѪf\BvX#KE[F;5LT>-I-i5tcB5dΦodi^BBLuI< ^WLW(/@ ?u| WFiؠ5qHF RN-^G =%:jȽw]+q*򙙙?칋֯:⿏ߓj5"",Bn9q(qysI$sԈom4Awxmz~7{ªʇϴmK;~'9Jqgw;cɫef@@ 4KKudu֩)[+7p.O1Oټ{@kMWnUi3e^u׫[[N;W^i.ʔiQҼYceڵG_o<~:R~]*9o]gJߠl~gHZ*l@%۶&hбW(s56HIKԔ4ltʢKx=J[)|e_ywn@9i=ʹBty*+;'sJn@k_ CPPQrk7؜4W[U;YfHf7坆JxXO.aQRBsWb[ٗOUB  ٕ/?&Wqo!F,J~C>[kA?/" .ۧG+~S58i{^&΂,85g}X_z%+.:Wbbbln:{n/U vj_u[6?#Nn}ba:;U-2ݪmx>zWݞ z }lg5ΰYv3g]wTӥjz&g4+;aգem~˚id˻SOT {{Α:&h+-jff3cIxD 3kTW+=f K@BF ,iry!cny d-yjMޕ\&&N ZҦ͉rOJg('`QNfF_+G&캌LٛO]9cU~)PxֵOqgmφOujtw珩w_}HiQ!w=9-W KռӰA\폜_3~鲕X浮}ұ$K:3@_XK:Ͽ&I~.t^30:څܶ=nn1 9c& lߤ5yBy{/%vXʈO]]ίoW|;ՁOn^Yu4EVaZ!NTj)Ww]*6]nXH^-M?vzj3"\7j=I  Ze2KoC>5}#|E.i} ]˵g^^-wvC`>\}ݡG:֬Yyھ}K_TvcɁdʵ&j&gvwlxٜ艓fj|._%o$8`)nCl0KzRZgB"7WlySUy;BdjuZ Qq1erMiN5$TNj6и9ӖieY.!61O"SdxN+̌ =f @ *2rک} |l^LAwC~WrϤ/;A}~tsWӽ瞐Us~cq~lyZ3 #zVfhϾNZ7Z5kee؈\/N3g||lG`-toU+WH>ujpn~?AmRRE7o3}Z}roJbcG4 s^_~qZF:f3^]YPO5ͿFL\L\E~vnT7Ќemv:2c7ݼAr~$:"AʝcuVF/X?;ݧl}u4" :e*Tce~wϭNVM?[ Θ1[~y+6ߕ mt 憻yw?n)Ao:/\ATP{(A]pZoay#/*?~t@<+RzU_iX#礇zՙUk˝?cĨ֦WC zf>os+2~kRJ;^- ``F4ёAMMVB3kKN-lkp1aҤzWJv IHv+ @BOd_ ڥƙ*sR^ 㭏 ( ?+g13F_߷NN4M.PAY޸:uj~_z̴m.%^E~^M}@ǙW+S߭΢;ծP;mXsW@ p&1i4̼bW@T\}m (ip" Ze&P9v/ӝ7c)ZolnT0FC)9ΛЙ;Ձ޿듎Ч4isnI[&M]嬬lye~ifƪ+]|:6 (8 n0ۖF (I  e?!ךn=iSe@(e.P%WPOgp肳JEU[)t}uQs-.Ny@>{٣W^I,;J+{uw{̸}9e7fxb.Zy6+L1Tr%3.5cC֨vmS9}˲  p٠B p|\O ҧA4aǙqڶ2c 4ysq7.8GT \t+  @(AwUV.Se#-}j1cee>|"-XD֭hZrt`l  P&J~pB1Og}\yLX=I_l~ (>oy:[e欹~5sy, @@e9&O&rM6}:S5?wM(ԩr:֡u~93f;t#pA@@8"iE|mipNNuಿ4̌aU{{U֯ydfez.n/=hV~b.Vy^n=Ό{yv6-,  X#"#ꊋ䇟ɶ%$T}{9-67g{yٓ$cM ۮ=23˖MJ_׵1׷gw~L4-#TR!@@̏p.Q r=:fڿo/-_~ mdnqy}`ƥDF.wrO>} TVVg  T:픓ͣUۗv7HF{c?{1:<>?xWa'˶/"9+rD@TDFF*Wt}#׶[B|GE޷ȼߚX sdh 'SMWjժ|rg&}歉r\]t\]zkԨg6y DD7n9R@@ @l܆xm%ŧoyf:bfHO:ujIHvm2   Pr^֎>􌀎QE?$@@$H*jٹ_@OW"!  Ph։zJ/Xw|C:GC@@ T?##Cw6n u@@@HS)_s:@@(YZ*J׭]#'UTvA@@<T*[CR%&&Zԫ+}s  @y=r>  c*J!  P*|@@(eRgw  7vE9@@JY(|H7[䪷ֹNX_N*wsE  q呲{ΪU$Ojךnr|8wsWb'Yd  'PAi/%K)˓?ɦRR|J ߡ>'I~[*D˿kSrpyrtX3?IdJ,v]fV5(L9nω2u޴I pN7RZܒb70PhbYb2@@JZ]sI?|n1MӔ=rx}EpC&(Mr Ivg^m_f[4ciUPy-c%m&np{}Mt`Z}@65K{$O0omt.<ĖV=~M붥ǔ{4v=@@(M?%QsG^lF:Z24c8EL {ः)fqIW_S2LaݦtoohOY,6yڌG%tQ$ժixh[ک^7s#]ٮMcί~(]fljr+ui@@Kxzӽ?uQm&ЖK^[g;i np3 67?kZXA:y ֤ <{S_sCyRHm%zq]jg xUם\Mmұ#X׆m-P VY@M7̠3[m˶2]NhQ;5@@@y=6pxbT3v!vC1 :Xyi<菇r3HeӚQi.zc*te553ӕ$iJm]/ O4M7-tҧA7Ͳ 䖆vWZ> JHVX=jtG@@4J"jfnq%T~ao[_CI&ܗg }~I<qk {?Nc[,Nz=vF   eMНp:NM*bTbb;UiFݾuz( 7 !  p OG*Ǎ  9ރ PA@@    -@P  (@P @@@[ۃ%@@P"@0#  AK   AE`G@@o o@@@ @(  ,!  @Q@@*=XB@@*8  x Tx{   TFq@@ ` @@    -@P  (@P @@@[ۃ%@@P"@0#  AK   AE`G@@o o@@@ @(  ,!  @Q@@*=XB@@*8  x Tx{   TFq@@ ` @@    -@P  (@P @@@[ۃ%@@P"@0#  AK   AE`G@@o o@@@ @(  ,!  @Q@@*=XB@@*8  x Tx{   TFq@@ ` @@̫|vvG3ͫ,   P ԙwoPADffDF]l@@BL ##C""" ݟ4HOO1N@@ 8'ߠB+Җ    )/NTh}xV<  XoP<5  E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E(jl  AK   E (   @݂n&3R ,,-9fÈϮ@@| hhF|{eeJT :E@@L?Ei@@X|/wZptrmÓe|V!# V`Snq{^ŧXj;"bx ?\@@,qv۾;o?h?:?=EuEߐ>  @ߓ&$!輦UAѽ^ @(}e{ZDˉU[ m5yx:^늻0nIL8FU,nu%=vP8ə_1a  p deg?윗z9:a@g%_QJ2ttvR?|}̝UPdrAҳZOzCY=?+q!  Lܹ (t7O ;WMkǾ t5qZHتnJ2&@2vA8@@ڪ)2,w,lfsEZ,5ݣ.kSί^4US6KZ|dyMϚbOɿ{+ (4mk ~ILR!"ZNZn~5d4n$^lK#vg!$e vz{H[ aD=l,ܳޜS40-'OPTYm.Sw,tlLa7kXVǘBSLx]}k걕YU[uj۫%D<ֵ~#i tj9M&80bO0/y:+k"=[nu8p` ]Nr]e **EV-vI{S44G@gtNuYQ[ F ?ɭ?+Fo2ݬrΥy|mgni~ZۍIPwӋp>1JӤ࣯u7j$}SzZh߶6f<^GYJreyiH{8@ٶ\;@6P d`rt"̜NXKdI0 @@ 0E:55UNݰyyW8֊?A d[-x]سߔ[$'Jc%B;} X}Zו'H8){"m5ck"?$ӌ+d@_)_`$qqqZ*   @ԎꓞhSESRIjGn;8&m%BWKΗԳN)%jxY&~ƷHrr#QQ捇^f 4KG}g^5O˚yNDJGpSg~A"B  Fĝdyi_A/k_ykxkY_;Qw>z-'tRq,OZ֕& ҹY R}̜}o^9&?l~A* b=  @ hˠ'Oqz +s`5m")IҹgHT].5oO7 1uA?NPC7yg;,~mpfs{q*(  EvqmZ(Ir>&HH[v2AMק՚yPuIRQԉ !//y۳Zng?!@Zh&ȸv7l oHKEA@P:""Bo.iii幊y@@1p\gmofeffJzz)    PBԳgߠB-4p gZ85@@G "u3ȧ>V!  ߁Zf@@@* b5  /@Pk@@@X   TZ@@(@ V#  @@@  (   AE>E@@* b5  /@Pk@@@X   TZ@@(@ V#  @@@  (   @d6===R  O^N(NIDAT+`"ԁ  @ T@@AE0@@ ϩ#   `(R  !,@PSG@@ P@@BX"/>  @0*H  AE_|N@@`TC:@@a:   "u   !|9u@@!JGWcƻpZ_iܨ\ԙV Sd-tN.VWfΚ+SrˤBXw@@ʊTY'}ضub[xiN 8<9s.>=AP9aܳNի   PGlPQHiIT:X%[ ];T  ϲ̒5kֻ%k֬!<\w%n3  -#HdժUC6QTʂKeڴYk=I2k|Ir}JJW~>SHV-uAZ,^\?I9W֮ۘfdddHGϤ6# >{WK.2k֡mt[2)==]|/^'YN=W–3Ȍ}WsΐMKY6lUN9Qr\NOu:x'_9s* ֗$sn v%[1;7v(<~z_wwfk6$9ת+M*W+赎@@ TVM&L zSN9EF-;wwPhzmlPz2{\SWZhY/ͷS_M[ȋ=.qke}v7˥䷜X~<+":Z DRe.䵩]szi&#! @ E(]f?߀v)z7r|7okS Jx#׫G7i>n:rrr196l!ЖƷ&bc{sjUyTP @C ,A[!u BdPe2nԏruWhׄIhRw,CP~KZnȱ*Ny|k{'Fo(3-Jm۶N{8=>]Y̙jժ<# tn[l<  @ XR@e;d-W@[ b\Je{`"]O+IBBEUnxޙ'_emyp&MJDDhW:oo̰F)ݕc,j֬!:˫*7yjgٗ$W},gZԶuKO;sT4-'(^|-i׶\cմi#U#  PeB Ζ>]'lTG>CY5_$::ګڊ NҀॗߖͫNwMvzrl;շw'JޫNuchْݽʫ   @ *bbb˩ԻGoW~X۵̾eګ~H  )鑡k/=- *_vK^}}sp=?yYSC\2o) ;t]wq׶,   p²M*iW;w햅-YҾ]¦mw5dmR~in\MyQ޼eԯWWZj!AWdT-1xֹc.ٷDZ5c$@@(N~0GDP.@@BI4C}jBIsE@@ T@@Mм5  A %!  y9k@@&@P4J*B@@ 4*Bs  M"hT  @h Tu@@AE(@@ Y#  4QR  )@PםF@@ hA"@@BS 4O{);  @ ׫ ²M*@@(t*C@@tJ0LK4   #fO֙ZPAX~@@P@"<<~tCN0)Sh`əR7  Y@ M:(;l(ڞEjj.2lY,!izz$@@@tHrviQC$&&%bQ*ADh@,1K/&'6P*$<ԃ  @8!2eȏs^epXh FIVm"}["  p$ 9aՒEA9ݣJJI h'm !  @ };%* ,t ]JC  w%PJ%ɐ@@@tJ>TT틙2}HXB*s|+yJ=R @@DPńu8\l@-  PJS~fBA:fGh@@(-ty*K\2usJƕZ@@| l߶MfϜ!7o'Zn9Rf#DPqD r  B )i<;k׮ /J^뎤#jq  Gc?ekֽ:i,_Dt]>s+c*X=@@B lڴіԀ"&:~b텬l#(%$j)rw]K|d℉cB'=#C~a釟 UB  @aK4p3*\BNc"D5iW'L"MHjG\,nVUEZprOg(wgά"I)9k>#3S|Mٲy$H*U c;rM7eW\Z~ƍ'SLk IHoIr6Mx@@;J]1AEWcI56![ɽHfyyZ^+[&WyN4N&+Ss"[ЯyP_a9-i ~4m^[YvL2=0S{챒P)g@BG8tN(gZ#^abL_~@2 hVq"L;9Lnޞ-U+;[_ e"kv]0Ymj2 \2MDN=v-S|.Yiߏ?D[)Rn]ptorn&ɓO<)wMt9Nnf. ~ͺh`G'-[JdРACӄu0ݻW>c>}mhԸ= L`WJJ|2o"ӦMN?ի  @a OeK9]$ * ڸrN9R$5D_+] 6#$*DDWpk;3L  M E\N {h0FDTɯU<.p}ХNoϞ=ko<ջif6EnuV?o-;I'}ǒ-Q^< z?"RpWYf̘6('tj׸| ~7yUeW &gDUwޓիCZ2/dK9k֙KNjq="֤OsӦؠ-[ޘ }O:{|ǥiu8ܤkz' RE,~xNѳ/F7`~oe4tHӞ.tցҍfvj>۶ߐ}KKPmN^~%3~{lq]ȃ<$Mrޞylˌw O!C=w#7l4SH۶v ~u7f ('3goҸI^g?Tӄm0֣gNK=)&/h+m`ԩ3ǯ3:ӶDy@@ 8A3XJ 1f~Ӵ).:FT?6^?> y.j`}tѵeBכae.MԊbBi?.M%D>4CЧ/y04Jf#4\eoua劕6 qL,ۣWKؿ9M*5-Ufid?W+ nYpdwVZ[!뎻/8߮ktN@ ݧvZj}mL"ɓ:M.[6m]VbLL ҥkc *v=vcMPVA}Yn%OTEDKD[$fK̰_Ml眕uk Fɓm\}2`y'EE:s$..gST[QTVmgVFG D(N0+5M釡n)Rƍ{,u~q(hiҴiṝ/<玩ڂ_ganb#_/u쉓tyul9g㬶x :8L@(P'tf`畮 X%11-Q?2R~L9alEJYKL6fKRamLHrٲxGEt\DN@.؃1̑{>7 4/{T8afLCwOpkܧϙ2cNק܉+W^nZ4dQnY}Q-[1ں3O':{PJθ+R^8>i n)> QM &Mۮf|5inhڱ}رӞn~5JLӺW AF~JFǞa梘VC?n 5 nnFxWD?N_ې#[ܧ+zݻ{o{W͸{ܘ? }~}vCN>}2g8ێ q+M+/2ŵhۮ (4ҤO`8%H}`Sfg|L;屇w֡]>sgTdp vlVy~fw޲mYdD_3'ktD⨣ϏC~;v Ͻ`&f,dҼy nƥ,5u9.09+Ow! 6 y [яwq$prUwwr~ y mƓIbUSܸ;- @fPuڲ%>'< ʖh6y};ҹvh)=<#!_uyC/CYx[^|'C=Z\tz덴i׻ҫ_L:.lܖzN֮ӥ޹\ڿ;򸊹7Nuom=Ϧs[GgVRxCo=yrKՍ0p]A_7p=}zݧ3,{[n}{MbH\Ruv?pC쳯Пƽ6^b-/q㜏W|S8], @`s+?t.6mޒyK ގA0fs{_z:ѥ{핣i[nݿ%_X7>PFcii(eGKE"` dYK̥'BY"D4ExE#yd&3cvBŠEm @ Dh( *AL[v>_k&ΰU*QLw 9 @:`Qu9G.S<ŕDCeUWs*N @,(Қ_X7;FϦ?b1s;ME Es6]( @X""ukL @ V08 @,.+*W|@ @;:|b"lK9~zl65-;cs @:ha.Al>qw^^wJ/: 0l @n>-(޿#wea =TA.`[q+q  @7.PZ#bwЎE񊄊Q xn!@ @`pcKDX(_.[ @ 0"z0[]z++*> @ ; |-8f @&.  @ZD @&Ke @jQ&@ @I@hR @Z@E  @h*T&@ @*je @&.  @ZD @&Ke @jQ&@ @I@hR @Z@E  @h*T&@ @*je @&.  @ZD @&Ke @jQ&@ @I@hR @Z@E  @h*T&@ @*je @&.  @ZD @&Ke @jQ&@ @I@hR @Z@E  @h*T&@ @*je @&.  @ZD @&Ke @jQ&@ @I@hR @Z@E  @h*T&@ @*je @&.  @ZD @&Ke @jQ&@ @I@hR @Z@E  @h 'eIENDB`vitalik-django-ninja-0b67d47/docs/docs/img/benchmark.png000066400000000000000000001452741515660254400231720ustar00rootroot00000000000000PNG  IHDRa pHYs+ iTXtXML:com.adobe.xmp IIDATx '"*xQAOQЊ (G+b Vn(CmŊϊբ]aY@dI6)=O ~m۶%yB֭mݽ}W4-I(iCjU"@@EըM7Yje'4nx|@?|]: uoOj޼u{ϗYF 2Q wK"۷oVHw}WȄ[uVAڥۑg?krӵR#%1cGj7mo?HէC5lP_8}Y||K.ZIji(FUۢE LQ^dIfLvZNQqtB.((3_ WyXjAUeX]믿'hjTy6m1[WQ[+b#joذaC Fwq%\Vb+SϗCw9,+c׏*#W/֫vf5f\̀efdhb#'Y2ZQШT^%Lo8oejTy}I./rǎ)([@^LpyckV^5:tPo~*%. &ȋH)NUҨKEUy1M':S zzr(ƏH3/[nEPI `}9&*\NhTFꫯQ;*;4jU-L>Q-D9s\ϩZIbL>>k֬_|Q.r\bJn*kF[ѣűm۶_}\jT)bբS?|K;ODڦ\+j(r1I4UF5FsR?+cjT5b^;倯_^.Νۮ];Y ^e0`I[ i\ &5ŋ X%.q5'"bJ_S텓36DǸDUMŏ*i߾4UZrJ܃Z SljE= ԟ.Ն05hRb+ MQ+40QT 6 !AuFLSƍ\9W_}4[cr@͛'(7#)wT祷Lyέ4jN5Z-YD.X_SerD݈#zN9O<\GMiԋ/XkպЫQsrP>_ƻʣVnmX_A{Eb}hT)\}.$SqzE=r4%?DsԦz_Iʡ-R!ȧ{*-$ UVشiT;:[.dO.lջ'rgsWJ\Iy |r@v^".[Qޓ'"O!Q> JWqVz<| `=73?Q$m HRs1F5{CSf ZL9r0-39!E㡇*Ԯ][c=VAKzPa=r̭RiT5Dju h45\_'k];L+ErY]+ ;ӕZf>|7W#TL^? Rd˵c3UM]MUNE_dpTu] GWUYX>PA IШ c}(%Ҩr'~D[*-F章PuyQMi*~T˗iG˖-;u$Zʥ%_U90-aE+'|5V:o>|TS&D%FM'")0p}衇36 V̏jkT꘺ѪU"SQ5URFUku}]4U$ר*WOZ}riDy)jȫFNWP^*GLUQ/QSըrb 2TRdW1t|TfpfiT.ZQ.]ZvmxV^q=˽!K*W7UhJ+Ei)WO>dr(_ͨPW*5~xUaUѿ4jU볋/U2 =#˕D4ʉ!?V@$ՆH۴i9 hҨIDTPjUɫORШI"+RԨԫJo&רU柔#]gSHIQjuJjrf޴q&*\Օ -[7_ T\f{aQuC3lRJ-BhϞ=Fy\"Ϭ]yxNw/ƫQϊTXl3FU+U\IrM- :޻lO4 3%+GZ?\BJʅꫯ*?*N?WXU?GLҥK~D%nͤD{"JT3Ubb5B$u)lxS%tlUCUTaٞFnu}/2FqpYJTqQ寪U*TąmQMQqQi/T+M9u}Ӿ}oٖTIU}v?mZcUGQث>Swq[^F*/nԨ9"av>jL=.S:Jm3ػ:ͨFZVEW:yZ9nW^y#eiT]ҥ%ݨ5eU'EJ>Ao"ülR9|AU*GF-P=;5Ǘ.5ȕ>[%VVN32PoZ4*L~w :,%ĩG;u$v#&@3 MSxnaÆ6׮];].⢢U3iLbo^oL;ШpbtuQ0V@b@Q F4*ШhT@Q F@ hT4*QШF@ hT4*Q /HDU 1cFnݬ۵ko׮];eʔ;S:}]2nF4*Znٲ.;wo Q Yfwyٳ/$ v…Z4iR^K,i֬hT5ի'Oչf͚9Jz6FҾ}{iШjT%AO:3f4kL+F~170O)k(iFc[Q5F5&qR' 6LjHU| )Zm[%7U|ҜqL:YT F*Q$YiB*Kԅ|)u}UCoQ.%v*ɪɩαE`9[՜S*Uetd:}vNGdu4Kl [Q`ըZ=+RRgO=ǔ*-RרVy[QUHP2+Y=K+ūDʆ257߬45k|whT@_6,VdIudU(FeF4j&:ڹXV$YT?34*Q QUPn( ^p1c̤yg}cYM$@Q/y>vQ2-ˤJ˫QumnejTUTf>Vߵˌ]xJI}8tP+SJ*fLQG+Q a<5kԯ_14*Q!d Q FAu0{3 TQWF@BHFETh;ШdѢEcƌ:uN:tq~˖-OzRZ u m<ѣ/B}իWOy:utJ#Ky:v쨎{N^֭ӧO7 F%:5k/_m۶U'./}z=n8=??By5AN+&Y/ 9Μ9S}g7+H?ɇT= [UШA Bo{OF߃P~GZOG)."tL}姮QVTRYdQr佧#U諯ڰa̭mڴSqqZL4IYU޵FU3_.aFMsLcF͇4}9 QL~|4͖-[Zh!FwvYjuWҕro:u黡ցZhkTQU&r\%YVtM*.Sׂv뉝r!FV4#Q*LF^D˖-Ph} 5OP)/`SqnAAZ^|g}QFA兒fu[[.jƐh,-8Ck'e*X/֦&ř,гQ?n)}Wj/kWyY7%1 0ݶZӧrJ3O>:2SN 6L[|k6++TupWˁR|\_ޚ^~eVKoffa&;XUZҦM9r];2PK#F<#3Y#8$S tR dy4OMebg^A֎Zh1RVV22z}m<_Jk>Cj `~JL壱>T,׉{ҹnS[Ft^eCS4@nF̺z6S~T=zH*'Ô)S:G!M; $ǜ 5k[}onN>03<}T}'xoejTl.}nusL"< 5=rͧ%vFQsZWNRsUj46ﺉ4jUz;ʗ,X@вP_wײq;FLr}iW3t5yT}LdmMg ;z" Mv05Y 㓌$8۝N);3F-3%)cwFQ- |)x|uxջC 0b#.s%:$W&'n]<[~z&!J|(7%zҨ>`G )ޗm͚ {Q˧Q6kh}[Kԙ~KݐF^VQӶ2tF/̉:Z/=U`y5ra$ 0R96l|^$2U\*/|Bu<yʧwG">UZ%7vJ]=_'::{9a܍9[&;X]:' %C}mYR8x4SL eOe桔9E˻[z>k#K嚲%ū^>)$oQ}6DYh`|4^).J%5s&F uEKnQ.8K+Eń h4Eߗ􎕺Ĵ@ШPˏUL-wkgT^jނU$^z`hT4j#r_vZXaVzGLy >tZj*´P߼T-ԝʌW. xRDLF4vrEȦZ]7p$*V٣U7W3XMrD0u$CWDF{Q8xL4GX2hXFo}_*5UfZ74Z ̢D'j$vēI%5٨?zk<_KӚ@s\oU;Qդ:#N徤OD{/"kƊ&neZ2UWazQ >X^]ؕKi9DӲX_4jkTyqx PEwes;8F+)˴лfLQZN/4^4`/f]"*|<#̰R k~G&;xoAIZSC9qE-R8xTSw޼yH/L]Z-&MPJ]hJ2z*0w/@?h&E&^jDvqX+ nMfĬ7W6wWnva-QLڤIo̳BMKnP?by5No"'l~emDcf7Wu3e7Ck/$ \DQCo+K tPꁲV]ZƘӻ^fa^zo+L_*U"/|i*K(bUkTSsY.]qj2{6:Cf\[PҸ#Q-;HOm۶5j*y(eNoQiIna*הUo旗zJd9FMdg'[=oʧ[-UD+2׻'m_U/S?$5p )̽UNZD4R>n;siTݫH['@_4*5[={:QF2,5OجY>c0^_ߢE )pG~=ERѨ[Ռc%?;O,??^ϤGMQ-fwG E?Y~txݾ𣦭QL5rQQSi?ej B~}Q9F-R=j5V۽R=K:U5:dT4*F$+@AuM3H)Ջj"|v7U+UY}q(+%s]U֚;{!Tu^SI"Sh?Òy衇Z_Ԩe{yGԵd]kǗmj uqYU?٬o7oKr2L2ERaʞ/.@>ԨlQ\(F+W2K1(!6r~~^b_ȉxe?ШF +J16ѨJs;lI50՘dˋ-Qx3ڙ9s&}ШJ+ڏb~R1j@ʼngHn hԼJSNQU'F`<>>YC2gթf;ШQ4*QШhT4>][4dVJQfI .WH@d>EO4c!m۶uZo<3ukX[[ШyQ<ݾӨ2Fu;kNnt3FhT4j2uVJbVSIΥPW#F;l6G>sȐ!f oud=hF5cQШ)iTk&"uRQLa`3,UƫZW^-G^}$bk( -JYx*ըj>XaijFpLjN34*5U[ިNUbC WBDDU%+Tk iTJF-ח-[3_[>"ܠVW`'ҨF ʗF5}Y.iH"iT颥YݴiS%_հkZXX(?FhT4j*ի5jՅ;묳sau3b;FOxW6l$I4l0)~4ze>… U0:YBK'IGKQ꽤y7G TQOXG<5QV-4*5Ujh^۶mkzZASM~ZM%ҨALfbդ5*գY UUWJ5ԯQfҩ|P~MQzOrbI:}4FաU#U7|O_+\uСCAШhTFMvSUpL=fVMQ-۪WZ.SSmQM1c"Cu֨rxdݏFuRѨmw]IԦMU F-FO?!Q>6iZ⪼4Wڢj|ʡg Q(Eχ}FNNu)JM>QS FMG8OT)Ju$ѨV'RS)qU^HTWU7C u+>.flNc˫W袋bW ˹%W`3Z>vZ)"SJ'$Ք1L.FUڦO>JAI,J z2%ʴV,G=#4ejTadRg}֬$OGQB]ٖDu{5pJOɃ_{ڀjTiN2EڣG>Fl֬Yf$y;JRo%Y}U՛Шh7 F]K3PШh}7]v3gfШh\$:=ӧOF@QШF@QШF@QШ {ٽ{Tr*z#O2{4Β?ȧwy#h,s/8sοo察^y38c̘1͛7?~ܸq֭ Tre>\4jg˖-Jj^ZϮ]%!Cݺu[dIf͚6mڢE.]X\4Q1]32mڴC~|hJ Q6~={FyW˫_~oF.]Zhqg;ǎ{ 7xoK>\4Q hyg;;o̘1~>ڨQ*UjٲG}G}竊JӦM5jx}k׮'+O\vF}`sdC 1"><~IJ{^\yd%{atwJ[t=B'Xt{LX/q=YI>޿&u':#A$?l; ɐ~IŽ$).cr}=IւIĒH.kD3*H2Iԓ,˧Tej9dHrUky%'OWU&CMdy.J4ÒrNrInO2[";+UbA4*usm۶)zqgׯZjg}yȐ!G6mڒ%KϟWϜ9SJ.]<\s .EQ5W]uU-/^« ںuG=rرwRVT+x: >\4*Q 7o\!"޵kצMԪUJ*$|R֩SO hܱgHGF4*ШFeШhT@QШhT@QШhT@QШhT@QШhT@QШhT@ hT@ hT@ hT@ hT4* hT4* hTHO>o߾W~mذO9|O?;޿ShԨш#N><veUk#'xȑ#}9gLvxg<;]ZNvs䭩b|>gKB̙^$+ʜ~7'n5UA; ڵ?ݻ=rsܹsyٳY^B|^Rm2g3Ͱc<8_hT4*?TZu׮]ɟSJ;wbyK23x9,yT\1;f< ]&y8*Ϝx ÎF4*x Î ;c9-ШXXg0hT@ϰc<ÎXFEQϜx 3gv4*Qug11ѨhT4*Q3ϜxgѨF0ax,x,GQ ^pe-^NUD19v4*dsvޡZzE19v4*dfm%Q:3 ;3ϰQ hT uc93g09hT@X`C 9#5j4}]4H>R\\\FQeRkѨhT Rrg`j޼ĉ{쩳OGݴi?{Ԇyoɢ9${όܽ~zgG^ CJ0bz֫[.Feg0ϰQF-ZN:16mQnUQRwԨQRQw?nqϞ=I捷vnSZwOoUKzV_kg*(P7v"gm{ &: ZG8 :3Ϝa1aG[̙裏Μ9SEJ=9o޼c Sb}a?Ш ` ;c9c9hI&=쳦F֭[$V Z "?ßz馛;<~;jԨ|w}I'l/ԩS7nإKoJ*|09ðc<ÎXF ֮]ۦ^eXSR:z'H];ԫWWUݺu/_?|޽{u]{3f_~9.g0ϰcu3gvg1Ѩy*TXXFEQw;l֬/~ ݴiӦ#F3fE]ԧOu6lodݺu n"s(NH彃M̧͐0ZOHԍzO>9ONo'>JD~ĩ[-m{v e~O:`Þh}NG8mk6$'İ,t/e7}q?)װu?Iԯְ'>ΙP'ށ*ץ$ٕ}z?IBG.${H4Ny4ݽ'_GoD(IHԫW_$ ]JީSF_ _ oO<ĵk~۶m]cǎYc=&??omG wq{uJKH;o!'m޼9Kdw͔␺_TR( SSs/j5)X*)3J45gjw }=39'j*OZv}q?IN}Cd}~𹿟$]]ZK{Riܩқ3e5ɯ$/? QW^}7r-G}zYfhB]_4jS~=#+Vh׮ݤI:tӟT W)Vy?}ќ9s^xz\s|t*gXg0ϰe-ZԺuk֭F Q|͑#GnܸQ*;nذa3fuԑO_mڴ馛nZ|yʕ5j4nܸ?u3gvg1Ѩy-[,Yb>5͑ 5l~+V|v1Gsq5vڣ>OVB+JaÆM4evr4j1gΜɓ'O:Nꪫ_F 4jy!'ڵKu1ٹsgժUGv-2u3gvg1ѨyG}Լy[o3ܴi/cǢQѨPA5*` ;c9c9W`9stСt hT`vr4j̘1'9sׁ.[\Q 09ðc<ÎXF k׶i7BEߩS>c}E_N@/ШXg0ϰQ3SLYxڶmۮ] SQ 09ðc<ÎXF _Λ7OJSʕ+[jFMb}ѨFrg`,5ШFϜa1ax,GF֭gҀX_4*Q3Ϝa1aGf[0?*Qu3gvg1ѨhѢٳgK:qШFϜa1ax,G̜9s:tPXX8u5k4h`lԌ4IQѨFrg`*ШXg0ϰQ3eҤIz28q"gҀX_4*Q3Ϝa1aGfڵkW\i>r QѨFϜa1ax,G̢EfϞbŊ'?o߾”3F_|ȑ#AQGup |!a9c93g09ðQ̙3CSN]fM O޵kW4jy2eRQѨP 7 /%zBZ⊧z/$,x,x 3gv4j޽{׫WǏ_x[?*QEڵTE͚5|_H0119F6l؆ ƎF-/䣢Q/$,x 3gvgѨb}۵k7w\pVZQ ~T4*Ϝx Î ;5 IzW_} TШY`}~T󁙛Q>IF3Ϝa1aGfIz>^XXxzShT09ðc<ÎXF k׮\}?*Ш|!x Î ;3hT|T4*Ϝx Î ;EF3Ϝa1aGBhThT 19v4jXzu SNUV׮]Ѩi |!a93g09ðc<ÎF͔9sta…cƌU>2}VR3 ШY`dQE_HXg0ϰQ3{-[]v^fϞtR4jzŏF3Ϝa1aGfʌ3u&h׮݈#vگ_={wA 2D\XX(E˗O0aÆoaÆըQFEQ1ax,x 3g0!曢;~w͛7_paV;W?Ҿ}֭[ӻK;v,X{i۶-tϜa1ax,G WnРaԩR>j޼J1U٧R@S&uXJ/5LyO^3O|"O8R7>5L̒o)_~|fK>Io=R9SIKwG&=ODw^y? sK wsؽS\R$zr>kC}F_$zfs&I'ݔIgx{'-Hk4](ѻ'zo]1{e5W~AI)~XM{5k֬SNԨ:]v#Fڵk~*G4*FᆬKʫ /T+D>.P;v89w1Gq{Wx㍙3gZںu-[\ $Y"ԯ6ڵk,L>Krʲ)K,ʒ+դsџ {gh4&|ʵN:]YO)9߇x?>~HfRwD'ƥI\~_OR"s2C( eHkJjdէ*_[/p%e5jr!RJ-Z't{W9G2Æ 8qw_R Ԃ*Uq}kgϞ}/?>mڴ:ol׮Դhʄx*,x,x 3ga?&^%S?+Xg`]/b=muk7*.882kPԨVRo[f)1cƌ_||K.MGGE,x 3gv@Y/ T!y\{¬TѨhԩS{&גFXg0hNU:uX:˕iRgkШp[{&?j: >v={D/Sؽ%v=D3EiԯT%r:DZ("4*g1ax,xiWgQѶݥ/Tf'Ԫ^jzI|\Uaɥ+FUb*u3ϰckǝT AFx3ycͻx-K*}6ujTnwzz5+F]&܊1ᤕj~z'+5o`CP*FزeK5UuhQ4\("4*g1ax,ϖ^[?6mf_kRչV$W|ըkW;TYy]3v+7[XΘ1cC^sKI>*gШhTg1ax,Ϯ]W:-M!ekAFlTo.FiXc"IիW7jSΝw)),, /<0WաfGf ;3@oEec,牑^5V*)&t'K5DK7EZn]\\\Fݻlٲo߾BQGEQ1ax<U)} }KJ4{o$-P#m<#].Z'F-F=C|QF֎Xg-."z3j䖐{^[gQSҨ'NfRZubtLBQ1ax,xL><+(cXVzy{FkTscɜa7'U*I)k-[,Y>5]hT4*3͙ Żh=%h$RZ[!=Vl1dTr=^LF<^(YҨt_{EH[q;5ѨSQ>j&?* ;3O|}laب]R_y~ $CJ%I"V|<k&IumFuy;Bz9kY>j䣢QѨϰc<Îyhy!+7mۣZ͚CukT90[z~%LO?^("wj}9)-D;rvl QѨjTQѨϰcj7>xi4\Z8O{#fKDR4nb5,D,1{\3m<#QQѨϰc<Îy qH#W9MjP֡J\J+3>vp; %߼e7qPGuШF ?* ;3J|uRy*JzdQ"ȧiGz\=g^]:o߬_?JEZs\riWQ!SQT4* ;c95hҸޏ WHPPA9>{;6G}8f~V9ݰd^n (_kۯkc/*>J(VkX?Q!SJ>*X;b93g09ʼx}sOtz6/?a W=I9.n׈J]Z((m:sPqW ajy}<Fx3jdF/US[L á7~,2_\r^^k?rsdyfLkΟ<.,/ѨRm'D6F5jF5菊FEb<Î k[v/m{ūZ+>fN)5Z(=RXijTKt,p%NfsvE鑙:skذooyuprDC*hvO 2RNsDK(R ~5+2ը䣢Q/c!L8պr#ʮ`ricU꤀FŸis,s%wƣQѨiTj&QѨϰc/Kd^|֝dU>huV(ᲁ~3΢tENtBM̥XQq;xO:3w5,\r&Ѩ5`tga{ͥU󱋨w㱾”n/Q3]he?̙n7NJ-Q7>"IXz5Qr'Tkw5ZUk0woƩypM/.vB;@x|'I2b)V׵ߚ3{jԿr{*XaIW74?jb{ѨF󨙄F~ԩS֧rE͟jժ~|pɒ%׿nz駷jժRJ,|Ϝُ}/Cn7T-Tֺ޵֫Ֆy1?EK`bS 5*852F+AJ$\v#̪)Syejt)˱ҸA}\Y~bd!{Qnll17޳䵹ˡjn3{} [L7,Z_|yaaC=԰aA 2DU>skn„ 9yQ_KCGLU"Zݻ2eȑ#^|_xqժU7nxꩧoЗ_}yתUK>k֬ _3ga졕R t3OO=^K4Cfu ;C/P9){O^y#1%N9J)&06g.ŜHFf24:Hi2b4f.aد* Zvu\Q=.=S:]ЫB79c uaZKF2۷oݺwv7|Sвe˾}ϑ?ԯ__ּШLQ⋇zo5kֶm>~3xG/w?ϋ%<3*U5j$̙xuV ܥtfjҾ4E?ntP v_t/tNs Z)S2Sih0\V ?:DxR F``spw_EȼQg:H;,..nѢ2#bbϩQQEf+V̜9e˖m۶U~?P^}ڽ{>mڴYf>|Ʉ ~EEo`"G+I,9+<~T˃uu%xėЋ?) && qM59N%R3)̘1crq,%qHGQ¾qs#:L'^;׼J#n~}VVBVIu۷׎֨>q㮼7o{ҥKKrmVB7N P~)nfvq- GJ -lz^_6=6<'d, 갯Yk9 OAODC߯38e\v?ט+џk|yDZzR)9g_fK&Dԇ\wꃿxG{}uۂbGҰZ)OͥG?xeHx&}yOr?It J.#6ZΒ=yᎺucW$#Ӯ/o5n (} 帅fZ: '|`_[72-u3I>s:$Ytdn3po©Rۻxu]9„]Y!w$! Ш_%A}Q'NسgO}f{{ÏF;FOO95 jܹ󨣎9sرcTOc*g~]}Wgۮexɿիh~hs]$a|ɳ9pڣ䑻[N~bM!g5ڦK(Zsr؇펨v^VcR$?4>Doy'Ტ/Fx?I4;gGLIZޭsmfC{Hs7K]{1O$/ֽ^);t'or{7|GXϬ]t ACf֬Yݺu%E}G%Ei$wʤKG]{ijTj&QkTUWҋ.G.].]:mڴ_~yʔ)UT䓇ƪLr+!#&"k]H{f^iFaupG.KEŢis+ 4K-TY}sbFQVS~if4nl2ڷVZ8旰 g:n3iWw$X3I2Š6y[Z#N4]Ա%b}!5LBz5+0`{סCŋ~GOk9jժ͟?_>Eo`8mڴ7ػѮ]ݻEo`>S֡d>7/Ms_`ҊhT(ew{&?*h|+c~3g:=jC/OMԗmPFUkG(FӜ70V톢E]I>"jk Xs xյQ$B'ԩ y%{sMF5K"+[(ƒS\}F\mi&AQ^ohT4*3ǖkxmT/)yhJSE< ©e_Puw{!ik@Za4 SƎf(j~;Jk4NgZ4`n Es$4j>sd䣺l8!dí#2 YШR3 Fxx#dcr[#(|H5Zj9Y1>=_LDpYҖaԿQ[:ʉ`XoЃZ-3?bmjfiU7VhnOMt,#p4*5|ThT4*3z$P5Wwˎ|uG-LHUk4mp! xV}eN=a uXRpuXގXHXp<\q!=Cr.u~72g9㭥l_7{͏on\Iz,^aou}ѨhT4*3Rrr5w7uoQ+1本Utiwe_׀I=wᛤLJȈt=Wo'-"CLz)* b9viNMC,i\gME][L$G Dnsc#h1jFmf) ҙN>Q*>aLK3 I5X_4* ;RjQ˯/(qupG.%ץ¨ebc h‰ 6wD";:ZQAasP25F0ZOb;nn{Ϙ;2"Y˖61m>bL2]JU X% n7eШhQ=FEb<ÎA _[Q *y"Lèe"|oDXzC70{E]y$:jlVJ¬kI^{պ3.&(LȾzujAN㨄5XQ ;PYkX PY;Z5QU> FeɎ ;buFBoKvWr[=ZLbOG) 'f31eNQڧZX;GS<ץѻśOksQu2*ᥕ5Μ0rg^o̭4j}il 'DdZ/u}ѨhTg1>7^ӹ6Q Vazu1iA!XߨhI'FFmrU5LkmF<)O'1R.='[W9J >JG܏ CN`F0&$N2)dűFR2;CX_4*vs:`ge<Ύ(-UW%ac}BSqg2F]_S@$hԯla=FaPh-+Ҭ#ŞH~ΘN0h 0Gš3@*"!AWKO` Y<x{T8LBv4jh1M*QѨ,1a m۳d?DZ ת^9,/;[)8S 2YͩfP:Ļ7p~ˉu r[}ٓ}v)z|+ۜ A~ ?mY2-C0B ]< J]_WZRU.XVFU5?*hT4*3/87JCkVzWճpgB Ff"5j/|m%r@ݧf$+QzQk@I%Hs<>"IDB[X{XL ztNՙ^ȃ9[<{a֎%"a<;ҨG` ѻ! nGQ鏊Fc|w~dͻEF;_ieGmx^4\VUk49C*ȥ3Eii7a.b~Ts,!sVQcdjbDlI𵕞pqVI(Jyj3$k8Ζ _ $ on9\Y&P*~#ﰻt l?4Wo/PwCgGCq e<}s{CHjmG:n>Ҩ%=X_ȆF +X_4*Q=5&oЩ^;sVJ\G*j 7%U=2qi =5#czC$=#%׈]I|2 &.QSR1lÕKdž5`]Px8=uHv3:B"vuU&֝'IcεFufFs3<5&2gШhb}FEb<^kGa5:Yz\7)*H [%o5o0a,NT3)@QI'IFn=ܦ韉UC#"Fug0\LNHB-h#p@aOLx0߈lX4D\xtee FKfQ=X_4*BjEŜv`[okߜ2$4 &vm 1dFb5Qt8€G04a*b؁KU%Ө&|eKז69vQӬ@ n̻l5_X8&#|3'khT4*hT@,a9Ƨ?3 +'2 ?J9"B|#" _b=vh l5bŇ|>1/:d@ͤdrH7,vFYIrԂrŃATx:.PZ{C)Q_Qh!"4+<2B{'Gz_4*QhTϝXعw@CKGY\""Չļy®ZiWfRD]-1!,|#iR:rK9H_n:H$usRU aĄ+ՕEV=kcs 'ݓvfJu~K9f[CGuw$z75w4*Q3GEQѨ {rۖV!FJ{pAyQٮ0g.|Z&vz[s _ VՎSgoV䨹κP'-"M4k$;InĬGϳVx ~^xOkwl\Lm'n0l۬Bav-?^*Q=F4*o_yHqY:[wn|ݧ?&dR|!'ڴz\Ĕ H|FZ4˫ k-kDBj5Gi*JsZ!וysI%{]Xpk' y? gxO ;X_;uٚNNpe&J`$ag"/lNx4*5ÚI{{>MFlػCHAWgc {Gli G%Flح^Z$,1r3BL"fo29-4[` =}ħJ}w˜.&Ïu˽Xj);F t:dz#R@[47L Ef ͖\+5u}}QOvR'qqdI0o& qgmkF\GEQ1a/5bوSQb7[J۟"Hl$u}g,pP)y;^5hw#{5j(q8#P۫XQ@z]ZQ'1~=!"Ͱ|Wx覩u2պrC=  hx OBDXu}#f`O`g;~wJ4*Q<2n " cЇyMq5 {涙 wX_7\;FlOR>B4U%n'SEf"a4%3ƳDHrTdLƦE@ͷCnxkk 钳!QGD\Ƿ }H!/`_$l NQA3|;CѨӤi:ZXX9`]?p;33`p01Q3rvQh0PXb"*Wl5+b=5Z2О`7`y^o_@0ƦHR!,0n[oV831A*G$:3>vl9"ISQШ`0|֎;/F  {-F7fP;*z'a9: _!bfDXnFPŏ`hlG)!m*';KfFZ[)>7]rLl_/"fYZ?>\iy /DQ_p~4oʟLk;N-4{!耵Ө^Aߩ4jI`XyfRQѨ[~۷ؓ9Tc8ro6'pk"e~ڿvx@c$L]涏E0$/AJOPJUbne-|A,9Nu̥0˛YN<{*ui c(;$9"as#sS7u7KyIsΙeV7W$9dX 󲍗rǏ ШďFEQ1> __h>\O~32/.3 qIdR3NZ{|k/-'BIp[sY2xi4*u/aL"F׎*Β()|hTkK7JՄf]G8z"׹NI=o+r_7fw yO]ay7>I"ySB"fs/ϺCCEր =-|D85ܻ儷E{{8M.hj#[y ШF4*2@Ө K@H[ R)XQVl /쯛,9o*^os6Nӛ6m*~c8/xДܑq˛,{I1Q ˏ]0u9}7F;b9} a$D2cw1Lp#)MF_y`I`_`04*dAn24Q3D>*z^Vd'{s^YC[Z&j,-cJ{U\{+X{Ϙ4|@b}l :X24Wg} lFaXQ(8yӻ%}yu~"t x)u{iXA,$Q#݁,m'}"A*Jx!&F{tFlhԿLhT4*ƧUꉻ3"_f0RHy<1#zZ|hVr8FEYᄴ%"#0\9}|-F;%fHǿwQA=P3=c'Fv2Vz/U!/\nfQ;2I.;J>1a"A&%wO>F_4+wi~LQG7.|F\ E(jYx7R`XxW\&<]"ր:Y{eɃ].Tv@20fzh92L}t+3pQIn74/@F d^!`f@ţM9a7o'7"g*^SLwVC> 4Fϛb5Xj&FEb|ZKv!̕sP\xE!YeN=`"IˆN:k!SGo YHt"#Nz^%okD n`->"^܂$5Bm Y,AͤLYW5ytQCC1k\v_4O+9FEfI>*hT4*ƧqdP`lgY20 >pQgDf-7܈`G] RqaQN־wJvD͖%U :jlWkqv>0|b.yn -4ቊW[Kޜ1zه*L\ ْ0}Y,FEfI/F -n{VgW4:Zj~ܹMo4S:Jkpp_飖&i}@gh@4lvaLb͏@Ke ~.wKIˆp];jܦq >Y;*s>(zk7֨XV/5?a:_AW㰎?'F5VG"Awq > lj_ FnW'J8OG:sqՒ5Y`F]xr@r֡9g\Mor:[V>P8ʪ/U x$=7L5g}XqܑFYsK'6ڷxc}C+|95&hThT4j_Uk7N29UԮݍ{ [$X? QaC;N K _bd|ڻjp{B XPm[,ԒF$,DzOϭHXRĎuKGl#V{J%q!o@0:]/OLxD8wkԜWd`n;s_vvzgJ^4[R~Hj@œ~-S!]j+!:!·;Koj;m4*dAnˤI?{FEV@ X:Q;tM[aNt ʓEΙްpJ:ql"殱't:vAdu}gfzH2} E.UT1r ^~T_{8ѽQ,B3FBݮNL_F 6A!&DÏ-ɴ— )xOӒnxsqw_)r9eK6 GrcШF%F5нH牙 ` `wwjFC)sjI#7-з0 jX6]K\h5^c"@cSƓOfbdEY(wTLtw68RkZ&ܔq"CK;|07̪M3q?'SXwo 񐶓1m `1Nf06Vzn}ں3 (q$5`9Q^_K {-'8y"<ږ(u)wH`xIwKeS,y{V7UڷJg/.L(oBsc"QS&uXFf|[ʕ+7m԰axc Q^֎VpwҒo 2:DCٯtߥaVJx6 &: Fd-VTi.!pG'pè*Wz?[qD*of!ոI _ȇ]ѨgSJ=?a v<<Ɔ̓ɿfQ+F%Zaq2Ck6 !ݩ%2WW 2R 7v Sos_exW)fN>kE B,~T7SW:h pEX&/7 KڽgvC JpnkKCƌ>ڌI}%_[:>*0MdguZ>c;=^N4ng:ZS>fdg<#z@QëFEnݺ5n??ӦM7o^UtZ_ոS"^BxlCs6#9oX ܉vH/}$_1#T[0'LQt(LYYglls}HYn޽{˟_x{O? QᲞfJgFM=kՙPҩHOSBUpV]~}ډ^>pi][h@N9#"ܞ|Ux r_{ ,lwծ7hQz>cWp "᢬Zo8"&ӚSYݥ_ خ<i2"M+Ƚ5B[օK&J ̼>{{>R3 Z^ڶm۽{[nE<}rJ9ߖ غwOnٲe$Roŷ?۪3gvUXr`*c36KkF=MH*5B-%=O,yw 842?sSϔ]%e{I-,'֯)Nx}?)y7y4O߼F̘ݟ$w]|a3K"xK\gtsRx/^%AH{nْa wؓNwیoے:~9^ے_有'YM AUD8mIz&wo1c7LaE-&wl˵94QCm\T,4*t30`zg|ӞB3g[!ZfM%#re*\<_w}?-({}=vGPoQ7׭e.K؄}GQDNO˔Kְ];ROQ?+0 ī%EY3S3Ѱ{ڔmrjkG5n(wθ1V(5UG 8IASgw,$n7,V_56RO[yw{~hzk璒)^{veԄw =U?yL:uְ' ivvaky4j+}|(NceB{սsͰ㏔%o)K5I+K~3WMjo8eg﫚/޾Cz0ƞL\ XUeŘvOxRջwh;/첎S jLE|pɒ%O?tʕWJѣGK\4Q3G$֗|T4jyuzR9@B9x饗zכj*$x*4#QP&{I7G?<黕E" znկ~OӧZ@oѣGu]k˕C=b 9[5j$V©B+ R{챿/w.2g}}r̙3{ɫW#ߣGy$gW_}5rHL\`RV\)oҤɥ^bܳe˖UVvmڵ6mwKfϞ]Q|D!C˶qCU5?^~_+Iqƽ{qi7ޘb#>*KΎ%lܸG9x]x)唐1?餓K]?{zӟ}*yjծ'S~e]6wܟhT@V$֭['/Ҳe*F_^KXҥˢE:/Oh.\(\T~wʵSO=yni?*rҡC<?ؼyը~"^SU^W4il)]~% ?sL?}r}R<<\mFʹ-6l؋/XrnA>Cy9r|"/#Fu]{wÆ &?syh~;iO9?Nܯ3ΐ|"TZ]w?<|P׌3~<4wߕw-ZN>}>W^ye̙9gm֪UkV^yhSNEgZkժ%gٳ3 F5nʕV^ݸqc=T=CRr,\0?sN\P2DZ.׻r\f?(WrG.v@}g*JVdҤI7xcN^z{8xoU6h@鍷zK+ꯧzKW\qEZO>;co>s>{=NhР0W끇~X~UwqrڜwyyF@B9l)zѣG?]v@ŢH:tX 7pCK;vVɓ:{'t 4ϗ/_ޤI~3g>Tm9v-W`q[-?7|3,|Gʧf͚_'pԨAꍓO>Y˿xbXW\!/*WO?=p/J*o_f| xp; NbjѢ*$]^ sGg|׮]{ҤIvۿk˥]T!CyV;Sw7|O~4*Q+FX~T: A֭$rV!\>}lܸQڼaÆYf]{R֯_BߨQ;[n+&hݺsKu'בrF=S&LpeU|bR,ɏ_?묳V^-Ÿ~%0[l۷ z)YK@gzwu]+INV}v׍9B법s^^r_!E*!tV\)O-l...rHmyUʩ"//O*Utw ?v</򪫮SVU?뮻K.,V*_~c??W\qSOl,?/ئM4*Q+FX~/SO=sSUqWF~ҥ?O* 1bČ37ԩsN|Ϟ=r\tEr=?UV0^rA&ޯkAOa̙;cQ_~e);3_;wϷnAjTDJ_|1ok&yLźlͯ$ipV}ѣ:jڴi*#mVs_~gqzD]vT ly #G}" _Yuw޷~J'c;vPvR~᯽ڹ+pw?3׉'>ëWN~_s57p hT4*@Fi/0`\YkNO?ӯ~Zj;v۶m7n|RVZu͚5+W.**[n.]Gj 6y֭+..TRzA#_~eշlR~۷7ڽ{w͚5;04>@lܤ߲eC9䭷޺_z%Q|𫯾0a? &[PP 뮻=S? 3F^۹sO~{4*~K/uΜ9?kժ5o޼;I&~g}֪U#G?6l/^,_|!=餓~uiӦMy?Rٞs9vZTsOΝRUmۮZJ]K/"|SQ`/An]??]v?RJC׿޲egnݺF-뮻n(Aiԏ?8[TTta~8_~<Ԩ~iӦM3a„cǮ_zǤpS4*eذa ,x6lPPPK/S?Ȑ!/… |w>쯿馛GiTB<78z)rv]֤:c9䐕+W6jH<|Ւ%K'쫯ʧhT؋[n߾o!Jq?Ν;L§hT˶mN9ߖ׭[ /_G%e={|'4irW^s5;w-,,B[nT"Խ'|yT _)_xݻwxN;OШ*;w,..[n/ٴi!RjU_Gy;4*ШhT@Q F4*ШhT@Q F4*ШhT@Q F4*ШhT4*npY?7IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/body-editor.gif000066400000000000000000023771021515660254400234410ustar00rootroot00000000000000GIF87a<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ! NETSCAPE2.0! ,<! H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! !1"2,:283*93# 558C><3A<,E=$">6JE:KE3GF?GMWO;TPD7QM#U[ZUH9ZYc\Jb]RabXldSmj\Glmsl\xsfUvu~ykg}mMS]pw>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$: .,;C;w;"Ѕ~g;rM>p3اḌM,̣A%N(T#t4>{ҟ@|@?TA{OG@N>7; 3C $+8c X`-ͣg;䨣34$=OcN~.*<! <8@F>y AOwxS&z# 7ѳ"v!=Jk9cP6T)4׌ O'_cJ -08-pAM8h"$tuР#jS/ 4$?0-H 8Eyਁ@=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk>Ȱ h 60 >G.58#  =I#$2/*2& 62 R1 ,|DmM@kH3L> r. \)Ks-ޔҋ; 7Hd }A A¥҉ }3 I=,1>9,= NyHyB OBOs%!s@>TЃ.t;x&r_BQ nw(A3 }`xD (7Dozb6Sc?=J |VPJ@/P9x9,$VC?Y){=ф*as 4S00J0B@ Fkn!3P(#+p=:R/ fQ|G L B#o`1#"9l!3[YQXaLBcLwl0—&H48R+Nd6VL̃tD B fh=!C4Xh {p, !p@$Ox:x F J @BQ rA`TT;KhwXDp c >M5w+K$rdtR~ - 6z!Dvf6ae*008b*h b@jBGtQ!e>`~ `~)p${'@tP ^Gd0ZE aBPr(,0 ڠX@dr,p>dJTTGzD0#;   2] 8p# 1jQei)LH$C#Vze \ׅFȊ:`~cp>ipQAVP"@0 r4l0bPpd`mu?D3Pϑoа#eXGcH|w 2] Pf1  OA r Z·0!PSH$^H1i o0@|W(u!7@ @pr@A{12 '" ' 0lD!=qO -d 0 `h6!IPb p0 :`) ~P]!ć E * D8]pi5h:. P 'x% ,Hhx)&]!'0 `! E*& %7j0(_0^! ]eq 2(&eXq 0XCww @ qPf`zXf0  'fY ppБ?*5 #Py[ #P5: `NZi$兞 ` Đ0 0 qR ŰIM Y%qIۄYհWP ,gkA ^ ! 3#   1(ȚǺ!# :Zzj ʰ* J Jٺڮ:Zzگp ۰;[{{ `{(*,۲.Ԛ PP`j B;D[F{HK2+ppbI{XZ\ K˴ ]{hjiK`fl{xz +q;`|[{{~ K;۰ r ۹۰ rۺ:k0ຶ{۰;%«˰+Ûʻ;;f˼[֛ {{+Λ[˭c+ ߰?;zA˿\Z l{L @k:Zڴ`Sk%Z4\4<8{*ee;ꬺ#>`cO:qW]UĹqXL*$bFd)!$1X&en\MP ǀ IȐȕ reQR@ P`OI OB `@ n P  RI,:.Wr" |3'o87;g   ǐ@ Ip Ġ @ BPZ P n ݐ 8{||i|`G}|  ˮ`QJ @},B@ 0 5QXӘϺ!R 0 R`Z,B QӠ  `;(9[K R R)^ J/ *kk KՉe !i|}`@ pˈ O =P#h=٥F5( 0Ɖ V(TñB@ JJс= tAmM#v` Kzग QnM Đ; }^ၬR#՛} ! `[!02>67<@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>;! ,<! !1"2,:283*93# 558C><3A<,E=$">6JE:KE3GF?GMWO;TPD7QM#U[ZUH9ZYc\Jb]RabXldSmj\Glmsl\xsfUvu~ykg}mMS]pw>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$: .,;C;w;"Ѕ~g;rM>p3اḌM,̣A%N(T#t4>{ҟ@|@?TA{OG@N>7; 3C $+8c X`-ͣg;䨣34$=OcN~.*<! <8@F>y AOwxS&z# 7ѳ"v!=Jk9cP6T)4׌ O'_cJ -08-pAM8h"$tuР#jS/ 4$?0-H 8Eyਁ@=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk>Ȱ h 60 >G.58#  =I#$2/*2& 62 R1 ,|DmM@kH3L> r. \)Ks-ޔҋ; 7Hd }A A¥҉ }3 I=,1>9,= NyHyB OBOs%!s@>TЃ.t;x&r_BQ nw(A3 }`xD (7Dozb6Sc?=J |VPJ@/P9x9,$VC?Y){=ф*as 4S00J0B@ Fkn!3P(#+p=:R/ fQ|G L B#o`1#"9l!3[YQXaLBcLwl0—&H48R+Nd6VL̃tD B fh=!C4Xh {p, !p@$Ox:x F J @BQ rA`TT;KhwXDp c >M5w+K$rdtR~ - 6z!Dvf6ae*008b*h b@jBGtQ!e>`~ `~)p${'@tP ^Gd0ZE aBPr(,0 ڠX@dr,p>dJTTGzD0#;   2] 8p# 1jQei)LH$C#Vze \ׅFȊ:`~cp>ipQAVP"@0 r4l0bPpd`mu?D3Pϑoа#eXGcH|w 2] Pf1  OA r Z·0!PSH$^H1i o0@|W(u!7@ @pr@A{12 '" ' 0lD!=qO -d 0 `h6!IPb p0 :`) ~P]!ć E * D8]pi5h:. P 'x% ,Hhx)&]!'0 `! E*& %7j0(_0^! ]eq 2(&eXq 0XCww @ qPf`zXf0  'fY ppБ?*5 #Py[ #P5: `NZi$兞 ` Đ0 0 qR ŰIM Y%qIۄYհWP ,gkA ^ ! 3#   1(ȚǺ!# :Zzj ʰ* J Jٺڮ:Zzگp ۰;[{{ `{(*,۲.Ԛ PP`j B;D[F{HK2+ppbI{XZ\ K˴ ]{hjiK`fl{xz +q;`|[{{~ K;۰ r ۹۰ rۺ:k0ຶ{۰;%«˰+Ûʻ;;f˼[֛ {{+Λ[˭c+ ߰?;zA˿\Z l{L @k:Zڴ`Sk%Z4\4<8{*ee;ꬺ#>`cO:qW]UĹqXL*$bFd)!$1X&en\MP ǀ IȐȕ reQR@ P`OI OB `@ n P  RI,:.Wr" |3'o87;g   ǐ@ Ip Ġ @ BPZ P n ݐ 8{||i|`G}|  ˮ`QJ @},B@ 0 5QXӘϺ!R 0 R`Z,B QӠ  `;(9[K R R)^ J/ *kk KՉe !i|}`@ pˈ O =P#h=٥F5( 0Ɖ V(TñB@ JJс= tAmM#v` Kzग QnM Đ; }^ၬR#՛} ! `[!02>67<@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>;! ,<! !1"2,:283*93# 558C><3A<,E=$">6JE:KE3GF?GMWO;TPD7QM#U[ZUH9ZYc\Jb]RabXldSmj\Glmsl\xsfUvu~ykg}mMS]pw>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$: .,;C;w;"Ѕ~g;rM>p3اḌM,̣A%N(T#t4>{ҟ@|@?TA{OG@N>7; 3C $+8c X`-ͣg;䨣34$=OcN~.*<! <8@F>y AOwxS&z# 7ѳ"v!=Jk9cP6T)4׌ O'_cJ -08-pAM8h"$tuР#jS/ 4$?0-H 8Eyਁ@=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk>Ȱ h 60 >G.58#  =I#$2/*2& 62 R1 ,|DmM@kH3L> r. \)Ks-ޔҋ; 7Hd }A A¥҉ }3 I=,1>9,= NyHyB OBOs%!s@>TЃ.t;x&r_BQ nw(A3 }`xD (7Dozb6Sc?=J |VPJ@/P9x9,$VC?Y){=ф*as 4S00J0B@ Fkn!3P(#+p=:R/ fQ|G L B#o`1#"9l!3[YQXaLBcLwl0—&H48R+Nd6VL̃tD B fh=!C4Xh {p, !p@$Ox:x F J @BQ rA`TT;KhwXDp c >M5w+K$rdtR~ - 6z!Dvf6ae*008b*h b@jBGtQ!e>`~ `~)p${'@tP ^Gd0ZE aBPr(,0 ڠX@dr,p>dJTTGzD0#;   2] 8p# 1jQei)LH$C#Vze \ׅFȊ:`~cp>ipQAVP"@0 r4l0bPpd`mu?D3Pϑoа#eXGcH|w 2] Pf1  OA r Z·0!PSH$^H1i o0@|W(u!7@ @pr@A{12 '" ' 0lD!=qO -d 0 `h6!IPb p0 :`) ~P]!ć E * D8]pi5h:. P 'x% ,Hhx)&]!'0 `! E*& %7j0(_0^! ]eq 2(&eXq 0XCww @ qPf`zXf0  'fY ppБ?*5 #Py[ #P5: `NZi$兞 ` Đ0 0 qR ŰIM Y%qIۄYհWP ,gkA ^ ! 3#   1(ȚǺ!# :Zzj ʰ* J Jٺڮ:Zzگp ۰;[{{ `{(*,۲.Ԛ PP`j B;D[F{HK2+ppbI{XZ\ K˴ ]{hjiK`fl{xz +q;`|[{{~ K;۰ r ۹۰ rۺ:k0ຶ{۰;%«˰+Ûʻ;;f˼[֛ {{+Λ[˭c+ ߰?;zA˿\Z l{L @k:Zڴ`Sk%Z4\4<8{*ee;ꬺ#>`cO:qW]UĹqXL*$bFd)!$1X&en\MP ǀ IȐȕ reQR@ P`OI OB `@ n P  RI,:.Wr" |3'o87;g   ǐ@ Ip Ġ @ BPZ P n ݐ 8{||i|`G}|  ˮ`QJ @},B@ 0 5QXӘϺ!R 0 R`Z,B QӠ  `;(9[K R R)^ J/ *kk KՉe !i|}`@ pˈ O =P#h=٥F5( 0Ɖ V(TñB@ JJс= tAmM#v` Kzग QnM Đ; }^ၬR#՛} ! `[!02>67<@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>;! ,<! !1"2,:283*93# 558C><3A<,E=$">6JE:KE3GF?GMWO;TPD7QM#U[ZUH9ZYc\Jb]RabXldSmj\Glmsl\xsfUvu~ykg}mMS]pw>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$: .,;C;w;"Ѕ~g;rM>p3اḌM,̣A%N(T#t4>{ҟ@|@?TA{OG@N>7; 3C $+8c X`-ͣg;䨣34$=OcN~.*<! <8@F>y AOwxS&z# 7ѳ"v!=Jk9cP6T)4׌ O'_cJ -08-pAM8h"$tuР#jS/ 4$?0-H 8Eyਁ@=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk>Ȱ h 60 >G.58#  =I#$2/*2& 62 R1 ,|DmM@kH3L> r. \)Ks-ޔҋ; 7Hd }A A¥҉ }3 I=,1>9,= NyHyB OBOs%!s@>TЃ.t;x&r_BQ nw(A3 }`xD (7Dozb6Sc?=J |VPJ@/P9x9,$VC?Y){=ф*as 4S00J0B@ Fkn!3P(#+p=:R/ fQ|G L B#o`1#"9l!3[YQXaLBcLwl0—&H48R+Nd6VL̃tD B fh=!C4Xh {p, !p@$Ox:x F J @BQ rA`TT;KhwXDp c >M5w+K$rdtR~ - 6z!Dvf6ae*008b*h b@jBGtQ!e>`~ `~)p${'@tP ^Gd0ZE aBPr(,0 ڠX@dr,p>dJTTGzD0#;   2] 8p# 1jQei)LH$C#Vze \ׅFȊ:`~cp>ipQAVP"@0 r4l0bPpd`mu?D3Pϑoа#eXGcH|w 2] Pf1  OA r Z·0!PSH$^H1i o0@|W(u!7@ @pr@A{12 '" ' 0lD!=qO -d 0 `h6!IPb p0 :`) ~P]!ć E * D8]pi5h:. P 'x% ,Hhx)&]!'0 `! E*& %7j0(_0^! ]eq 2(&eXq 0XCww @ qPf`zXf0  'fY ppБ?*5 #Py[ #P5: `NZi$兞 ` Đ0 0 qR ŰIM Y%qIۄYհWP ,gkA ^ ! 3#   1(ȚǺ!# :Zzj ʰ* J Jٺڮ:Zzگp ۰;[{{ `{(*,۲.Ԛ PP`j B;D[F{HK2+ppbI{XZ\ K˴ ]{hjiK`fl{xz +q;`|[{{~ K;۰ r ۹۰ rۺ:k0ຶ{۰;%«˰+Ûʻ;;f˼[֛ {{+Λ[˭c+ ߰?;zA˿\Z l{L @k:Zڴ`Sk%Z4\4<8{*ee;ꬺ#>`cO:qW]UĹqXL*$bFd)!$1X&en\MP ǀ IȐȕ reQR@ P`OI OB `@ n P  RI,:.Wr" |3'o87;g   ǐ@ Ip Ġ @ BPZ P n ݐ 8{||i|`G}|  ˮ`QJ @},B@ 0 5QXӘϺ!R 0 R`Z,B QӠ  `;(9[K R R)^ J/ *kk KՉe !i|}`@ pˈ O =P#h=٥F5( 0Ɖ V(TñB@ JJс= tAmM#v` Kzग QnM Đ; }^ၬR#՛} ! `[!02>67<@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>;! ,<! !1"2,:283*93# 558C><3A<,E=$">6JE:KE3GF?GMWO;TPD7QM#U[ZUH9ZYc\Jb]RabXldSmj\Glmsl\xsfUvu~ykg}mMS]pw>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$: .,;C;w;"Ѕ~g;rM>p3اḌM,̣A%N(T#t4>{ҟ@|@?TA{OG@N>7; 3C $+8c X`-ͣg;䨣34$=OcN~.*<! <8@F>y AOwxS&z# 7ѳ"v!=Jk9cP6T)4׌ O'_cJ -08-pAM8h"$tuР#jS/ 4$?0-H 8Eyਁ@=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk>Ȱ h 60 >G.58#  =I#$2/*2& 62 R1 ,|DmM@kH3L> r. \)Ks-ޔҋ; 7Hd }A A¥҉ }3 I=,1>9,= NyHyB OBOs%!s@>TЃ.t;x&r_BQ nw(A3 }`xD (7Dozb6Sc?=J |VPJ@/P9x9,$VC?Y){=ф*as 4S00J0B@ Fkn!3P(#+p=:R/ fQ|G L B#o`1#"9l!3[YQXaLBcLwl0—&H48R+Nd6VL̃tD B fh=!C4Xh {p, !p@$Ox:x F J @BQ rA`TT;KhwXDp c >M5w+K$rdtR~ - 6z!Dvf6ae*008b*h b@jBGtQ!e>`~ `~)p${'@tP ^Gd0ZE aBPr(,0 ڠX@dr,p>dJTTGzD0#;   2] 8p# 1jQei)LH$C#Vze \ׅFȊ:`~cp>ipQAVP"@0 r4l0bPpd`mu?D3Pϑoа#eXGcH|w 2] Pf1  OA r Z·0!PSH$^H1i o0@|W(u!7@ @pr@A{12 '" ' 0lD!=qO -d 0 `h6!IPb p0 :`) ~P]!ć E * D8]pi5h:. P 'x% ,Hhx)&]!'0 `! E*& %7j0(_0^! ]eq 2(&eXq 0XCww @ qPf`zXf0  'fY ppБ?*5 #Py[ #P5: `NZi$兞 ` Đ0 0 qR ŰIM Y%qIۄYհWP ,gkA ^ ! 3#   1(ȚǺ!# :Zzj ʰ* J Jٺڮ:Zzگp ۰;[{{ `{(*,۲.Ԛ PP`j B;D[F{HK2+ppbI{XZ\ K˴ ]{hjiK`fl{xz +q;`|[{{~ K;۰ r ۹۰ rۺ:k0ຶ{۰;%«˰+Ûʻ;;f˼[֛ {{+Λ[˭c+ ߰?;zA˿\Z l{L @k:Zڴ`Sk%Z4\4<8{*ee;ꬺ#>`cO:qW]UĹqXL*$bFd)!$1X&en\MP ǀ IȐȕ reQR@ P`OI OB `@ n P  RI,:.Wr" |3'o87;g   ǐ@ Ip Ġ @ BPZ P n ݐ 8{||i|`G}|  ˮ`QJ @},B@ 0 5QXӘϺ!R 0 R`Z,B QӠ  `;(9[K R R)^ J/ *kk KՉe !i|}`@ pˈ O =P#h=٥F5( 0Ɖ V(TñB@ JJс= tAmM#v` Kzग QnM Đ; }^ၬR#՛} ! `[!02>67<@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<! "&2*:283*93# 436<:B@;3C<*">62?0JE3JE:GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\0u}?O#5cv+dg{bVDPaK\Nzd6C=E`' 7Ou'adKCM˥dmW+xXS֝;Tm U }DjPB`筹kwڊ͎2ľzҿ}ŒÿúΣįŷlK]ʽʶ˻νμٿVuτНҫx׶~˱nƕːҦ{ԸϷ݉߾ݺyݬ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۭ%9F_Nt]?乁۫)%sΧOH.[?>GqWW8Y|$:.0;S;w;"Ѕ~g;rM>p3اDУM,УA%N(T#t4<{ҟ@|@?TQ{OG@N>7; 4C $+8c X`-ѣg;䨣375$>3OcN~.*=! <8@F>y QOwxS&z3 7ճ"va=Zk9cP6T)P4 ̳O'_cJ -08-p1O8h"$uР#jS/ 4:$?0-H 8Eyਁ@E=t &9TyFT W\Q۸O%%#7faWd)TPD/ *DSPk<Ȱ h 60<G.58#  >I#$B/*B& 62 rL1 ,|Dm#M@kL#L> r. \)Os-ޔҋ; 738)~чJ+3 K'*$$tCO'9 Dd#D ^ӃC,=45(2O;j#5ǁ O&H< >YTΕa>t =FЇ0Cu`"h`wG A(#J4D 1U@zȏ8% QMpP|P#A|`!%<Jߓ&Ts!@=Q"0ZQ0w4Z;w Ij-G 1}`)\; z$1p*Z:ъhChF#5 d@5U J p,'P@Tq3P u܂L3 '+&ȕ`bcYhBȌc` α ! P.ip`&QzdC𨆥 ~,En(-EeZk(1ѩLJ@.!rA =GB_= ZqBƽRs D7B ρ$@-Hȡ b&<ځ>DhDчLNK2&с\$`EBQN%:Aa"E(1I@QB dpJC-^A|:.`bE :(3l ߧԀP  pih07R;<lZ![ ,//l# ád唆| Xь ::x7p Nu   FP5-AA`XA(QGlz߶ 0x$hFy ! a>Ł DBp`YaC,'+(0V' $cgy7 5@h@1C @paoك]"|"=)?o0"U D  P `(V`JFCaD-BD 0NЀT - D"MVJ)e`~p pFkz 1OD{~`giW6p*018b*h{'bPjBGtQ p;?p~ p~)p$|' W aWd@[U aBPr(,0 X@dr0,p>dKdT8gye0zD0#; 0   7c`#qKp0FVD2t8o fe ^f:p~ep>'ir8QAVP'@0 s4l@bPdpmu?D3PϡoѰ#eXWcX|w 3] Pf1 @ODžA r q\nj@ֈ TH$`H3)i oPP|W)! 7rp @7 DtG+# ~r)qN B$'T ",@@ i1  ѐ wXѠ"j@P|p] nN faHbЊ b@ MYp A opЂ(@ٚY "k67]!"0j@0)@ ^Qp(`Y!pQ N&p 3*U& (,aQ@Uw(5tPp@p'eF Gev Ęy0zbPPFj[8#МPi[ # P4JW\i$P  PqR ǐIM~Y%qIܔYX P ,wkA v^ A 5#  1zjd@QZ00Zz՚ ! j0@ J PZj⪮:Zzگ;[{Kʭ:0 0;۱ "; ۭ  ${8:<۳>j * PP`ʮ T[V{XZ;BD{ p0 0)6l۶np7۵` xr;Kjpꮄ;[k􊮋۸;[Պ0 븦;붨 뷵«b˸ۼЋś{ѻ۽;Z [{蛾 *ʻ;k^:{Pkk ;  _[ p\QK:#$|Sk(&$.243|:;@ 7L4l1LR[<ʪھ 8c`pPjPt^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02Y?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhj;! ,<!"1 2*:283*93# 436<:B@;3C<*">62?0JE3KE9GMWO;TPDZUH-WZ@WPc\Jb]RabXldSmj\sl\VpkFrwysd{wjoyrv}tmMS]d>uCK\02u}AO#5+dwk{VPЕc[cK@b?HSzR2br /MLCd$:{m+ޜ?TxVhd7z wǃ@PPⷲh&}ηm2w²FöιļŗŷmƀvǶǿǺK]ʽ˷X̹̰̼qعTļѨӝԽxƑÙ֮q~˶ש˖͐{Զԃ٧ܻyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+%:F_Nt]?亁۫Y%uΧOn۸?>rgWb9X|T;J#.,;c;路;"Ѕ~g;ޘ>3PاD,ÎA%(T#t4N>xҟ@t@!7|Ha{ӏi@>7;" 4>M E+ِ8I UTB+գ;谣34$$>#ȓON~.ZN=쀈<38@a>~`OwS&z 8IHth?#a??:c 7E2P5 %Z +G9+8`C $s̀!rS 4"A 2  5Dy✁@a=w&:DyBTKW\!E޼O$%N6WAF!hb, Q9,lt``DXpG T,ǨB&,bЀ8PM $ 1 ӆ "B'@*`bL9 8/0;R+'eM7F<uQL4H(#)Dq:Da =84% $ ]C Ǹ})?\BۊN=0P=AP=,l]O cC0J>w ל8,$?< 1=MH>ΕTBO?Xȡ.u0C694l%DHv GG#=~'Z hx/ʁ @6CZ @p) D! ݄AFr2@A vB&A$^ a$84`\iF0@"G|hf0 X ֱ  P$(ipP& {l򠆥!!~,kH+Ec֓kH5aOL @,}CE'1HC8A+QBR4K@@8ȑ -y<qh!9w@d|75$:!&R>(ͯ~_2$h1|+RtdB{(ɀAxI⩊! 8V C@ႎrl GA*p/Н6 %!FH.@V vD!rmp:ހc< rEzb8 zOf<YDD("ZH8]bD#" P|~ t=hq(B2&Ž1<`$q9A<ͨp \x&lC ;64 JXA U LG40x N4Ⰴ`M|H, q@˷8(}: ~sAp4x#>q đ H 'pb6-dr b78! ҒC*.Dг :qPx;6pp7xJt ń vVʥ!VU"G/qYx߆q(%Px"xFy fx> (BjG`(8XAB c+$Vdȅ& 4c833@DFUǰv)Fpqxps`X 2F)y {`De6dS*\*]fPxr1GH؂ \W{G2`{' uOuu<&@U ($Pr(* %܀Ja0oǐ*)# ~R)qRNpY6< + Ci$E0 P' pq ХpIaM@ r6 Y%qbIYjJՠMOQ ajv$Xhe` ʑ%ZS̹ VahBʪQ! z ͰªPΰzڬ:Zzؚںڭ:Aګ㺮ڮ:Z:Zۊz;[{;zگzj̚{ [&{(*+*+2;4[6-/{<۳>@9;F{HJa KR;TC{E[Z\۵{֚^;d[f`[b{l۶nԺp[v{K+Jx۷~2ʷ[{ +J۸Z'0D{[K$۹;{ ۺŚ+Kk+* : {[[۴.*S1]꽺q[-k+a`$qb$*P$ၶ6Dÿ0 `p00 i)iK ` [K P@P b0 G LP+8Pp'q{ #Wrr0ܾ2Ā P` K @0S0LD@K ݋ <z{{y{ |P|j|13| ĩ5ǁ<ȅD >| @@  5"AzVЃBs 1Yʳ1W<`^ \I l p@p nji,@5ڣ|Lp | PΓ@k\#\8sljzOh07L 0p D 5bR+=!04j1=3}paD֫\Db@D=0lV=p  ]V -:0j b]гYqqPM `<<=|!|Lұ qټ! ]ȝʽ=]}؝ڽ=]}=]}>^~ >^~ ">$^&~(*,.02>4^6~8:<>@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~d芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~ #! ,<!2'72$b2n3/83*:3:3#A3 \4a 55S9F=FB=2F="$>6D>,sAKB+KE6iGfIKdIZPJ4RLwWq|<3ﵣ? Q]=b1h6;~CO<ԩ'S; ݳ>C ڹf~N>=;`;hB ?Ow&z:= %h?!2;ϗaA@7FU> 2Gs=VADbh9BaGT屓e< cyHL8a: Ū<10`*hEG D"+@yF2>1fCN3D$TTKB18A(&҃L9c9D{(@21=){z&*|kL1 ӊĎg<_9h?=-_ K#SE6aJ>|A@= -5 e cGH% PB׺;o \*D>"H/H\LN> 8VQ>z('z?r#HbRjG7%P]BWC.q Rbm2$R`UB"~6~B'懄zOS|!4F|Zn֏/?^FAJq=G?8<m*B(cL#1aDW A>pW@~BE9 _,{ ' 9A$pM?KFBx<)Tp@;= F0Ka!bq ` ?L XD`UhYD@>[ =NVa@'HCB8hw+-|@ DehD eXY<ԡ8 ?*qDA&a@eXG$ wh/@lҏi6'Qˣ㈥,e= eH`s c"4@,^5HgAsW 8Z=.tMItz O+&SKͬf7z h[$h1|plA]|%Zqt%T) "`p˞qd@m Q%J"dZP P~D xa984G{ HH"p}t?u`BX V}A}#0 T8Ci 1\xQP!@Q J`lw Pp'd)D/m  4cJD`pbшXgw &qJPV @$7 C s5)HZ}pp(Rr xgSw0 >6p㒐  'Uh"P pY6v !>-W@@N9eut8 m@@zW1e,@45R p pv #Sp   ''u0v  Й)78 9QU7x`_197HA8rhXA9`hr0ylUE.$EE>Gtp] ufb8eZ YX YXi Y ̈[h ڠ  ? ʡ:`":$Z&z(*,ڢ.02:4Z6z8ja9:ڣ@B:DZFzHJ"?ʤR:TZVzXZjNzQb:dZfzh]jR0> ir:tZvzkjwڧ~y* " |:ڨZj9a<ʦ :Zz*ڪ:zz: *:ګ-zJڬ:Zj zڭުZJ;=:ڮ:9j Iu ;[{ ۰;[{z꯸` $[&{(*,۲.02;4[6{8:$K סf + אJL۴NPR;T[V{XZ\۵^`{ Q]+ j+ npr;t[o[ dKf G` T@`[{s?±a+0  P րP g0b+ A@J[k;[{Rax r [ J2b` 2p5JkӀ 0 @ ;+cK k {蛾԰ Lv+0 `j Z*0pTu0`0{0@ Ap° оk{A0 = G l T+  { '-  T\V\$! +|40qp/L0 +Ik k$; 1^3S|ń\ȆY'l ^_,[s.8 ِϻJ>0ګ0L3 3 |Ȱ˲\< ѷ-<ـq z`= l{ %-@K LȵL 0zPaoŜYO0% @ % ۼ ݌<|2B BP ɀɡN0Mmk APb*= 6}ӳ%\PF60Z P8N=[[}۹봡 \"ԁi?d]ֱ !"[Ǯ{mmt]V۳?;Z0<~׀؂=؄]7z eס[؏} / ٜ-]`m&&P0 MŰ ٴ] Z)='p)L` PY=ڤ=ݽ- FY͢dyRjpޝ5+PP  -ߜ5޿}&P'ހ Mp= P\E+ :n-,* YM&P *` ϖ *⚅): ]H[@@NBYDT~QY/M ^^._>"z5dbtjm.prRh^^~ٔ&z؟Z/^ڧ$|.H/ 3 6׺Mם錣~ݢMg lI0F(''R `+q)`9  #~ߨ y10VR rI +|1 *풓Z] ~@)4Šdc}PzʨIha~ JvI)}V8}?. %~ ?7 9  g,_?ڦm2^ 7O4?(y}PI{IBcE>3~NðHJ. ?Y@07ao`[z22MKju%3ޢPݎ?,ݙGhަ"޽'ܰt߬o._mJ]zIoڕ>_ޯR@ۯ/֞N 4baA .dC%NXE5nhV;!E$YI)UdK1eDnӚ G-t$ZQI.e#MQNZU67v n=o'Yiծe)VqΥ[V)^ EK%O[ȑ%O]̙5o70&,2.YUfݚeαeϦҳkܹu o;$xq&fsO^}mٵoPuŋygx_}?Ep@ @g+еpÚg/L@rj"n.TqE2E=+;a!oaŒX`rȒd4! pH($E"ˆÉ3q)40`F)4s!*T=,'D&E?S4:ϒ1pĆǩ=5?# MLuv;+W`x` /j<dm‘%ƹ+YV(7Q R) gYq:zn\!oՙ }t5*tQGqƘ!ʹ-(ܛmݾ x+*f 7ݣo{ęW+bA|J_f 6pJXhDӅb? zzLr`X8`O++ 1PXxÌυ23q":!.&D$*E;D(.z"()wV;W%d"#?,~QT/jv3DNg_)!-!KkC#lt-rk .$i<(h!eCibDK\8@,Z@e e,<t&3YM6n ,Pe s 0 O H-Y$ e/7zMOu`8g(D)ԪI>e8(YNs1R'B0օ JcƱIMo"@!'z y{b! D*PFL'SVG5҄/x;`|e-] 5 .DvsY@Uy.aq1%.@Nk4i `g\S=*&&6T k_ CDvX5ֱڤBP j$l4YtW*j%mOyΖ7(bP mJ498v\ <̂ 0;fLӥэP!`$܄ Ax5^ un4.7lI:eЎ\k(޶=*;>q # 'y[%.$]zdIso߼7d6!9tC p({R>>:MGH-"HKLO" f4/<g9M6ɺ-oRƄ)@6/ƨ/ie Kl&&&h )g@@Yxq1䈩Pi-gBaf bA2E&R)(25d[~OaQvǖTO5C>ƈe7k*}aiwWh|=$35c=ͣ=7=΅~g=r?֨3اDc2CA%D(T#t4D>ҟ@븰@G:{"@8|w>CNҸ/aŠl6;"sP ~iOC c:䗨ӏ:M(҅>ӏ;O?$OR>R=7@,sCKJ(a;#HJxA;R$O((RBC'AZ cLsKbR5y]sO?x̉:r$nq5qǪqt< cIeA.˴C # `S%7JnEc 2"2PK>@7|9aI8߸4 t5#/,繃N|?QM5F5yD2qF8xg\ M,-*O3%U*LI"_Γ  `&c8 }B" GHSGh|TšD]8Cg y.X!|ŰA()Db "bԭϲA A()%K8Mp`2%oFy40ay8Z?P'е,bFDjt=ďK4,J-xu!qq~F,<$L| Π,8*m#6hFa/0TXk B x7qS9XzB @ Ј7I܃bp11 8DC7ei)*r.x/#di?nBJ4쨇2xG#L$uA @$ܣDta߈GQ@.BC(-:k0U B>+pt7(R`Aʥ~(\(y?(YEZWfji]6)zcH@7I Cl#OG8DɎtD>Uh sQX ȎRD; lK[@A#hb"ȄV{:ЍtKZ%CBvg.߽`܄ DIğ`{I©hbP: o[BpGA.(@DH9 m!7@h` DRma5 EU- 85,iiGɵȶÔX?uA)׷STfȕTe"}Ԏ>rRo@T.ќf5Wyh~  l5,`H"0Sa *^ rPA ^Y 6P;+8 2{d9VZ`n4C-AQJ 1|\Xvr eJ8uv( 4^| ߠ:|BX:fpn',SggG8І !,=@d6,0É^0R fb':X^p>ay)0{d8p(z x@@fpa=A|%|6q5{"6~ !.{;v%_a#)|3> bhviQ` >t`foA3:~.0y@*0yt)#p q zSlpp ` B]%rBQ^x B`%Eأ{6LEb)FPH  #k\_*#fQ(m[P@I)eFf y c uv)xD]T0y kX&P됁( 0hwP { !EBp1(E,X.w[?bQ؀ ;Ba_#Fw#u4eqPb=6  xcq"wjxs8uHD pxH$H8e tl  a 7&HPqCZPoze Ő'0)$נVr%|'הM-bxP ZeGW "uT0|o@q3Pl` )@CZqP/]׍.!`d` '׋ g(fZtǓ )g\ayp :\ZL EQi%xjP6@ @ %jQSCPUvU  nX զ* X'* btZ X7xy ! PP`)`b( 4 `x]pb 4קv`1$g0[o`a5&1op!w$a@oBV%pbGVZa vvpv(n[ڥʡ,mp٢4 m[5:g9ڨP޺> p~x-I M!:P IOwޖy 4@t | tЩ`P~p[&(*, x-\s* P(1ht@ *fJ/AKO;Y ڠ AOZ_"$0" ' T ʰ\ %@ra${ #0$JKn pKLgoSc_}ݐ ܠI:?ϥ WhMm_OTqZ[ H |`߰_y!?"# l p_?ݵfkOVkRNc[ kGtO $XA׭Ciɕl2$G!E$YI)Ud%DM1e\M9uOAe! $D8tSڒ5$IJr|WaŎ%rYM5e[q]G8lб_&-M/fX1‘%O\ٲ2:gΐI ]˩Uf[昛AϦ]vNȮu/촷':oɕ/\vqѥ ]wuW;ֵ'_,wwo{'ѯ_vݴ?pDCJN@M$mY p$B  "J#-lY" STQ" 3tŞa娥 n&cȢb\E4 Y+@C#a8` $(B\PdL(>H O6` >A1\&8;ON:CP4=lCٳ^ 6zi:\55>hHSbUTdď3YgW`WW(O$--v\M\e2%Z;Z5V> ͵!T FR \3]c!\*z75oZ !H,7`}`S7$ZB/]b],6 (qhhp_Sv[ji&JEu%:nzm^~+ٶ;;;1Ӽ\þ6|ȯW<w\ܧ~7#|sH?mJ|t4FFA."}vLGvVME}xlwLjAuL⣿Q%|!* Eī7f=lhǷ?,ϟԲ}?l@AA O/ɟ>SAxAρ4B`D#31xB4{SS!bWD7Hؐ;If> ЁFP0V!Mi#l/m @b ^ph!EeT,*R,<(Juҕ.5'Gc*ӖҔ0),s@򴧾li*P:t:ԂU.":`&S5ѦP%qj0:GI!+Yϕ#%ADR<@s]]튬`9H A{%R\iV6=lTg| xBCF[Zb4ivegچuITo`! K9p#nq1w\rmHsO[2ka70J,s[4hX\ ;uzX-7:B$z  엿1܆z $`09ka: *ŢOr@3n+cH>.c\@>ld**QӊL&rCguf|8)w;fECVz)9љUf5yk__v, +6q,t"K'E T^ %tˆ* 8tJ  }h`8+.*Z0(@!7C%jꅮ _¾*j䆻]BMpRrWsjd gu]J}3p׸7;Q{0vfbv7 % [V6}f방7Fi[@JA!{0`vȂ2/4Y8  ,Ŀ fM'NKggT<%iz<"MQ=HgG{.ѽ0,fqgr|x&7dAxgΎ:#_j#@C( tbmh`@F6`r V/ֻ^C3Z< 7!7J`Lm "Pd#`C!$D{_Ch YH>2a D=j١5[MkM{?ꨚm@"@ +@[]HjziT:A@KH|tA8cU vrA B!| d؆m@)I!'ԡ ').DcCdP0@0#*:%rB4TC*døi@0XD)?D+DC|,4I,5Dp:hCNDJEHST9UkŮWLŀZD[Er],0*R, *1*u CFe;+7k+x{<:F°k0>+>psFYLjh?Nd  F-5eSGh4,%M(Na0lM#nʲ q2O~cIz,=k\JHyέM؂+6ChTV^@ adB,˳|VߊVa"h,JmJي$߃MuK4 TWG}ԁPrcLs X|1X3E +WX0LX͕N lwM`MO5! ĉ؆HSX lY]PŸ1T(ThE1X7[ilx DͪD֋Y |<c(O.qs_=V @P פ!Bt @,I %ܯ]EsQ 0T 1e(.Wŕd1+Ne] 0hEu饎^^^2-e x3g*ht]u=6nS+bG?S@{ K}uR&Q) \`lt`'*\]VlVXÞ<腟kJ>@?>:%a`Wlo-DjaHaN ޻㮕X~.ٕtl?⮘⌺b]ap%3c32a>N3x'2@cs9{CC"H&HPqaPDNdF= k13ePE;dRW~NdYeߘ(TVA]NXxs! ,<!2'b2n83):3:3#A3 44\4aS9F"<2=FB=2C=+E="%A9sAKB+JD6iGfIKdIZQK9rKvSMBiQ^YR9ZTD[VJV5WVb\Lx]o^fbShbNjdTfmh\aj^rjRrmbsm\QqqqBsysc}sVzuk)w~ykpzrS||m|b~PpcA}1?Nt_%@@3# 5~Oь:za5Qb@[œ%bO@KqɖVj5}R7eHbu")iGҹxũժ6f_̬m_~үWD睰LoԶ}e}к莼üʾĺijźUȻoȼɻɵʉʴʊJ{̢̼̼̞ͻίzҽzբֲڬڠ۟۔ܼܳݵ݇߶y沌ئߪ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+<F_Nt]?$۫ ϥGxW"Ps@s=s8cYt;5 +8Q=s-cPs ) ݌ճ%';.\!?4#n^;HÏ|w>C#/al6<t@ ~Y<,g;s: ٳ>S"Z;䗨O;NH!;O?Q>꫓Q=3@wM.tc E 1P>_`P>ELM1H>=-J)5B }˩ X #F#DSH!sh  rI?A>B3M o >Ҕ@[x؟-e8$:bi *+Cpď+Ynp#q}XZ0 a3AC~ZA@(pk.P]4t kq4~ V#b񎊁C*Ă4Ђ1PzCe,EEJ4= d&T(ai" G8Я:ABˀ!Y ;TX`(@d" p:a2co( YXciP| ARC0G~A)q P,C)yĒ@b2Qڪ8%HcBry)0BH҇`)q(|X9!J$B,BMC Zأe Pip$h-Z@JQhHt! OLhjkw pKDHю cŹLj+[DIхHtKBWlBHr3T$]DAd YP!X$ yo[LuQG,pk;};$'F0)9XOi6A GR^%78E<#(INvbp$T괬eFEtdXn_xX XQ:x8A&5 &.<ԣ!t 3gV\u.tAE.Q`#"F(q"Lm=[a/#w($;x*&j& T L A:9@[aIҀ!,7 . =@P6)x0C^0DRdnX׺$р9 5;, dxXAP(`R@P;q APh~&]ā %L䑏m&B%P˖x @0IHЅ9ގYp_h6 `]_<4` S8x;F] F~W zv2i@`m'PUepyu%z\)O"=ARBfy A@D'TB2upKss)VLX0  0uY^*`fM8upyPVF   a؄Qw'c]x(^yCbP gtzp ` a5Aa( U>.w;< # :` ZiU2{evu5ev`a5  WF: qiq0$ XdHXd Їkk x^R0@WRnpz 0!,P't ` A'L,Byp 3dTHg "`tM0| o@v2`k ]b*T:0bɵ}m.!`b 2pw^ffsk ؎ (MuyX\70'|  ;YYa0P 3P !u4P tZ! (u! F0P&(0(a†jZ`lPtaP@W:t{a@@¹  Pp PVwZia5vi+$i0Zl`74B5 ')GKY(\[pGdz,` QvQvoUvHmHvZ^lgva!vj١m0m _A1z8 bg6;!DZFzHzp3NPR:TZVzXZ\ڥ^`b:dZcj]CZKڤfڦnpr:tZvzxhjk~:Z{: }z:J*MZکzb *ڪNJ^ Mpzv Z.`:ZzG^BŠ]ʬL*ؚںxJ\jlʭ:ZW[ 溮ڮ劮X*zZ͚˩{K {;{k]Bu p*,۲.'2;(0K8[6˲9;۲=?˳A;CEkGI+K˴MG= pX\۵^`b;d[f{hj{"+ r;t[v{xz|۷~;[{ ˸` ڶ$ p۹;[{ۺ +메 `[ [ ;[{ț ;+#[[ XP ۽kۼ+K @ ͠  Pr+ €˽ˠ qrs;<̹kϫ:ջd0 p :'p{ -l @ ʠ B|= F JLܼgk 0'FJ D@ 5I^p=`/ #5`( M<Ȅ\MkR,TCb'| `:Gp`flŠ[T` [0<*ps ˺݋ȲI ȁaũ&| , ? `E| @ I q`v  .a a˼<ϧ 鋤AIdZ @KI|V ﱻ˼b4p `1͗Kތ /0/ /Р .lN E* ЦB EJK a&pfp +|ј9[ Рr*`@ 'b0}hlB@ ) z*!lD0PY@P=&Üm fG}pT4pSM Jܫ ,my { ,EKmJ0 _Ws &.07|MQF!y ;>6 5!3, ^!@7S G~N<` pүn. {z9M)Mf. !mJs0k]æ[7œ+0 T^. ^EP2 bxݮf0vTM@t|-c>0K -֫˹ Hl^LZnkF&@xEjhv 6]m!OGi08@(0ІNF0`^!?7-|}P: PD` NCb>lK.и宎!.0mIB/`5Ix-|zA>{Zp?_O Xt (\p (( &o4*,5o#?V ν4o}Fo}(>OyDJP/"p" ` GCܑ LG_/N!$`i#0$GzG[^az߫'!OO k& G?g߰Tpk0MlopZX l)8jh1:f#H(pCMN>C-vPIȠl)FCk sq[f *XC@]8`!$8D\PdLD>H O6` >q1qL4ꑥoA /Ǖ6=6g3 DZvp\ȔC3ӴvB"8圥p`cу=K6) C(&uJ1UL@9]IU IXIUC@?94[sZzu[%oIlX=jQU>Vp<)@CJWlN[nkH6z(*:ds MhQ5( wd)JN9, \ h@cp9 VNdN@㍈6z}?TklSXrj DkWcZ+T {.ٖ{n)n|cnO 'oLoq#pB37C%- H?/.| usSN9:BYם4a)ZhYfwyw揢ܣ8bHhM~{;%|3Nd(I {,~4MlS=])?ze~_wB +@TІf+`mb?: ׸0 bP+lI]0t"`ȉRda " 9P*qOpo*AUR aSRQw7)f[$#^ek ;5Q/qa9Q%uG@}yH ãTHH*r~J=$&`d7ٯJ,EA0[ g~nU6ny)Ι%#FjTC|L=U`kns<省s5& g롹*h4GPǧ8c#,v1KcKʼn( X.3] - 24`hlߞ8 HV23@-f\+_{v9BfzL>zH=ïKs6|M7hwzցz&X?$Xц?}٘VX|k5u0A=lDT5[92#{1+aSpqX l;D/Xo ?Ȇl]Z5@ժ О @ XA(0cX!A I(b&x7QلAT>XPZ5B1AX-OayKx)*y5p1 qJS!pX6:*|ʼnCcCa UȆ :K>?tCAd>a0Dpn(MDHPJl@ߛO\aa0"$D{(JCUtqge(؂0a,b4F5)O:Ԃ]ƏFjQD CnlVFѩr\oDǸpuvtGGiZ8DPG] ^UѼJj諿{ x&؀l֓x T,ƂȒъ( ה W, ʟ%@Ѓ(k xO6j#ֲхq|Ty} .tS7$2URIЅ,Q ؄,`C(6DPATZ ]hЅ Տ#̈́+Yp&LP Op`$wMiюEc ֑233(CMA݈ Sq=,-3=xmI6`fE&Pxa֋:ـ?c䕐㷋*M]8%㍀HN,0PWu*d:9sN1>DJb~ L ۥfk XιLLݴ:Ix rfl#=_%&݈]L&Rh+W{#b_!=<;f|Y=nԊsFgxLhnh"b.h!╞ WFtȉ! ,<!"1"2*@2 83*93#:3 44Z6Y7?U9HB=.E="$>6IC3EKcEXnEsiGhQK9SNBiP_XRS~Z;WO#;CNH!<"?O<뤧'D8Rd i&{}̐>̢G=ȣO1wܡCCmVВ>b s#3ϰdO:'?a5Rl"< 9I˓N n\J,C ڌ"C3 B;@X4B>: 죏z~ ͉B2@˔Jd?\hrx!OBnx2)3>Ƞ!6P,6V1Z@; G>x@ v# _9-0,`Zۗؔ -nx'e+]2@A p/ & X(0;nv t9P | . <`-kZK @Ɂ P.pq \@N5M@ϱ/2by,L2pc h |@^A ۦr%Q}B( ZP*F,Nds%ԫ9:@/6rAX!,Bj "H/w ]^BX`"JBAZ @PF;؁X@X@Fc; sE7>F@kP{$AG?t@F1Ġoy؇Hpƒt@h!XT$ Qac|,$TB^„Ds_i "d:l q ݑ s ^`/{tAڑ)| H0lm ɫvWA[W)M"(0 w3zp0:4F5y0zpJb9.9 s 0Q&7w?}a_|l5}0g}]~>45U(iVXwABG 0ep  ax> Iܡ*Uq s i &jjI}!q`'2P" ^& z>= ԂEq ULl,P, q@ k  |^~׀M{! ٱ0 G X.ơ}b}{Ż ޜׁ::uJs(  [~!KP}n멭9np

>p!G *~P!mK9W.4E5nG!E$YI)U$KXZYM9u~tOA%E_H"ۤP\7@D*}{B#FX;Cs)V3DST1?^`|xh Ј!0"G&)Hb0Hȡ D&t2`"qE*#g H #yNlI4T(_K8sN̴| :O@Q74PDUS)b QH#mKLRL3enQI;S(%RMK5Ԡ8uUV[HBQuDUuV\=TZ{K[sv5aWdͲmvڝUZlcL*w\\t m!b p=ahɵWtz0LH \Y@~(^|+3ָ%Ȇs!#q؈0%"~b@#,U56]v:3!sH cHaO֏2N#3" LȉD!b8 vӢZ1dž1=l0n/JkrIDm*,a!X G:޶ҸW1'7zpÆRۜ/5LֵbpXb!s3{GnrL7 ',kѾ{6{#ࡔv](A 2#G@vv$`vA #SglP]&JB:I$aCk5!nC j=$~~D$~jEd}D(bN_jb(fOKbE-I\b3)9@r`W7-1ƑMS4c7QQ(<:pQLxhFl#p,Bf&dD$"/m¤ }+{&]NvҎS2A F``&3=Y2fa2rdEb)K3R')ї \ZkZ~𵰍m!!pD$B4τؒ|7ee+GXE%;iwOH4\57l$GPuMLht' &va$ͨ!7Rw#PF◠5A:H.Dt)LڢhFEl G8FT$ jPI+5jTjK^*Sv_+ '=IsU [:BUQtIzW_Vu-agp,V1c7gmp#lF*kٹQl!mVdg3Y3URQ[l#F7aql#lc(,U@F7*`D0&yamqn( oڌ` O` rۍq믣l"ff"Ab6f9+Rppo[AB.Ll-ԡy82Q?<ǡMmhkC.jP0 5PD.Ћ8 8ANrd"NAZl1VFv/99Fc!76 O0Bgyκ%f2[72 'a?8iIX_'ݽJ[YF1\lAyEU!bV-kY*F ĹVĊ 'L?0AB6r:Nin/q%o\D aĒʼ*DhC ҟ!kbPQЁAgOJ1mHYlFMJ'WO%1oP:V䟖ϯ(ܫ[۴]뵇ّ$!6: j?蛹Cڂk &*8-o@ DH,1<«1m'(Foh(`E*0WD5K<"32$6 =`! 83lD[\Eg$12;3l|8Er"`qGJ,Nj3t,@KxLJLJG{|G3ǁG$zȆdr: @[Ce?\$Ikl6'tIHKuʠ$JA{[iJ4 J9JʋJK#˲4R#6faH0:J;#أ>h(2Ѣ˺ltJEb$G$.: DD*8,LP˵!%%`p80Ci("O8Lz\j]";xdЙar0c$)6մKy'jkb(ŋP`pAPS 3@F?X ɎZ $PvtmD&rH`ɹ 'hTeAZ( @ȃĝ8O%΋5#pEf4ЈDPˆ\4H(FaPы '8PE ыQ<b}Tr!(n(xGPJ#QCA*j#ň  G!4((q()ݍ$I/ 8+9+ړB8@M:ȼګxh1TBՏTPyT}TNLTHPO-GjSաQ%U'272-J-p LmUHUg-Ír93\NUYpXz.#XpL<ѵ2)#dJĦ+/j:Z/ eDF܁2p>o058X0ElS Z4 ` ,Ju֥]} ]P\E?33(k3w7Nj@0\`XtBuPЇM=|%% H(' 4W?L4VWO؁{Hl8`XnEr:!%}a hWa$AxlW`lP5'Q˩X &` U. r_p'(l1as5$@[ I6.)v#͌ܡ2=2& Ddr`9Sa(2W#b`Ъ9fA;BIl]) 5 BF׍PZ~^[Vd&mR ^N'Tf&aNBPf@!fmޢ~/ gq6GrFUs>gftn{1LՂxnf;v͈Fh@C`?`rY.zg{8Srixhg ˔Ň @\Yr (d́J "((N. ~A   P8^_ a8>00ϣ,茄{VhrPhGDNCP醕c*kNnњ:蘿4m_lk6 )N U -Z2C(钶lT۾gd+mW#%_\d$mm2p*m.UҖes: IN#qc$aq8 :N Xm :`_&]^hoHkfOnfߍ' NpaYpO$0 p[yoH5j#pg~Kp(|ՒK_ψEG$ fl qoLQ"%iiM&i&Op'r 'zP͇3e" xL]a</pHiVts1p& #+zWW̽V@V@/ޙX8 S(43ʕ Pe 0_޽Hpx)O:pE Q_IYmfk } A$ወ]Ofb/3(hP)h(%Ipl,pSprm4}=>ptsG1uWvȮňygpm~`[݇H%ZLx>wcʦ_POlPW.憲 [7LyGI0~NpytVҥr N[ۥ Q6N a 90ښEo!9Fd ЀOaXdV#q|t<%e^6i46lCrJD4EKcEXiHgQK9SNBiP_XRS~Z;Wx(Î;SG?@Ow&z: l?!2:%ijbt93d=Q,=%S tp>L$Ot0ܓ. : 3@N=C5Q;(P?*[0p.h ;7hTs){N:s (|!h3lt|pF4 CItP/S h(|Ѓ/@5 dK9j%;70P>3׏dO:'O?q5R| _> \ G,!.*L Nޣ&4n*äBp9wHr<3# X R$RCxh7UJ ,+H}PIwA`!.8=Y/JVE|C -hJ:>d( ֘{ڟj`s?dA#hbx lOd0 E=a Ohabm !${A. #ZPݰP<  cAdc9G=qxbJ#=_I|`!ybC;걌ؓ b5pO#gxO^8" 6u ,:`C(J.wІUHWNd 49xR>1OR䀤jQ]*/dJ]J =3UP44Bc?ց ViHBGZfHL@=M֚|J~9EcHZ$2Tz`F$0tҚMjWֺ.B#NpV/-aMpD%J".$ShFn1kNI atSmR๺m<⡈t!4:PH4rK>NhNo,0HA"R"᣻ЀIl^G Q,>.:,PjlpwND=W1b8H)ALtYU!(G"6Q.=q١<K= ( Ճ H@2ӂJQqY\!Һ"u6e 99} q׾%a1 vb@-0U,;_v xp5nt0@\ -5 yկ.V @P b]L D ,`DM##fAcajÍXdޭ@ p ʭ?HfxR$rPbԀ^5;m1d\ NtA9npLAZTS!hæ)OL`}D9* a 1CQ  Xcb"'0P=2kh;@sW h zhvLB.ă·@8@ʃ4 P[!GQp5Px(F%OP$ ^Rp0%,;`# 0w1/`D JuTD_i"b8h%hC923 !.VǾ%@/Sx@\qaĺUa0/{w&^ dxx$@x0jpkCjygT#g 3psqm)-9P sP -W҅Q*'w8ce|Чl9}-g}\GF674dz&]@wArG pe  Qx^Pw hE<"]Bk0CixְV8SZutr1p5g_% @1#T VU$"PtX, Є`A Q$Gxb 0 ptf@ 8YQpV! 55"0 HTz9;lK"44%FH`} "w V 03+Gw U)@$u%mP6[wp)!0>p ǐ+`}uu !dD60U [h"L%w`H\00`z 1 :yXwO* ЈրP3J a =@~Yf P @ ۤf3S*G q5 *wu6w 1 P)00 -`ϱ_iB_Q-uY0UXL`e&0kl V" GYl"FTL _ t mtXkfF5[ ўBG!CaQJMyg0Zza)P&>x!":$Z&z$*,ڢ.02:4Z6z8:<ڣ>@BCz*zJLڤNPR:TZ"Z!Ij\ڥ^`b:djX&eڦnpr:Lz@#ZlJ~:Sj@: #|ڨj< Gp!pl$:ZMJ+y! Ч:Zzʣz!**Z úڬŪǪzؚ49z:zj+P@k @Z:Z گ;K[ EP ;[-۱6L P&{(*,۲.02;4[6{8:3 @ A{HJL۴NPR;T[J[! е^`b;d[f{hjl۶npr;j xy  X P{۸;[{ 0 | @ ` {ۻ빢릩ʐ ;   [{؛۵+[mzaPpKKp "ྈ뺹N +  뵆{ ˽;@K0`_f`k 9`"p p ذb([+ D@ `\@L \F|H|<P pf `ې؀ + @h $ e0:P CDE i`-0! I|ȈI7$pА܅[$`* B~D^FNZ I}K0"":l+p+ m nN \ꪮȁ.؃_'9 "}ݣ (#r"h$_zbY]ޠ;ذNR'q@:W幎:-Z pP-J'PWzǞ쏽' 0K D>? zݠZ1}Q <Z,Igp- AL2?4_68:߶vz7M: 00!ҼG NN{\TA P `X_/#o 0 r?n?a_ɰN m_ r?bNj#&: C2 S touz"#p#%  Ҡ Κ /G $%:nPM EPBp!p^ g O/ƿbOpR2D8\zTaU :E2G!E$YI)UdK)#AYV1uϒ%ZQI쨠 \tD24y38%4$JTee[q δi,x[_~] &\ذ/&0cƎB^,Y0ë*ٳPv4cՐɲVC0hQ`tmF gɕ/gsDM=zr > 2i;tW[!ȗ+QEϧ[xJ ;Զ3Ɖ>v KD'8 ʩŀBqDUϦGTpE[tEsLL88X(gn4 :&[0KrJ*;arK.tr2`r0"datM8w,N< L"80NB 59!SOFuE>C+R]QN;ԹH1uTRwTOSUuգB-UXcTVkSWeuQiW`̕WbSSUv/u :*Xj Yfն?v=IZZru mU9oK '!訛P܈eZswֺLv]N*L A$P#qFe|w_EW`; s<"% ,)lh7 xb`,!ccݸc#B>g09h5hxb)*瑈&h( )^ߤ6ϩjΡκV+, Ǡ*rVhrRn-=n΃sPP5jS3צb$bpD$jEd"D(jNn['FQZ,nQUP!xI8iQr#xF<$T-с$ָxH1$ | GxdRI8/qիBd'yHF2; SHF4ҀƐAϓ (CGE`*J" (lr<;m4L\-oyF87*SpKl-\]{ B"H9^al5ͧDeAp+_a9e -G=yE|fPI4VؔC66m Ѕ:MG <S} g8R{#AP IB_6T3J4HqJDF8>;r )B2$%OZ*S=ԧLb"TЬ EkZk)?JPs+LjWka[W0eHXߑ}c!ۻH-e/9>li? ;%p #.fڳ4k RXɳ ng-nz  >$ ^t]13 3pCv 0bblnyx^)A)a $CEBn-1y,G .VSq@E[9 %s!b#D( I 1GLmvЅ 0XAЅxAc \ GFnr\Exd$gOȰiACL!\muۙȺM3DAf7#CG MLxCv!\heJFx D؁[Q(_CgMw{5D `'CY0pdHW3tv`@9k׶,, T•aClWa{+q ~(wZGT80g{3t!n؁܄?x_Tes}8qEFO8V $liGOG \Er r劝nk ;h#27w]$bB/sO|S/{k0f6ZF"&d A͎Sy9h+XhWF זŬaFΙ*fm{'O29uPAD"1kVood'CY6/;#Ne"V|{7oJzZvþ#ylhc}165zwIp2pY&zZjiy{oiYp7J}Tկjǿrs?jQK`+b;6؆$`r4bA!,7 *sdZnzSAL"|AqA<<0 X"ԡ#D%&tx˸()zxB^B.|xR, ՘X24CYA4lk-0.;@&w$y!p2`1]<#Һr7"(nHDE4!lP3;0`/ s!؁OܡP_!KsǓԚ(Dpph[@;E^%;&{o4ӀAX:M0j?$Ah 9 ֺKIG$I$X.A "!)@LLXLRSJ%nVU̼<˷d\*&aR[{Lah(U[t(`6ִ|spXҞ یv_(  rmSE/.uSmVg?xOxZxA4ߟ݅x7x8nnx}73YiwpГ .dRL (bjm-˝6w R 75 ^(IW_UlwD8u \ 7a Y(eU&y{wS pX攐ffE+G!)}T}qW/J9Tm! ,<!62#:2@2 3+83*:3# 43Z4Z7>S8EU;KC=,E=#B>3(@7KC)KE6GMbHVhHcnHpSL;YR=ZTDZVKpWc4XX[[Tc\N|]x_hcMicTqkZo]pfupdTqv{sX@t{uf2vpyq~yiYz|k}s}Q~l;QcA1tNC͇3}?<F *T#`7,|fxQaSDcGLZ7_ϖOKŗ]ƗBq5š6[ %gM)Z+uɦFTϨtXFۮժ5«kszf֮GɯZЯhKZʞ°gjʲж}k˞߻}4ľ޾lٿӛ“FöwIJųţŋrƼɾɻɳ|ͿͬrΒϽϣоЂАѪ}tҭV՗ڮڞۤ۞ܻܵܳܭܓ܉ԛy H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+<F_Nt]?۫ϥS~Z;Wӏ;3$Pr?<ꤧ)D(Wd i&{}ܐ>BG=XQDģ1|QC-E>HQ sز*Vܠ8EFy @0DWl)?\q>BڸaWO?X,: q0Fѱּ>l&@C=X17+7DbM9N6Llr` +4O67.hk 3w@hL<#?Òy;9m͂NL5ZkCXS :2@4BD5$>LA>`>I_s%8Jp?W2e8  $} E I?ܰ(4S2F hgRA.ر+h}FPH tPL1  QU8$Y! v5O S9_!Zy} > )HM_h5Q;Ѕ(Y?P#ՈG ! 5@Vz[ܪBؘ! AdF3 &Mt@9t@# W Q h<e61P`q" tj6?>݃c@ǥ)TxPGC_$ W$n%Xc9RYHFQf\(`4ynYt<ġ{aHF  SA =!+c: q`CI2ьQȁ;dÊ* ;g$Br~M()yr@+ZR-)4,,`L| &mP6Z! 5DS$B, *kMYQ r`; 8&kΚQª@3lH"<ֺlgK%@Bvi=%f-Z)DIЅh g-6 $.x*Y X7mG<q"I8P([v"36Džw"( p\  ޶QJ m^G Q=>:JY#SwP$}qY3c8H1RAMui\V!"8eQ.E6r X K=(! ԠG  (DH@6EjE+B 8V?4q@)fNT\_Qϻe.#Ž @JqN1sp"eߐDH; yָ6V `T@"P c{!0@^8Yw=p_deX4l `@JAW7H),M`cDa x-Ҳk\mbPvtD PcS=G Ď "0+.dJo`,P(7..\h ,@ cFK%_@ Pvl  @.ԃ9Asv0 ,@+x N0x"R"(H`Poy*xchc@Wޣ8h@AYs䓧}X`8؎7h숃,\1Wc2oGosHA ^NP;ywi=0 o vi ,؜o_=fr{3l nv!Pi0xoEA\B$Rxpf@P#cyG&Xq/)..0 PCW@s\]`".j\`@&d%P}w.4bw~?@n7}&]vWW 0eG  x#:dZTrt!z  VD@ .`1v )D( 0{^s P \0YL`f&0klrVu&/kr(L@&f$JPUGGg]GWY򙟘Ŋq5vJΙ)Y *M lPڡqFX& 2p!*,ڢ.-+4Z6z8:<ڣ>@B:DZFzHJK2R:TZVzXZ\ڥ*ڤ)zQdZfzhjl`@.:mZvzxzTH+7tʧz[RAR:ZzD: Np!֖ zR,y!" `JZzȊ:z!::Ԛ*:ZڭDHv!)@욯I;wH  ZjG ;Dڤ9K ,;$[' .02;4[6{8:<۳>@B;D˳ Jz KPR;T[V{XZ\۵Rk* d[f{hjl۶npr;t[v{xz;з~뷈&) ϰ ;[{۹;P@ [{'+ @ Ұ ;[;+[` ? {۽ۼmaоK  p3  BѰӰ[ ۫ef <\ 䋺拾g0 hxg@` E$ Ѡ ؀ (-K ` ѐD` 0gkPR<Š Kkh Š* TÜS PK$kBѰ ?@B 0"2p @ŐɒLVYix`p0 p@8ɠ 4p * ِ s ̠ePyl [@Dpk @2 'p\ pv0<ܽŭ l  )+ ـ (qf&0˵|@ֻC,{0 "l wmP]W̢: .pάjp0@@ (`v1$+ ϋ˼Ъ)NԐ{/J + V9#}@'d߰(` f հ Q@qӎۻKG0 ~Ӑ" KЩL Ր,K+ʩv 9o`#w!9i9`!l`M`pj.am0P X@X@18-4ܻ~?؆w = lmԒ-Ŕ]}9 0 p!pp[)p ڊ]@ 0 p!rmP\-] 6|p5Py@ A:CĶKj20F~π؏N;\+R}VVsj\5~!przG f2 p`vۤ=&Ñ&+ӟ+ P+KP Z>,,0%e* o`v W.ߌĎĸ.âӏN~+"*Q7 4O_}!\,U(bk ÞN`u!o| Ϟew =Ou .mvw._9^{j߰˼+)F9 ήm }  aߢ]lpU u/!n{LNPR?M !/AJV N0q`rrFǖn~aj[q%R(%};u.0tp@ 4@ b RCC0gAB0J4[tEc.q|`WG JH!"H( -0IFE*21YqK.r@vhg F&ƁA"J8㔓,N<Գ#1Y&oNB 5T:TtQF] ^PJ+4DtSN{RPC5L;5TTjeTV[uRSu=?}V\匕V^{\]}5o:aDZlS6"fp3ib5ܲ,uc-&5lqv\|-]~ 1P0!TH"piF/!B|+v~36wUTh S"q9g`b#0җ%vZ"D lj",R56XdMtVnd‰F'!Pq21 @ lh -hiMrjʩ&P8d&bn J!7z+׵Z;׹MV @˩!d |x-^pqRc_xrޫ|{s7|d0&&|AAv1$!K-4!)aYPR$s x0+ 24 -@A &0Eca41Z*a D!&WD4bD%FULtbB)fqTTbE-P\bF1rαݨ-aDȓgQc!ȑ>XD۬.ܠI'Q( ƻV7z5H'F ~L  oLa` 1QR1)H#L jsnta Lp8`F#,5!.̢lv^ҋ4:IJtԒ/ %$l(D+JЃKA7INqZzCp}Q\`Ǎ#?P';,Lȃ7r |VԢhK5% =B$Rpԥ)BtEhBP(4bCmˋ@pt&Ƞ?5$%1ig0@ sU UD"̄&5I*8J٘u!zX5D$X^$%_c#{YLf=ؿnM8>{ڇhVq#-^ ӢV QjZplCŲ pP,cmm1V^XEzy`KQ8 0 PCh Hn].܆$nH 8m ?g.1 ?DLzUc|k.rc/ U8º "!F̄03j xB~SVg*8JlE[ڲA 0xaǒ|qCxPFU9ׂaJNpS;I@d6mn67#A% (qI,= ˵+L[K<`!4BpkB%zB(mB-,.sy ,B2#3D+,5-ޚf.85h[-HHaz>C9Ĉ<<(CoxxaEb5@FAh#H4Ϊr7|o`xY ;F -zR0I* C#Q9'h1ɂ#!h&\t?&\iP`Q EWGz440-„)+@7DȄŅ\n?ݑE>HJQȎ \@\<s74^ rIQɘM̶mx4\ "q7f؝oP!ʢ*7ෝJʮ3$<+DlLvؖ)ȷL-lɻ-KHL;8,. ,O#:#[ lx̘ ACB$oy LDH1 a24MQ,Xď\HQ%h%i0i!pMz&a"&c 9Xc4JDH0!8$8 7dƁ2'p Jo oa3p qaYH+X25TT-((/X4 > qH͋0Xh ŒeBbnP8h5UaQzф )p,Q-&`b RX]tP騘2fa*'5P qp8)ن22XR&Q J5}7  q`'I \ (@O=!%L:4Y67PSH|*@(SPUNTHT~UU\B`VC+Va dEeFfm옵E¿h]i-2C\0lm+At.;J΅X$sEPH=9DDK$;MMnXO.RPB`'5T/8PCYfaP8bxىMWu^ F h(y 1hIXf;0H mZr D(ԙ7 H̀mل9Àn2(y7`QX2*F2p,3>8Yʚ`&*x'ȀpeLeDϣ. h)e'(8́P P@ ]q )ӭ/G0 >2+Ts0xE2BKdȁ` Ȟ]8q8=D@ x >_.Ę@_ MA™\KN[Ǚ5 Y|;@T0a`E s@6e[&qKI6B6UId@aPIT.Xq ҃PكhU_bx.ᅍ(&6ہ~gX8h`0gp`@|_hhcLJ\eJZCiKAii~ɖz<zKHjv߇H.#jE-ㄠh%o؆?Xejt)NjpEYm&8NM0jԂej` m*3@uL`!8Ofkv'P۱Dq0hOp]; O YllnnCДY3d3(o؂,E Kmn!˒= ٞNm1a{+%%ܞ>.ڵvC1*TrR5:go.}kVI765 Sh7]XnXpp vB 7(@EmT.`+wv改T%a4'R70hp%&wn~ 6`*+H_ ss23WCa67B9s8w?^ɬ` tBgH$L8@ĈaojFGtHKʤ ؤDxPc\58PuHURWo0e:OZu"Dbpl m!b6dep";LJ X1b [ Hs>vdB xt q\BxTb`^b(HH'8b)2m%J K ] Z#YH*7i~w0O)qj@| J`[5aFKf'H&@znyyȀ,E УN hɂ>7`wf|q%Pwwy6T#$-Fԟ{qpa 57F4vq@Ҥ:S dFP vqy*ʏ|E@5 !JIj`7E K &r`7u٦uvd~Pū+WPwq,h „ 2l!Ĉ'RXU7r#Ȑ"G,i$ʔ*W  6<>0JD3EIjHgbIVQK9 OUSQEYR=ZTGsVi;ZWaZJ`\S]}br8ciicRjgZrl[o[plupeGs}sV?t{ue~yipzq}kQ~asNl@[:|Nu'6D<GF Ҋ4&T7w~cg)cVH6]MW5zIG[ÖYϖPKBoƗ+:b fHɝaW]&uyWYEuYժ5«keЬnffծGKϯX°jʲж}˞ƹ<߻}4ľ޾lwٿhz“WźųţŋƼɾɻɳ|ͿͬrϽϑϣоЂАѪ}tҭVԗÅڮڞۤ۝ܻܵܳܭܓ܉ݷ梵ԛyߪ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+<F_Nt]?d۫ ϥvΧOx]xO#z+5qݷA`?t23P;Oz#T(w/ @R߉ճ9вO=5P=HHP=0 cI!x?Ï?`FP]C3˼-h6S~Z:W:#SH <?;ꤧ'D(Ld i&{}p>ȂG=` 0waC-SВ>bx C-lS0N=蠃 4Q:(?Ė3KNMo:c Şmd, WSH":Fi(+0R>p 2;>47§8ؠ4Bp.@(4L s \8NC%:30>2ϰdN:'?QM5N\M„:,=̂"Q 1YBL#˺:@LA8N%|_s":c2eR:H | E J?(.` #  hgR-ֱ+}CP(FxPA`!b-8]/J֧`Gtc ũ-lJ<׾d Ԡf~Т#F|/>dQ#jp h s걌 0"A+`<EXeyF~CAȀz$a ,`YpD lh1E|G`BR2!fa 6B>s& O.ѫvG!2?(;W*S}ɧZ SiT=$X4@"Eh=kJCNO 0./w ]]Џ"X@Ѕ*& =:B= @`:qs"PNU(z@@;, ż<p.pQX@4}s=q?  4!,A0 6؋@i>vg2H+ Y߽* ,Q2V^x%(.P)M"(+ g0xsC1b0;?tz$qx0s`Jq($)9 s 0WյQ*Gw@@J*&FJLڤNPR:TD NU\ڥ^`b:%z@ XZJlڦnprf%){`}Ⱖsڧ~*ut!|:ڨ:p 6*)` ,˰ ::Z;z!Jګoj:* ȚʺP*9J`:Z:Ί*;zʬZ'|ikb 0: :: DOz ;'ڰOzJ˟|R) P&{(*,۲.02;4[6{8:3{ @A F{HJL۴NPR;TD ) \۵^`b;d[f{hjl۶nprPvkX 0 {۸;[{ 0 y {˯}' pА {ۻ+˦W 9 ʠ [{؛;[dzaPpkK` -i  <`0ѐa +]{^ ڛ ᛺e `ue`K 7P!` ` ` d %`++ P ?@@ ̰_KHJĘ ˽Lb*``v,` Hpp 4|Ak P A?D j) LȊLR T\@ e e %.P4nl`Jмr\ a?g0 / $@U @tʼ\ ťkܬ  euPV[p0p`Q# 뼳< 5@̜z$\}M # Ai!;ae  l | %0g7P ,϶  @<̿0ШP&]F}Ԉ .* P 깷` ؐ%m0W 6ri1]˼J |PC<0Ч IԆ}̬":)o)5i5`! -@@Up*WԌW}0 \\n`7p4ܿ |9|wML j@Ѱ¬-&P؈}Ċݽ5`-x!@q "`o@w*" p!Ppr }'z"=! @# 0a +k,0 ;@2>õ`Df /$ @M}H--z O"PG ev 0#J#w!iPwߪ~`D:^)#5} >;K>M-P.v~}\@!*cnr  ovl^"vGlA*1M^{ . RRN 0, U}!6m9k궾̸ܾQ]w!{@q0&G + 0.t ^n֎F̵|ck 0w+&ٙ)&IB&*o@i@ j/ ?:<>@BC OEư [RPV_7S/i[@{b? \Q?p- ڐ " h_͐0zwo.   + 9 !  }OzM #:!& Mp! k o;c?-& @ޠ %  y {j/?-R@A` DpDp!L&z @{qLkEp!Ez# aE8hg~bKp ,qtG!E$YI)UdK1UJYf$UdO& %ZQIeh@hƇ$oE`Je[qYW+x[_&\aĉ/ƻcCz|ȒVE"zP!"dmܹuoI'|rٴID[mtN!a wgӤT;yկgpqR!>9~$n xHD8䠎.<tƓ<*B 3 ,pĸ!@v@1 q9F #15pG{OB 5rH"Toq+BIJր4H.ˢi4̰TsM6L8㔳B1GjaXsO>zsN@4:4PDsPFuBtRJQZQL33J;tK5uT 9TT TV[UT&,KV\/HW{7XWR&'j.Wdi_uֱ1I d`hU[pGbYr-Bb ml wp-fUj" ,sFxw'0]X&9h N#:h` DdJxV>C ZBH xxŒAġ7( Dy>UfjM#p bs#o*$Li~jk՚ D!g?B懵,4[IcXDŽ8`a@{5t@kbXrǛƺm cE0};tғtԛrW?h`9o 4C6tѕwG杗H$ AEEjB@# ;ų[ >iW[_T`JP)#Q,xB E+ Q3̕ axȐ;< q`Cx萈KDD(SxHNՊc̒x@4O3RU6EF<ʼnh< ɤ,DպGZ+xEjI" nD^;FR&|Uh *G"H A01q,0M)KyD>L!DZgBI` .B ld-$1dr*UJV 6O%nd9D&V`$9ytzdi:4G,LN4!MX䍟?_PTd|f:G$:rѢ+% FQ{:$"( t6bJUء͇#Rj2B pUv!jQ)%5OODՉVԫS"؈&u'j]k%FQj@a #THD }4%d#Y]Ha! FlvCI;(7\߿6prz88 qJ|\EQ3|㧃z5ae5>/E-M"jXnͼXWe=s{!;uȞ@&:CjC5(򵅽 m\\{yՍt1@^K⴬pK^ ׾H!Qb"ٙ7n\!)>@D>x!)N@[தGZB󹹽^YG}t0~# yBbe_p}Z"~/t,$v+#Sw<7oW~,jCZ YW@ ɥ[6qp >gA4d06dS69T@l{@lN7r+7%="~1SzA|Ip>"A".DBVQ%#tB()  zS+4&¬I:-"TB1ԍHT:ǡ -/dCTq7č+-(p?.Cpk,e8?/:W:y! {y86 Jp +0ժK%Y:*h*+Z/0>DT+^<-<ۙ$Cl''Xe""b k's=(=HyшEqDc34h8 xEqz{|DK>m`lB`簎 hWR\C<?lȥx35Hl]X ɔGܔ@ Rq"qR8ن0%v|RQB hg<7qHkPpO6R7}$r(y)y7lTқ4%( +TNO%`BVاS-GXFU[ \!=ՅK`}$ɬ#Sc͐*L9Պ0PfTGڒC$ -ߤNT|dj.n(/.cԝɆdr*ԓ*hTqĬ3/(Q[xP9Qqq3&ْ 46]hF DhLJ=% f$N~Ό TAmUVeU蘁}`XhaXa\] HQ ̂`A$BY@H U`=wމyB4CNzE(30alm{±EyՁfB^mDyh'hIoȰ苮莮"gi@Ñ^6i < sҕ&viiޙwB 38l钠h$&$Mbm%|ui~)X΃ `H撺G>8MIPWN C YQσ 8d}\:0P3f HH˰f!Z&4?]_ >_Ql( mIоN )u%QQ.' Mmmn UE( 8oNZbcqm6n6P0UMZVb~͆3ȁ0ooΡgKX@D? A=.j坱+ SgtU`O#&m ߍSUw #$W$jSyr(h)*rOr-/ɑ L//d#7#9.ND\93W 4O? $@< +^ 5`;G<󢈤I d0nēk'D?Eg8?7NV:0k84 acHe6HExfqpC\L0{2u}AO#5v+d{c|PUДbH@aHRSz4b% rI/MBd$:{Gm+ޠWSxdhz6Ꜯwƃ @PPⷲh&}ά:nw⫿*Ŀ³ŒFö΍ŀmƴvǶǿǺǽǾIɼ]ʽ˷Yˣq;QüӜxƑxŶiڬ˖̐{Զ⚹Ճڥܧܻy H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+9F_Nt]?۫I9uΧOx.?>GrgW"9W|D;TM.$;S;蠟;"Ѕ~g;ݤR>x3اDУ,ÎA%Ď(T#t4N>zҟ@x@A6~TQ{ k@>9;r 4>  +P83J W\B+ѣ;簣33$>ēON~.J=H<#N8P@q>8QOwS&zӍ7ItX?#a??9c K7G)3 s&^3 .92.8lR$Ouܰ"jS 4"D`-,B : Eyᨁ@qF=y89XybFT YdQݼӏ%%5YaF"hblT8ы2KJtdDHrH V,ʠB'4ࠇ8HÌ$ 5H (0*l 9(SC ^830;BN*'e 7IDw!L324Tl CJ/xs1H@ xEjD+ؠۗ3&+ CD0 >,AO>;1h NyIuB*_@:!8WR >hA.q5G #YE?p,!]>P 7H=$ԡz&Z0ryȏ8%#>P0| QPN/HCSD:2,$~Z=g%TIp5 Lq D I8h.rn1. ~P-xYB艃đ ,p(&|e91 ~{ H=8H$|u!ah^̆:Qȁ A'2,B- F.p $Ap Hh9qxC$u"G3vtZpX dl`GT GB_= ZqB:Ǖ["+1Nx(hCAE( ;ZM]UxM"xc|N:\!|Kͯ~ߗ ! eL9,CJ2 vDzFhax"}kzCRp|J9G0& bhvX@I~R HʱN$`d!G\+<|A"tTpqh TrD2"=#=?Ejv8E8;xigą64B]hiH8hGGz:TlE=?3jćN^^#A6]JH('0hY8vp&xz;*8b7@ C8TJq EM@E :A^,7PHPA) Ё>0 d1 |pD PpHVB8z0CBX>(9Vq؂(@+ zLb H| X :olC8<'"Mqpa$w|pH$ЊM A`(|!  0x#]iw9D5``g>AEv-CpbP6)b@xЁP @ypy!xF$z} `YiIx}BKЁ ZxߗGK  _'{G20q7 ftT((%Z +de -cF; D@4 +@X$GxD@H @  &vU@`$ aid@;;H$.$Ghyb` /M8|ӷ i6)hb8RqpJ&~0 0 qjdnPِt(uA.V@#8# ( `ϰ#bWŇb({Wy$0&X pe1P HJi'ƒh #rH$OHh P  {WF6O!~9mP 09Er~` -2ZqN jCN4-d 0z*_ `{3 =@#@ }PC# {\@](ED!e   bЉ 4)_@ 7Y0 A h'XpY8)&Kؔ\A!ip`І*@+#  ѱ v,pp 6+<  R5q 5`!@}UvH{oppPpe0WV ` 6yTΩPP. iZP $PPy0P@ PXWBiD`F]) _AP J@%U ! ' pZ5 B'M% W Ϡd2FZWah` PѨ<"$]ZYXZz$affA*P :ZzÚȺź #:Zzؚںڭ:Z犬0 :Zz皮jZ 0j ۰ +@ @+ ";$[&[j `ĐX[ '<۳>@[)8 @ 0 P NPA{XZ;;Jj0s@ 03`Po/<\z|۷z$O+F;Ё(G  x뷖{| J N j@ P X;[˹ F+`@" 2Pjۼ(;:;PX ;ȊiPFK p@ 䛿k"@pJ P D[ W˿\QKNG[ 7`\&|·+ 6;$2<4Ll.,.l5@<[ GN|BR\OD™ ZO ! ^\S\fc|*7Alr,p hs\4u  bh)LFz |`lPɗɬlʤ*z)i<O@  PO0`` O Ô̌pǩyqq #Wr/vЫ<ͻ] 0 @S0͂pM0 M 0p @ZX z{gb@e˒P     Sp@ ` C0 @f@(R$Fq!P` Pa\ @ S P\`Ժ0<C Qb`#4IZ`1ppӻ<I} q 5؃ԆI'y0մ3" C˗b}p M0 P7- Q@ ]T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.022?4_68:<>@B?D_FHJLNP! ,<!1&72$3/83*:3:3# 558C$;3@<3A<,E=%%A9KE3KE9FM:F@$PSTPDWP;ZUH9ZYc[Jc^TkdTXfZmi\Glmsm]ysd]tnwtkqyr~yjc|}m[~\~~RO>pC\L0{2u}AO#5v+d{g{P[~UДbH@aHRSz4b% rI/MBd$:{Gm+ޠWSxdhz6Ꜯwƃ @PPⷲh&}ά:nw⫿*Ŀ³ŒFö΍ŀmƴvǶǿǺǽǾIɼ]ʽ˷Yˣq;QüӜxƑxŶiڬ˖̐{Զ⚹ԃڥܧܻy H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ 9F_Nt]?۫Y9uΧOxN۸?>rgWbW|T;d.(;S;蠟;"Ѕ~g;ިb>|3اDг -ÎA%(T#t4N>{ҟ@xЄ@Q7XQ{O k@>9 ; O4@M +ِ8CJ X`+ѣ;簣3O3$>ēON~.Z=H<38p@Ё>,AO>;1h Ny IuB*c@>!8WR >lQG.6HG CZE?q0!]>P7H=$ء{&Z@ryȏ8%B+>P@| RPN/Lc[D:2,$~Z=g%TI5!`N D)J@h.rp2#. ~P-xYB荃Ƒ!0p(&(|fO9A ~{ H=8PB$|uah^Ԇ:aȁ A20b- F2q$ap LW҅L$+= `A <87V B>$C`E0@:;N$;1 KѣG`lK# dX^;1 tS bG:1NP0OɥzLh= eЊC9o!x`%rx -@ x0b Bf rkI#HtILyKͯ~dHN(c9fV$DP&4*P S_q<90&0pvX@I~$r H܉h],܂P6k0H.] #3-ShB`F['vcHQ'@ug0L A )4M$ "Ŏā4@i &4![秘pOmԚδ%b"q,0$Pw@k .ˡLp*&Uvc_ohT3`7@ f\)< p(a ) B=8^pqhX> C t|306^;<lZ! 0KT@/@ #oT`_-sLFz9xGL D IP(.6"-=zfsC% C3n b`A>Ձ <8Dpf8!=VC 0-:QS?})K'%&4LZ` V5hq, "x%pO$<:>BI⠌H8@ʃ4P84 aGΎQGPT .Pg0D 00s2( ` 7)py ~ `De6ds*8` eY ~7``i*r"@;'+||)p$Y` }S!S0~q}H7N~ ``Pr(, ۰IP\`q,@B0jBDeЈfpMwG$=$$ @0@0yM`bVU 8pM`@fqdP7rHl 71|IxF i&7]RqpK&0~0 @ ljdoot8Hpre@lm0?3ˀ&`а#cWwiz'y$0&Y `e1` XIH`z8(XDrxoPdtb` iq`)` -@ "# ' 69$ .t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02M?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?"! ,<!1"72#3/83*:3:3#4- 558C?<3B<,E=%%A9JD3FMJF:$PSTPDWP;ZUH9ZYc[Jc^TkdTXfZmi\Glmsm]ysf]tnqyq|yj}m\~~RO^>pCL0\{2u}AOu#5+dk{PUДb`H@|aHRSz4% brI/MBd$:{Gm+ޠWSxdgz6Ꜯwƃ @PPⷲh&}ά:nw⫿*ĿŒFöθijŀmƴvǶǿǺǽǾIɽ]ʽ˷Yˣq;QüӜxƑDžwŶhڬ˖̐{Զ⚹ԃڥܧܻy H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+9F_Nt]?۫I9uΧOx.?>GrgW"V|D;4M.( <S<<"Ѕ~g<ݘR>x3اDУ,ÎA%(T#t4N>xҟ@t@!6|LQ{ӏh@>B 㸓ON~.J=쐈;#N8p@Q>~POwS&zӍ7IHtX?#a??9cK7E)3 s&\ *9*8d" $OsԀ!jSo 4O"A0-$C 7Eyᘁ@QF=w9PyBTW\1%%5WA!hbL RЋ:,lt``DHp T,˜&,b؀8H $O 2 B'4)d 9,#^800+AO>81 NyHqB*W@:!8WR >`!.Q5E E Ǔ$`w Ac&!H`9D Q4y2Py B| Hi|HA`ЁZ=g%TIGP4HqDG(BhpD{n0* ~|0)GWpB艃đ$P($|܃c9 ~{H=88#|u!ah^̆:Qȁ A'1$B)豂F&bn #Ap @w)Rs4)r P(H(6hC$HEAA )ԉhdt0-$܎ V)rLb.&Ž1< %qF@P q `]b`=ņF5* V ijBCt R ( E9rpF } F.P<|[`p8%.[t@HC9lA Hó(r B'xi{PJ2G.BZ,t7ci=`8A !PšR[Bm78)R z"͐E 72Gfg;H9`a` PS#8`IG‘ *_aP ?((b ճ~ɐ$`  -0y*X±+= G8 {nP"L AG`(| Dw#]jW8D5^@g>AEˠv)Bp`P7)`@vЁ0 PyyvE4z{0`[iJ&x}BIЁ \ ']i.s d,؁0H}@})p$V0 ~SQP~Pn@~K7O% ``BPr(% ڀF Y0nː+=jACbcpMx1xG$9!Љ! @ @pyJpbWe hpJ`FI LDri`|Mxj芝ԧ f6*ha(Rq}H"~0  pj4lPـt(t1F.T Ȧ#8# $ `ϰ#`WbƗb8{gy!'V e10 HKH{8X8KhNHh 0 i 0{WG6O!~4p@n0-` -RZqN jCN4-b Pz*] @|u0 9@#h {PC0{\p0\(Dd ae 00b py]@ 8I0 A i`8+y)C96 k~MfpP0pAb&PX `'p 3`(B  RUq 2``@~Ut8|op`@e YV P FyVdߧPP2 Z0 !pPi P PXYBYD`F]9`AP J@0 eq05``eX+$q"Iu* ҐřPO K-AjA |f ^ !# 奿  a(hqjpPzȚj` ` zؚںڭ:Zz蚮꺮Jʮ *jzگʯz ŐJ*;[K  [` k[&{(*銱ڬ f` k5+=ڰ,;D[F{H.;4{ ` k D Vk#`b;dKK+ `9 4' 0 O{ ^$[[{[gK`0 rƠI@ ;[kKZ i`` {;[㺺POP / *۲誼ʚٳƠ 9㛿{˺E0 {p k Xyۿ|Lۭ HjP: ǰ V k 4\6l \{P; <۵$ ϰ3|HJ|[> GV|X̮9Q|Q\Bf|h 暰lܭl\bLƃn|xz|~ǀȂ<Ȅ\Ȇ|ȈȊȌȎȐɁ?n<[p,ɠʢ<ʤ\ʦ|ʨʪl7A  %*f˸*""K g]!{d˳`  K,L뜪pjZıaM [_PK`KM@p _  L ,9`q q!$gr,tP<һ[  @ ŐQрK K ߠ @Yx zq{*``e;Mp   `P-Qp=`ٌ` @@ +x68O>`*EV!M` M_ZPUm Q 0Zغ pY)-@h;X!HaL m} }` o@5Rǝ wDR`pݻK _@ }}IM

 >P#{嫠ˡb!Z6 6z01JУ?z7wܫ@ -߰{P;2a}aQ g0茞9^N閞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_! ,<!2'72$83):3:3#?3 44Z6ZU:ET;I=FE=%$>6B>2D>,L@KE3KF:iGhbHWIKSJ4SL=>PGkP`XRg֜inOgʲzݴȵʌ»ż{䬿1vĿĿؿg̫Fö÷ÈwIJWźŴƻQsɻɴO̻ͣϽϫϏоѾѝѾtҾҠq٭ܼܶܳࢨԹy H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+%<F_Nt]?d۫%vΧOx^]xO;z+ݷo3~1{7 N>ԓ^;'~gQ=SO B/8=S7cPs ( ݋O'';1!?\&k:#J ~F,}H/ >^_|s $H &ِ;}D}#CjM!<\zF]JL|Ӆ\? o=(E"U~[E(CKF0)YO2pW/A!pS?H :#@zѹs,)B΀;㐣D(}; T!0#_98 ǘ\?G ~1 7 >;C-~zشCT+C:@4B>NTÏ艬 ͵B:Ip &%ɘE~Ϻ;i09d)c>aF$KO.LC>3?7GNc:@{E<,dT(yJ. MBX&b n9ɍX73%CH:1%c~O@P i?VPlP~oTۺ+\E`!42Sb? ZQ(+Ԟ:Г5"Kqnh$X"{'X?_\!3(BGX OBqLb,#~G"谎I S?@ }p#zA5XCHJ7/^䁂!'='P@=$%U F$Q%hVLY ? ܑ;C) @>5X T:0.p/ I,xO1n1tl#QztϣrG:QKJ `@za\ AV =Az#:7eE r[дX ς<hAlz; )aX *?>Z&cjf7z hGKږD;It3֖v0Ef u(oIbUbõ; }m[I`pDG<:A$W$DAh< =/D1@ $w`enסFu@yGp qN-rGO$PD0 %wX8N:$ ,&.KÂ"E,e#w`Wbt2hlتfeXp]` ¼{_}>%XO]pyJĠa%(߬׽\3YO @0ܡ  @7L-~фMZWE@ :0 l C xկV pJXP$`z!(@t8`EvBaUjչuX ]pW`VH k0Td[I6W#\p3 4:H)P*q)(| T R`@*@2N =H > >wO< %B B.  ;0ϑ7y_ ;ט_ `g@Xɔ_&Q0h!TYF2U&>r[IhxQ<'tP]fubX[ѱUz1߀ ڠ qшcZd1Z0":$Z&z(z5P)ڢ.02:4Z6z8:<ڣ>@=J*?FJLڤNPR:clڦnp8Z?"j*|ڧ~>J? " 3{*ڨ: !tΦqq&m:JJ; > WwGliP FڪzȚ;j!5P 0rw y` ʢڥ̪ Z'8MЫYh*::EZ隧!uZpZ9z!! i hJL+(*k8>Hk &0&ǭi޺D[F -6 '{NP;I MV{X;zoZY`):_b{hdfnFKM pxz|۷~;[{۸k ^s Ӑ۹;[{ۺ ЌA* @ ۻ;[{țʻۼ; ;` ;;[{K{a*a`޻[{ʻ!`\ ̀ܛ۽|! ; ˹й!{(*¾뿵v uPPh h`vPc` [ u@uP 0@ $ 4[рZ#bc,|hj.!u P p P ـ h \x h ` `60Y\V `dP! k `` ư˲mܾ02, v v `0,Ȅ +# ! B 6P VɌ ` 1`` M` X<` v Х0 a0x0ͻ /&a0 @Pʰ ip` B=ϫau` ` ,a Ü6N(dܻ<  ` p P8V0w`82ן@Ԁ؂L x ` 0Vm ˁ~0P {,gͻim= tmxm d[lƒۼFHcpz,< @ r0x_A( lpߐP w}Ӧ0g j۩!!` , P}̠MD@u# 0?= w ʀ |0ο@aBR0P+ BF~\/|۩NR>)J(A:d-%zd>]+`/@{xqS*n>!jNs>.Pi!&P p ! @{!!j p7 `':죥/@p L@ߐ 6 .!%'@ pI{ p_ P3; s) n/; /Z ?J =`$Z 1 #:P8#}!j`! #ji)u)YL/!Y}fDZ/7ðg0p$n?z^iv! 8 ߠ7PAvvWw?2Єj"q;"jZ`._ -{/>P;   D'mV [",!‚&%0[Ǿ8S)UdK1eΤYM){OA%ZQI.eӢ ЋW ŭHYzL񵀠o("!4$|JᎵkK|!@ 'E Ф`k}d>Ye̙5oƹgСE&]tPߘ "+d6m1Jζyo'iɕ/gޜguG^u4;wгdwy[{__}Wp@ ?TpA3A#P%]B r ;*pD-DST:KtNΔkaqd̩n4yTrIZK,$2˦RȪ^񂍂GʄN" &IH;px0!߾т84PsQFJo9 :G*. &TAft+!doNH@Q\seIF{ql.f@%D*h 46Dt7W^}5G.`q^Pk=)ggЂ"- O a`D=wal")DoASz $hX1"2*QDxvK`q7Ex XАJ١ (HYvF_: ≬ZV!Z:h뫹E"ikzjLm zM PVxK6ĹV?ep O|qk<;|'.|t=D'}uMGuTg}]d}q9yW7^ f㣏*!!W>MNU3y+^zrʼU$/~u$3HsMz7p&ȩ'(@G DQE lV(A\]b`oic7?LR敒@-pD*:` AC (@@<TFBP@Lct! ͘@ Ʊ5!@I&]l)x $ Cl,"3/]X P!յ hop@| B#YvR ,&@A 4\rC ~SE|CA Pb- | A{3^]k? ݀F#Kؚyp xo$yɷʨ+/68@!@ |Jv 9rV H/cq%kA4 L[ A*Dn6MUncRa @p ܮztj5ڍjC (Cg1y!sf%.u^WNu81B8p[ܛˍpv';0{vw*o2TSIh}Bup3h}W+:լcIᇃxDƞ6Mu㌓-mKl(ׁSd=nr\-  тg8C@ǀZ.h<^BR9Ɨk2A,b|<+[Y;"a`iVeG<f[}Be7(laAipp%@BE ~IA<-8ȃ.V@[1 $/!WX&'~ `CB4\,[H[J4(p< O# #;h;nЅ U Ws.55Z0ϫ=PP7,4-`@ 6h[eˋpXiˋ>\CqCٶnShXDqkD8`FL7Bl+C,JԪ6&DDOP-QEҸRԥSDEݒ9UVtE*#"(N U`Z$\ .jkHЂ:p 1c<[LƧf^|Ɣ `[0Ƙ1@m̒n0Cӆ#3gF xM!xBb @ *cJ[؀>yG#Gy\ kq$G`(AP(0S 3`;H4DoNGqD-mDŽ(͹X9p0?!E;LI#pF:n#HRQ&@дjL2p"U6J%kg-`S PꞸT˔8+VJɰKd4ZO}*9i̅˺Ԧ`L̆ѹ"L_Ih f Lŝ($؋U!̴M mMgt ɵhM$8O8-8 $O;DOPONOe5Ʊݪ AxP PVPV ` 7 Є Ȟ8j,:Q I k P dP(Aʌ OE ȁPQX A(z` » J) Ayh #-$OUo Ȃo@,Ү(;E$:X 88fIp3Pz @U؅8MS;Q -kH $HBň'`ʌxJ#$ RxDUX0~dqU QYM,U~\1'O0 CJ)(hVSmU RP`1'::5cFf*"VVIkV}U:] 0KM3)'KO '{z --',؄@ Qk?V[U!X`Դ#u. }( 1]贴YYÈL@+o @(\{ 4d$Wt>Q V]4M…Mmqy\͌\K˽\9܏c \ Pѽ9QM]\eтpQ]ݞQQ=z[]X pRҕ)҂" d=ՏU^W> @T;8APT s#* =`M_ׂPQ[ؔ8lXV01j__DXւ؂քcsK3ӜH``~MPkLɂX1¿<N v ;’=,%a8ayY--ڔ`p<ՃboLm۷̀oSA ͹V(aV<Ăx;?>6N HTgmdG\OLPQe,AUUNXGZdeRvel^<_Ɩ .exdWeKT cmlyedFEeŰNJckE|L[??!:-#l,'B`m `n:@ox p6R Ne$n pֲ` P :CFȋ@(H X t~P5Nu䕘w| g?0OBs DQe4` GPtYU-sqʄrVRsjDul 祁wU`dWXEYW,槄?h_ PWZWb7Sn*gh7;*o٠b@ 8If[ ڄvwsc8f[[NXD{/`EA7I^xoq+Wtɋ7 €! ,<!2'72$83):3:3#>3 44Z6ZU:ET;I=F$>6C>3D>+L@KE2KF:iGhbHWIKSL;kP`XRH33P;sOzs T(w+ @R߉ѣO9=5=OTH=8r B!>?t`]l]C!11@t = F>4s>tt}NBÏ>г_<Z(Ow%z:饪H"l?!2$:%_)&iAmC5SKDIL?F`=+ FHI堋ClC(H h !v*Ɩ[24mT)N:mG(mp4!7qtƱ4﨏3` 1-T'7$IH$> ”-T1ոB O_TP P  lWP  PI ?v  )uU p_4!OyRa 4W9aX$dY9_&Q0jkb^sG&rU $kFd0v`` QuQu@oUuĸly`Zĥʠ\Ǹb١$ l%,ڢ+a)e*;u8:<ڣ>>/DZFzHJLڤNPR:TZVzXJaYjBڥ`b:dZfzhj:[zk_r:tZvzxfڦW Xq:Zz|j@{pO:ZzZjĐ#:Z*Qwv& "j`ʣzº4QG 5P rW /i;ګڭ*u@<~Czt:Qz#QW#@2 F@@tܪ;:\ʨ9: Kw M{(˯Pꯄ 8 1 J %[*B;ʲM*Uș1{ sUx7[&7&KZ\{F+M{Y۵d[f_{c{l۶n릆o[v{@vJx۷~[z[|[\F и;[{۹;{ۺ;[{ ɰ ;[{țʻۼ;Իɐ @ڻp 4kg) 껾۾;[{ۿ|[\+k \|̿ʰ `dJ)02<4\!,…@&\(B\D,L Z@0E 0 @ Qw Kƿkjl6 :Ä= *8  @ԙ@$  lPr r`զ}ڨ9s\k _Ѱ Q`c]`f֐Rq}p P#,ՠO ԅ @ l! `F,]ک}[=­-_ n QZ Z˼ ߐpp߀ fpm =ս Ԡ` (- ޖʾF~W::YuQ' 0= WPpp 0j>1W Q\sp@pZ$>pQp e@-`pPw Ԑԋ 9 V ٖd 붬rL9c`Xks8Zp ) o iͻ` vqa 0R<@g-(* <p!Đ5`Ƥ s;nr`>?ô묯g l|ٮ` Ề~'E,''/pONht"  z P^E ߠlL)mB{510OZlʝO|ǵGM SKwp d< < l ` oAc qu`@utP~q oWp q9 f\,,[˨?[o8^t 9kY= P0a Pmn.dC%NXE5nGW%[VI)UdK1eΤYM9u!A9"7b}eSQNuUYRWaŎ%[V*#iFjYqZݷs߸ت(`ĉec^ő%O\`13DǡELYZ+Zk1plܒGƫ *DG9ٵGܺ^ٱn%d pqC8_g^ntUU}[=8Pcq)/ dx-vaBn(r\YX(,-(j<0RtvqkHT(~{ghUrV7iFȹ!Yul?noAٓ[HLv,~׫tIoB q C<",(R"Ae/cAp;֡MFƒ"da Y8,k'kpSP; kC Bv!xD0KdC얖̘SbxE,FewUbC%fQbܢxFqkdBʈF8#j܋xQ{4#r* =QUN\1!-D.RF= 1 U*b Ё4Ax`8!A9@^2I`oUR%S( Y>)y *Tu @2zM2ѪWCӊudp!R N~E$Tq N VPw6X# (ƐiNN+jQ-#@ zҽhH0%3nQ qѭ)dj$WLRozppA."B&Y#@O*02]q[OU~oxD0^AƁbY2#TsafG7LqA\+E V⇀|HcLxs*D c5M%-f֗l,6`P d;{ں|iQڐK+`{Ȗ%mq[薷o{Wz1.rbfs{]EnY!)d8 i٨FbWΗģ'.XC,1n' h5%-FYM }2*[Ѽu Q24f+B"x0&ȷʂt@~aZ ВJِ )^cVqct&D,-_8EЊ֬=Y DDsI3D;$'; O6FD@!YV @8Of1P(C vrcQ [AکFQ `~͐4M5t۪T,Kin`mm(Vڱt b Qt^[H' xAB"a=`:ڵp >c[lK )[j ))?:$CVcY`&|;+\`Ʉ s@Hh 9sҁV?)ֳNݭsקv2ٸ4nv=K6&q;lbwCXAy;En4AՇG<2 >x!0kH~rJ5\?bx 8 h{``sP,zpTHuYV|ܨC:Q2@Y"()^*g{, X dAx?nh ):&'FB??*{k>4nX1HT@U؃( @/=nȆb{;An3.;^I82lAnh1( Bo!BZ#t$N:&sBFB+(7YC0 :n )nV 9":CIC5pٳ&P? bP,E̟kDM"l`iCè CL HўTMtNDE lSl bE` F`db`,Z4[=,\FjFg#Fbj!mhhpK4GBt꫾CX:؃\HN `N,8MP"3#Ц=覠$Jީ?KŧXVH6d[HI(9{o:4W@?pT˔B/(;@{<  ,,S'K> LX2x$V%nHH P,f@8قC5prJ?@ dX)XE^ ,^u;N!c@PQpSNeEvx[ +[-̧FGN f@.@eUv6pQ␁-;\!l*9)HLr;7iug` %bnHd؁qb>L[%g=p l+L)@UúhbqN |]`5_i> ~\Հbej)깅eOq%_Vˬ̮߭>!YkM`.W_߄n&ykj fkn `k&`}v>jjRe aƫXBðabLlXl֎c~(*b\LnXMK+& (xcIj m(`D^RI26Mr^jnV^a2-clV)UMf=2mY_Fp$:dp`ICwh5(pI50PoM5hbvhnN-@Y @ (F8L / T8i)ivX:@ bnqxqF=j Hj햊ol /-> 9]b`orzrrr)k/O^01-sBV5wJrduT)OPՈ#H ` @kxm R+`.t;GDP%Vŕ jr6=#)}=bMi  )ai$=WXWlT1Y3I57֨:<ٓ>qpCAbPhJ\K)LJ ee?؎Vt]_ab`<9fyhiE{ʖ(n}{wҺOe]L7,ՑA@7UxÜV\Ѻ (9v|޷|ie{)YpNyEyɑ) !΁znX6!yՉ׉Jӎ\cTiP뙞yaמiI)IyfY+]zp<=Eֆԝ($ s7}AE,Gs73F~(~<~ KUC}e_w'J߹_~~Ҏ^ȂG$l FlFϧu,h „ 2l!Ĉ'Rh"ƌU#Ȑ"G,i$ʔ*Wl%L "0 IVGx(aV p ,4Rj*֬ZV+ذbǒ-kV̂ M SD聅|lǁA $2bCЗ,rm1Ȓz=k2̚7wLK0A$)XZ:PM0`Ag2ܺw7…{f*P0uA >Pڷs\y8ǧ,r rT낝;y 8 pŭM i7;'}5PATTi!H !Uq@p \oq !H@@.M@V4J \!EՇ#*$!&p[3X C@L2GzN%%$e$Am\a&i&u 50'}iќv :ehy(:(::zDZzi+j:V@! ,<!2'72$83):3:3#>3 44Z6ZU:ET;I=F$>6C>2D>+L@KE2KF:iGhbHWIKSL;kP`XRD33;sOzc T(wN+ @R߉ѣ9=5=OPH=4b BӇ!>?p`\h]C!1!@s = >0s>ttֹ}sNBÏ>г_ӎ<Z;C(:lS>Ow%zN:饚"l?!29%Z)&iAi5C DIH?E_=+ HI䠋ChC(H g׎ !uƖKJN kF:3 ~} $ !lͯ];#q;꓇$H"C[ 9` ?G0 5IxR.B"&2D0`>P 5L9!6|N4 tO4cL-N:1"> 4vc8,8#66L>P;;M3́>K8b'b:@|4B>IӵJ'5B y,Sꇃja w?0P;X9M"x A CV1n@; G?v +27Oȃ E`BRu=9z[G&]S~$TN`V%s{xfO4k -"Юi$QBEp֏-a?x/ o 0 <@# &<7O9Zx*DCUĖ3 Xk(1J@D(ny`:('<&'h70=0j#4soOaam !R! =!}(  j4DQ6="!#_$p6 Ћ |pО>Di*_ xhc:: ( j4p%X{B -H ! s Q6⑎:0 pFaWL(!}4֝@WhW8-c"e~RhwBիsORԥ(zH21GIC넞 p4$HDHJcpPC\ b8q$lcGkE<E%lgKͭnwۖ !AyR00#b[5(La-E0bOEY-x@YЃ8J#t wI>N@JdHp.0HA"#CER.0ojv4*OBibMRidq` /׊3Aq<0d Ga6b!=S8@X葇l}4bv7 F^IQJZ|A#5Q B/} i%^  Y#fmM@/!h;@SsV= ( j(uT`ҀP,bX^' 0Th 4Z7&Xut<qw=PpG#x .({J!zW!lF15ll|:l syjAd v sL@ Y߄&DiP10m/P6T8O_qT  hW  PE ;wvЕ  P@)q 0_4pKy`ͱ 4`H"cY_&M0jkb^oGt&2U $kFd v ` uuouxluh ZE\ax^ kP!z(+a)a&;t4Z6z8::/@B:DZFzHJLڤNPR:T !U*>\ڥ^`b:dZfW:gJ[npr:tZbS mj~:x*ڊI*Q-; ðsQ83[&ǩ" V{X;BI;U`bk[;_;hjkzkr;\@ | ] 0A 0 M7 { ƻ+f|h26|ÃP9;`fPfP] >iPf (\`Ǜ̐*ð S< *10 ;{ŤbL`j˲<˴Lll8^:Qfȃ `P` ] ߰ ͎W < 0@ ΰK@ D0 Ԑ ( !`qʁPY0`| `P *\]Ʒ\ |uN| i p i | W=m#lM7Pt"PY 9 WPn`]P ] P >P1p| g~ @]#>`A` d@-_`Pv PKԊ 8 U ٕpc p벜n 5_֔ XmjPs4Z` %} p ֕ Ȱ ipͺP v0ɽ0N<PD<>}> <2 N:bϚ--Я.?/LYMYЯt{{j٫m`NWp 4f >WZ@:p[|* JONlK~8 2R~ 2 hd^7 w^ dŢU | m\-~UZ~]p0: m \p=c  m|t us0~m W` r9 bL,˰Wl˨?Wo4]s4{WT.˞hr߰ hrm@ .dC%N\WE5nEUȔ$YI)UdK1eΤYM9c"#4OwLm^E*SSQ~ZURnWaŎY J[bΥ[m\y"hkau/xcȑ%On Xel)ogK]Dv艥vf@ˁ!Y.6й"bQsn/g7lj7WuY9Yq+\>կ0mk^cVq0z'0rS(&C:" FЃv<&h` :c EJ,m^F(@H b>"t/T)Ԩz '!'@RJ&0 JEzis0P!j1JQnV8n c0٦Tdf`m4(A nIN;VZtT4"(!8lP!bpLb5{Lh:jsJmtUHH 0t6!4ЃTp;TTUErUw]vu]xw^z^{O=pY!r N@HJa"& FkƄE"فnvOS @8Dfwƅ$wg{Rgly#f8aZRy+X8`OLeYv-9DzMSJ&:Sf{2rnf,mH7 ⑁\!/5DmfI;)a8vr<(Li5l@D: P׈{v[}w{_x Wh,O0!>ty.@Єh~aIHh ņOe~ &e18XBb4( a@`H t wO-`=PG$as4 P+Ta|ZPLB.a}27ah7PKlfRQSxŧ䎊[gڑD,1ZbH/QkLF8Z$y7Qe6~?Fc!_=&IBwA+d3d%9HEf6'lA@*6F Ek:0& l8(Ғ &5mJURTJAb+0'D1!5H%2@/I_S9Vժq#Vjڰ*׀k $B5aϮs # ΅ kc" yT ox9+B A=@:ٱp >cl; !Sj`)=y2BFY \$|;+\@} s@oHh8sV7)ֳNݭs}קv1ذ4nv= 6&q;lbBX!y;wEf3@ՇG"=x(vkH~|bJx5\/ bx ( h{ ``sP,zoT.%(!ӟ>@uYVb|۠C8Q1Y"(A)Z*f;,X bAxmh )5:&ЧEB??{;k=mP1HTTЃ( @@/mb{;m3.;]I01\mg1  Bn!Y#t$܆6N:&sEB+ 7܅XB({9m)mV1":CIC5hٳ&P?܋aH,EkL";l`;iBCL HTMdND#lSTE` F@_$LFbE"E\#Ae,flF8h*FF"kܭl`ZnoGrԬsDG $aA3>yŊNVx6PTIuPm@+ Acd7 Ŷ#zY5(REY-URQ&E!dX`lSG`6 FMS 25gSo< >,?@UA%0C#E=FD}jF L#VJeKψs3 44Z6ZU:ET;I=F$>6C>2D>+L@KE2KF:iGhbHWIKSL;kP`XRDs@s=s1cYt;ܓ`:yJ}(Nd>Ë>\BPŃ"rw"˃`Ƹ,QBh6;2`}i<ԩgC9 ?3 cO;WN;봳MsH"P>ӏ;餧"!O$HϗajA@ݧO-qËI$1;ԒI|a:"D$Oy '. :> < DCQ^;{h0>j\O.aw,~Ka4lTE):lG(l046#lt팰43_ 1+ŐSSzc:lCML L):ܢ5>C+ӼcN6BL6ߵS M+c|#{|!఼"l@$! N̲=lM:p\Of6i? I?ؠ><1>_D>OCD%"= J(5B }˨,Tǃjq$w?*y4P;X 蠍"|B%5l@zd) h> bP Cq@E<R,DUГǽuؕ>JPZ@_.N$JhA whUB>c+Z: "vZLy((^/g؂w >#! 4 n{ՓXB8!SJp 1Ŧ8CȤ A<'A#r3l"Hp6^qsCF0byL0V="b!BH B!sYhǒVL# H,xl#$XbMYE1glA :/a6P3c̰CϐvLc 7Q5GD"0P QXg(l gDaw4BHcz ++ṿPm!0ES[a:DASQp 9ZH=3MIU{0 щ361wT"ͭnw pے !D;4@3w00$p[6(\!m.I0ULPWizSsVm <h! Gƅ$H^Oa, &\ $u<$e}z(r|:ͣWՓؤEƫX=ugAԻ!7SDfȑTd!yT=8%rŽm0SB\d-opuC i` 8Wo@V- 'l#ՏGKl 73_}K n#Q,@h*<0"SA^C nv4!^( غ@0P DC5Xbl'|u6Fy"_ѡ%D&h"T J`@AH [W@v%Hh~luQ9 `^Ǧ sEH6v4QD;D<);6{|8|0y `@G:CP:яJ``Q6lƒ<6I^#CЗ:t@$/^CX-gMo@ ς]*'r{n:lCxQu!>7A i/G f2xb)!0 k yRgp0H _B\W)N"(<$G>qz0 C@o`{r:x47dt0|@4P4 0W7tURVFHR YP@7)UF 6 x`nUH@IGvE4U( {jHPP @0gwp z DCkr`{6P)-yB=ttzpӰ)9BL)p@wW&ab'aHWE^0up fe bvbxw@B Pw'$G8d  vFyGp pPgy &0P*"1` &D i 4&zȴ"DTAF~"E M0ѷ 032Pk0 )ayTaPE 0 p2~(w` f^Qbxyx"hf]"@{p^U/qqPP@Q9Y  5FKUZx Zj`NPpr w% ZaP %T`tqj@@™ qWZ ETو)ZH@p|YV`B,0՛lMs!ku & &p/UW}Jp/k2U $lFU`zr \\W_\u\ ZZ˥Y茀&ڢ x%4Z6f17JXB:DZFzHz/IڤNPR:TZVzXZ\ڥ^`]J?*_fjlڦnpr:\J@JQx|ڧ~v Ќ^ڨXZ_J{Xک꥔ %:ڪ:Xv붚 +kZȚʺJJ4p_W%@ w|X Fڬz蚮[jBA/@0tw jp ʤۧ쪥u)#@2 FЭz*::eZʒ!;Cw Mp0[YA : J -2JJV*ZX9 `tZ?k&ǯi.˴b;d NU a[l۶n;g kt[v;{:w۷~Iʷ[۷맄{۸dKF P{۹;[{;[{ۻ+Ƞ {țʻۼ;[{؛ڻ;Ȁ @0Kp B<ĄE̦G`fPfP] JiPf@ 4L`@Ȝ̐*ð _< ΐ*1Pś ;ư\n v˾ x,Dkf ȏ `@p ] ߰ ͚W < 0@ KP D0 Ԑ (!`r˂PY` `` 6Mì,|LZ| i i ݌ WͱW 3`, \0 @ P &  {`  ,P`0F P=^` Ͷm !hp } W+} hތ/} W 35 ̰> #*@-   P ՙ0$  kPr r`֮ڰ-Al{t gѸ ސXwh-k]PnՐZy},x} P#4-O M Յ @ k! `]F,ڱcµg  ^ ؜߀[A] ] ߀pp ex] =ݭ Ӡ_ (  :}ߖPN_=\C:YچuX'E 湚PkjP pPhfhհw 1k!1=p|0p L]`,.` dP-_Pw  Ջ A ^@ Mږ@c 帞,zBj`X`nXWFp @EPG ǐp zm  /=M > P* ㈭> < 2 C.n Х=-0-з;eu~X {PXpkp jP{@ƇmC o࿽ }n@/KE4'@{'/ϿPZ O忎،p"  w  Uh^N ހu1-J 5`Obʧ[?ʐǽݭpu?+0PPG  x h{I;d?yuЌup0zz9v(X /Wp ՠܰ}9 np¼c,̴cl U@ \+P *l#ؤ@ rnqzHP 5nG!ETI)UdK)YM9uOA%ZQI EVSOREr^$5*Wa;$[٪bծe[q]"JK_r&\o`ĉ/f/#x!oe5ovygСE Yi|Ifkŷ'@yr)8: p !J|C؆H&A!BT1B# b-O d`2XL!1X:rl IѠHX0% z$b6P+dazư;'La mxC7P }؛28$b&Q^]Ns #FQCxŎƉz1EaQcxF4U$ch4QdYxGq{IꘘQc ?n9YdX7HH$Փ'>. ZIPf$em0AO؂%m E  t ""= e13R&SΔ5H `LhR- Et 2yN ST!̡+^#פE7υ;` NEdDp NV@{j,Z#  BnB'"HjpR-+]BREmj0Io8 ER%l,%*[\ S:mqzppAPN"F\-l[#ϑ*ccQzք5yDAA=i?{V]>&I;6LqAd%H̊VcPL3,!$0([Xr䰉lrreVliُae[6kZb^-`n[~o{\언uq\2Wbqssb=gu۾4# #>,T'!wV=i|" 5e^A7=M 1B-]=!v AU240+B`x1&WKKL2!h+7d""m@h1ERЋMUY[\5x t猕Xc5j(m`Jcx6H`]:e6PNA L;ԗcY+> ۆ&P/Tqqb(FF??3=/T@S5p T=HH:/=l >= :H@3TLSԿ, ix1b ?%\&xBmf넮B+\b]10Cن1ن:`pB`S,,89h޳&P8\aI$ WlHEC)aH E)XܶQR4E5 lW:FdLF@cdPDFfE*E`48Bi-jF]CndpT;l$G2sTOdrwD8ƛG0Bpz{ǘ>bHЈHT*>>C:؃WPN XN,|SIP%3&&=(' LJ?,@O,ƮPᳬ6i=9SOѳXM:hdBG`n)DxSQ왟AVh 5S%PA>lʹAB"&XMUcpܱNC2$%ktQ*NDJJ„/ ïV9!9K#z,myC$-<$$b]]> )J0DPWkP<[8tkP I|P85 +ؾND@!:F55BUVG\YdZ$0\E&U }R`a,R@7MF87d2.4ukS>J;?3AuB5@D%EeHu|ATI]PhȄ@rTM̋gh顑hp@UU-VmUXUPՍ .SHՑU3RJBYծAK6`p S%i`V2Hm}iW&0VdU^(( :xK+)8?,Z ) &d8QxyΈF0Vcm|peBs1 p9  ɞ00N!>:Ѐ XPm XX m0፰5="H&ᝄ,S0*KEE LX1%.#n'H H-ֈP-XYi5jhYѭ|q hb= CN%]$$,_u@N!ӈP`Q6An'VT^&=Ch06ec#pMab>"ebUfds&Q1?\thHhw0ofpmX*OEخ3Dm`Rq# g$8Ȅ TB쫀&v Vm 82녞ni e ) (gW`ݥfVjaj֗6NkV u_ȱǍE`0`k-kI m|dd a(ᎀ `iBt5h/ f9f)^h+FXW0X,hNЀ)$mnc&Vdsވ(%=1KAc@^m^SFfbVa!0lFnrg7]um؃2;5eNnlXd>nX؄Lv65(wxAPoC= Fhfh -GQ 8 )F`L . မbf` ʪ5 Tn2݆a\qzq&9UaXwrrrr0s&U =-k4 5GSJ[6'7(B>Q@ @;to2DikUM,dpOIP(4 @7!T:FT;JD<"=FD=,)>6C?3NALC*oCLE6hGfbHVIKSL=yOXR;ZTDsUp[VK4WWXc[Dc\Kd\S|_vhaMebU8cijdTgniZjkcrlZWpsupdxq[@rNr>s{tfxVxqyq~yklzw-{a||k}&~s~PQp`;AD:O`uVJ|&ˊeYR`G>ǸdǕWK|1ZؙM#ko׉ E\)cẌ́s@ݷaWתp{KZgxߴ}ɻüw4y੿Ŀ޻FöRíĊWźŴŻŅmȻʳ̟پSμϽïоРБvѾѬtöӊwٮܵܯܳݼݺߤᬁԹйèԨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+%<F_Nt]?d۫%vΧOx]xO;z+mݷA>L33P;sOz T(wN+ @"R߉ѓO9=5=XhH=< 33"2>?`Rt]C!0A@y =qD0s_>tt}sNBO>г_ҳ<Z;';lc >tOw%zN:饺"l?!29%c)&iAC5s rPT>v=+ F"P!JrrGPC'OP{ÇHv%a/1"G C Ĉ5tw0@L;">^;1;+8*H,7ρ8:lsO:lN5(̴M"?@1BkO*?O*X P#KN>HD>X,(ל V,,OL !:"+,4`0r Lb7 H-d`t9IhdlcŰ+hˡ^Mx|X0;45l{ Pg a uI:@TT<+;:$ܣ߄0Wķ<`Z)% q –xUw@ 8 _EAW\W $#WDpx`{@ Gv#HAG D6+r);; POWtR@`;0Sd_}mO~@oGCԄO{ |0i;VP됀 H `f y Gj]{?u-}o# ?` ] #|pTB0\קus=UqJPnIF` VZH"u[w00A v$Ghc u6 Py_R`ppFkG a*PkBKЏ@qT PP;k"LĤ"H[4F(p~bL ZP& 037 Z' )@!wt`[`(V0P` x'kgPS`5+ْ&e \RxЎ` @@A@Y`O:U'DK U!QR̰OD,@FUSb Si N"` , S`` ,[sjc00i HWSX ;Дm2`ͱ ;v=g` 0B)3ue`9!ju& & vaIt&"U $kF4) ` AuAuoEuhlvZ *way d9* q+2:4(_&^4NAu<ڣ>@B:D:`EJLڤNPR:TZVzXZ\ʥ;ڥb uG:fzhjlڦnp_q:uz|ڧ~js@fzڨC:Z=-e کM*Z* =*B[ڪo*V # VufnIn6ګB_@ʺڬ*Z ; P7 = qGf Z WJ;w`VP<:,B;T:<:" 0бY @&K\۵^˪F70SXlP7y dۢQ; ʣ]'z|a{W+@۷[{{۸ [ˣ{۹y빤[|IP к;[{ۻ; {kۼ;[{؋ ;[{蛾껾۾;[k P˯[ദ њ)aD <\| Ǡ P&l pj !\6|8:<<')]*24NPRm}}}F p -} Qi0Y o ]a^0׀դ YP L +9-FP w-` 3`j mm I04/P@* H@א R.mP@r P ^ M. Y>ƽj} g@ L}) ,>q24nu^=䙬=JSPg"L`:"q$ ^r rjY} W^( ^P p\~0rP ^Y t 9J[ fP܅- q V0ݭ   ~Ȗ?ԘEeS@Pk3PSfLp I0nqAٗP  ư  Д -l# N >gl2@oɰ z B @` - Ռ+ʐV @ m^O  0lSP+^g3g|Sq0 9ɯ.g`ߣu<^@ Bad, 0 16 = rtrt&p~7@m7ހoP''ÞFFÁZP7wPWZ i@  L uPނeVA .dC Md. E5nGDVd,7TLK1eΤYM9uOA\vѣZJ@Re0-b[S ) y~֫`^XPo_1ZYaJ&;2/ 2䗍mPСE&]dU'SVkK6*5τDdݚŶ  0 ]K˽dٵow)VMYc/S{ϧ_}t ,d"&_F"p³BpC;CCqD1%&A[tŅ0qNFsqG%AG"F$-E#tI(dJ*R(,2I.[Ih002A-TFM!\sN/) BA-: 5E84q!u;#(m9BndሆрYBQTS0)SUXt֍('nɵQMǑ!!SD->Ѣ0 !m BbXD$j<(.)D\18xJY+PXU7m_!`(-'n6| A !n8eQ@K2mzd~ z6L!4$-hh$M jINf6A (D-x4N 5qr0qx,Nm6zv0qlźנzyTmFhЂ~1im80kkʝʥT|s;sC}tK7tS냿&l;8 NI{ rR p! vpv/ (ۂ ?x ۠(Ȍߒ ķ18 ksY ruXW}NIq2S.`lrZS,ѷr=F3 Z&epG*>P#LV< v$ o6b6X;SaBL0|*`AX fF*HE0qVG _i R a ;VO^s4 Ҁd JУ*0^βEt]Z䈸8%/Q$w( $`j!2 S!DhCf/Xe>)PR$fE䔦[Rte0Lh 2Y6qf77kSYLMoS8N*EmB:yO gCO4CgA O&TѧAO.Tl臚P)h:+!eTZhGM MJRf,Ȧ,&pg#JzR VFOy+j )2B';x@ b@hIVT$[%MsU1a{*\80nf$Pˆ Y ,0Uȫ`%4$]aleK톺6 \08VB-liۧ0 vc&&k|[[fwpw%.];я6%\)m!Ղ"nwCw5 3;LF;Hu  · AA6q=!oߗ2HPAڸ6z`x=H,SH48 TS#M̺SaF 0mXJ"hD yD9qcaBfld(O Mre,kU2e0cїÌ-Y2󙡜5ǙBmvs#VV[su|g5Ah&J5O FCh*z) _u5/*I*_ PTL 5 ԋviqjzk%Ry 6TXYrY0 LA%8,`UyHVDP?blGW TD@{:%lGTW@@ T'JY@Gh@@3 Aofh \@lA2{A&J* f"hjlh0rXKbRiBkD)q(([h6D?HMBXD 18r>1T2ܱSWT(0D1HC[]z*3$j D$2\Db'l50l@p@3x xPQl>pفU|;Wd40Y, Dl]_la̖0Bj{FEYAlh4 +K8؄YhLya<N0DNd'|D[DJTIʿ8s84)"UhU78R2kPuF4E m8Pp"dsqP{Ym:.CifR +โ) msRDR,rR+ @Y$tGxKV 0 p+2eq,z)7@% @$T05TZ 0]dH KEꉃE>pTgM|XHP U` SWX%SDI Ih DLc(?l m|'͜Q*ɢm("!ʢ TTs5 [ղFjh%`Be¶՟Ac*+F k} [k[5۽D"XU+0a 4;CB+.7S`(e(t%(!(uѝZ%` +mJž4q]] ̓v\ %f !PJ,1<=m4^^N&X _l e$YxЪa?}H"m}\j(e/!- _|`0"9`r`(߅,h`HE.G@)A,dC.KD2[fH]m ކP8Yȃ`x<-_Ԃ_0@r7jنhRLVhY3h|&N.%~.Vnf(z<("8bO% u"(z|iR)8F{aȃECji<%BRvjjQ~VPP^^mh76!:/Aij }X6iN8pmP>) 6ȹ)39>+L:={ll)QhO96 ^#$ǂȼcskM0`JS#ڎ6ئe*X[cp_vWO8`펓O/Mt6/&h>:, }+8N2Os&9rn0<v0!WELm.PsEj>bl ȀSiKvuiS(m8mXoYPYq'o oG~9+h*we|aO6pww2 xGYv¬x7Kx:xxۉˆW-,ٟ Zhx9oOK<@=A ^ fˠU[ `oʒ ܿM«2yS7(za IuiFoؗy'Kq' :|z(~(ZY(JjOZz)B:)b@z\pz*m)'$  xQo*^ NXP@zXPFT%%llZ{j-MqE)Q{5j4WتHrnq`@"B=k 4 4ZPA/0 /ŝʻ P!ooE"p ̇ `I,"1O\1Έ^,P X@ X6[tr4At7<; 4 M& t&)oSpi+5m'Z@LEAh@-%\ځc˶ۅ'i5\L2EDŽ I0@V*8n8蔺%Pܺ o1r {Ua~ygmr0~ oSba#G;?<?$tpAՋٛi11C]+>_},'! ,<!923,83*93#?3 557?Y7VQ:C@<2B=+F=#%A9OBJD3JE:GMkGmdH\SM:ROC6RU[S8XTJ]VEp\dd]Lb^T~^~jcUniZsm\Wohytd@utukw}xl0yy]nzt|R~~no:Ab0OFS|s%[&4?b>Ő`m~"O{N9?ab9~O?# o"'uQ@~Hn[§^Χ9QjkƮMჰtٱ`@f޳|˴tP6žѾҾwĿۿM|gwѻĹƺƵƺƠJɻɴ¾[̻qÚϽߒ޹tӽw՝ժև٢هڛIJ۴ܸܽܭܲݚ⢹溹õۛ뺧 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+e<F_Nt]?۫eLs@s=s*dYt:ܓ`:mI}(Nd>҉>\B8B3B'#A- WOh3H>QŃ"Bw"ɃO7M D)ِ:u"b0}iO<ԩgSO; O?跟&~G0b;갣N+hcdjGtO>M>NzPb?B?D8MBَ|&:S)7 t;N?t]Î=C' ; <  23!@P+C婳Fp4eμ39@1| , t'(A{sN< h$sMZS E 3M=4M:\3:-]s͂:1,2 ԣ 賈ÄӾҏr3|aϤ́@BsjΎ}އ(n׳(,<'.Nz?2|">pGC?4!kb۝͖ǟ~"臉A V q4;l ГB*ySO`8ӈ7'! Sê:X1<Š2 0@cx}h @b q(OwcQ #b$-h W0W'jed|!zэ(K̎|P V0Bg+Q#0O#VЈ8 a/`/G r<d8@,LRdOS#E@ux| 0`~}Do_2`J$sPVR`~G"0y@ 0yog)@uA W kzSUprgp{ P\"${] _2]ŗD!-pUJstg)D,p, 000uER0H J@G` sBnXk0F`xf fJ0yjUcRpUs#` ` 4B?l(!(+ G?p-^X|=I1bB)@jTv_'u,`EW@a! Pm Q`tX"vL Їw !B1?ok@   P_Crp C 6n` \20 @ ") bIG0 @ `r LTL+_` ǀÇ@$u~ꦖ|ɖ Řmɜɞə ʤ\ʣ\ɨL}ʬ\ǃm {˸˺˼˾,zN @ ʼ<\|؜ڼΓ0Ρ8|<| p =]} =ѵ ` Üdz+qA (*,.02=4]6}8:<>ӷP ,|,)!  a?PR=T]V}SC]ԏ(0M}X]f}hj6ՎA@xmwM p O@wtM mx׌N pҷ fi@ ҹ )Ϧڷlڰ۲=*D ׉*V T@cOvVI - bM@ۗTV`# ` ='+ ߼ Pڵpߖ}AߴZшĞ*8T0~ =@ ~} OPܤ pI:p @ 0p@ !ҟ]K8` ep@H` 7A P=`b~۹ b`~p `0 ."N@I`' #0ٳ20'P Aҹ 9EP8 J^PJ X@ @c뺾X]抪~ t V )``0c`zx%N IP > 01 -w#0( KPw@N  W@dPeP Ӿn:;kf /0j0jN@@ V@ 0Nz.́3^ #@Q= _0 BE gP e p?7"fj-o]ܰ r˰:p*P~0ݨ0 0'˳+?/c@ `@M O@ ܆M /.JMԎ# ]À U@ĠRO9W0]߭nyo J6)[ùWkd !Ip0TpAPiN ei {wcA @yLLR0@ =~wk;7l2>IЛI6l ;VXFӻ{SA԰h R8e.` ]&A4|]DK`=3أ/Jvi0۽[`Xh@ P%E"sŶQS>h`>c{_Bk1YLO&[O2Ի ԰ ٴAόOtOaFDO #n*) С7 Q2܆`:QU]Q䋘r-B"Q#[)<&&@$1xͥ 9MN"r1s Ȝ'[![c3,-N!j1?PxҦjlx G* 8MM/X e &S\Q>UGG* ) PG+v4hx%K0X2ɐl @;UZYUљ[)kl*Sȟzl X@(:@i< n%Z0Wu!vm#գ+H+qM2P̺Rh,uy nIW8?h I[K!n5ʄڅЀҍ*YتY,r قq9'YZ;eZnZA(+1C{$KnbX>H)@]XZԒeQ@[NK( 0ۛF l/m `ւm]*E%]ݒ*m#^h0Miˮ0Z-] ؅ SKmuM>R z^0xޚSsk(/8t m`Λ!u2(riREޣ"W'%qmf)^ana~ay:C8.)rv"aᱤSll؂V VannSzMb*b+~'!aKxIȄLGL4NcJ(LxHxcHB6Vcz0 02>+c5.4*8=cFVcG~d?dIdJdKdR-bNv)NeQeS>eTNeU^eVneW~eXeYeZe[e\e]e^e_e`fafb.fc>fdNfe^ffnfg~fhfifjfkflfmfnfofpgqgr.gs>gtNgu^gvngw~gxgygzg{g|g}g~gghh.h>hNh^hnh~hhhhhhhhhii.i>iNi^ini~iiiiiiiiijj.j>jNj^jnj~jjjjjjjjjkk.k>kNk^knk~kkkkkkkkkll.l>lNl! ,<!1"?2 83*9393# 434/7>@<3B=+E=#%A9PBHD;JD2GMNI7.NRBOKVO;TPDZUG9ZYb\Jb_TkdTni[sm\XneRrtativth{td@u0yoyt~yk[}}mPOo:Ab0UFNt}(&4?Mbő_@5m~&PNQ?ab}C7O6?'J oR"ɟ%'Q@֩~n̦>uYƪ\Qjk͜ĮqMჰװG@ffݴP͐6žRw~Ŀο߿lMgéwݛѻĹŴƺƺJȵɻʴ[ˎ̻qšϽߒgtòwԝԠսև֮ւƲ۳ܸܽܲܭܟܐ͖Թ漹ĵԛ뺧 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+;F_Nt]?d۫vΧOx~]xOz+ݭf#~ł{L3>Lc@c=c,dYd9ؓ :aI}(NT>#>\B(QB3B'#AӇ, NFi>rŃ".1w"ʃ6Is 4)P:#J bB-cg=c1=$tO?sπmO=N:3KY>O=砓P>ڪkP#;_ye N'AqB1~"

c:\N% 8<7 iP=>0>HT>7< <0>L6,SޠH=1+P GH?z t`C(7N 3BW=ݣR@|@! v1 '}AxR!9*!nVc^(  #}8` q@ w[>> cb@I a؏;Q x# 9za 7C^ #6P.f6[H\11@>x ~DT$q6xIgHF'PP{AϨ &!cB( +RT4b!@?HNH?GǩB+YTqPy@ X!i.`A Z{ (HHxaBn^\P$q`64! CD$B(@ .MB $Z#^H [p$j=Kے4pA[Lb"(jKMr:%ABvg.}`! @"!`$1h?R8,SUwt<yG4*0_x&yP@Iz^ pHى"b .1HCʤr^vayE` cYiQm*QRsW/|_$IG@t"GZ.T(c!  if#s\fK(BZYHv7L dr\fHpAkšM8 r~_K=eĢx "2L" Bb1?CxHG;X/Se@,@1X`:<ac6-b h-` x0дE` @mjcB; Ig:P'Y, p X@ :`-8 TpF%f1ЇnW@l7qO o}@B=D]F}HJԸ R=T]V]|+q `b=d]f}hjlnpr=t]v}׹ ) w}؈؊،؎؋{ק (pՐٞ٠ڢ=n- L٦j10گ= O0=ڰč-  չ uY` 0ּ ٭ݼ 74 ]}cm|ڡUp R g QOPQ E p = R@UPm 8  "0&0ֽ ('⼠ /0]6~8.ג ՠƶR !R`ʰ R@    ^ P0[ #P : P b `M5؍5`6@   .> `~~;Z P +!ߚ-P P E0VZEP݀_ "ܵ)#p xּ 4C`; @CZ`h j+ @ 䖺 j+U  Ug>~~P뾭 E` 멀P @` "sG "^;p t@S00`~HsM~JR[챜ېN X  1Q P@p _ L`U`f. G9aP )yNC d@t Co@0 02!P'`Jקݧ ?KK0:@S.԰Y_ ?@kf?jX 0q?@ QޯoMo.^P p` n ;0!@x-4I3LIRӤ& eyjff`t^Ó 溲a ~<&: f6s)ntF2 B@HjP*t@#h\(@,T'A!OT3iMmzST;iMM;bC:O0h!\@C蠅A B "`_b3 ,ȕU'4@ qTsk]zWAuƹ쁨,gSi`aX/Aa(2=m @&YR2!miM{ZԦVemk]ZV+.K, aJ6ah#YLieڄ@*xDh{]B"nw˗ۊ3/0f1Ik8Ue'j`dB lA.8 fn=~W&36.L/ [\)96,}{LQ _X`LDM|bg/.KҀAtD0`m~!b$'C$NqL.cP/^|D,/( b#E4|f%3kf3)=@s^JH4Cm&tT!M.!Zғ!GgБt=-5K+ Ӛ&u9iTh-u]SZֳK:tHvDF\4yj`&6mM)`G.v'}lFriH\x&Ҩmmt!LgřO8 ;l4yixޤѹ}&c< 8,2ęr3]CUqNdri3MFؙ68]^`lt !~l@'H?K2?7.Ѐk/h<>2E@@gH&XT .(3 da@$)-˳x3A ?ly< k(YA( : PP"#LB;-h8Or1{B+0B> h(( )y&y1xgkP"1"(Gq6Y!1ȩ9|4CVl3^B?`2vh0i]l\40 "28_0"EhE^% Y&\dTf`JE$[VƃI3k93E\Ev\(A`Ax)m))hww+S?S@ TATB-TC=TDMTE]TFmTG}THTITJTKTLTMTNTOTP UQUR-US=UTMUU]UVmUW}UX]! ,<!1"?2 83*9393# 434/7>@<3B=+E=#%A9PBHD;JD2GMNI7.NRBOKVO;TPDZUG9ZYb\Jb_TjdTni[sm\XneRrtativth{td@u0yoyt~yk[}}mPOo:Ab0UFNt}P(&4?MbŐ`@4m~%PNQ?ab}C6O6?'J oR"ɟ%'Q@֩~n[̦=uYQjk͜MჰưsͰ]װG@ffݳP͐6žRw~Ŀο߿lMgéwݛѻĹŴƺƺJɺɴ[ˎ̻qšϽߒgtòwԝԠսև֮ւƲ۳ܸܽܲܭܐݟ⢹漹ĵԛ뺧 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+;F_Nt]?d۫vΧOx~]xOz+ݭg#~ł{L3>Lc@c=c,dYd9ؓ :aI}(NT>#>\B,aB3B'#A3, NGj> Ń"2Aw"ʃ6Js D)P:#J cB-cg=c1=$tO?sπmO="N:3Ky >퓏=砓P>ڪkP#;_yNe N'AqB1~2<+_S(: JBh,T*=$B #Dyq@Jp?(q=)N\<9Ɖckq( GEJ L]:P<1 0޼B)<0:| BpK$)3,L'ƸS7:b3ߥ3 S -r|P^;% +3pqGLx>c:\% 8<7 i`=>0>IT>8< <0Ї>L6,Sޠ=X_s Pǡ:J`ߎ4)8l(.nz?)pG$xÂ>HⰃ>1+P GH?| t.pC(7N 3Bg=ݣR@|DA x1'}Bx!9*!nVc_(  #s8` q@ w[>> cAi b؏;Q xC 9za 7C^ #6`.f6[$I\11@>z0~HT$聄cP#P@L0  q10%a[=pv\J B,(B"{ `ЂJBw<#8U \hc%Kjc!Y|H` vЃ<$,HA t)x L[^(x;ܫ G-PP&CHX Ztp QI$) 8 <(Ax9ذCC(!vX, OB8BSYz n7"%ze~"WH.6ֳ:j`W)GAi,h"ڇ!pՆ&Dw(D*qeWAD {H‹ Bz Pmgg[Fݣ#Htq JLmKMr$H=_ź;dY$D QB p^`"nC"F]o0D" (I~Ka8;v@"_ @@cHo[ˎ9+!c;+<=-M{bZ:JYjSwf}+@ @(_(gp +?C|!Ltc&s| WH*>< @ !\C]p \R[ȁ z X~" .ûq-8Hp} 5X8P#@@Yd C@,Wt@he (M l =վv2 $m,P8@Ʋ $H-Pu(ChG=`;L*<@.`ˣ0A 0{' VQ@,%PAbp^0p鵝mBBQo  B( d1 d tH.*ED%AoGc,u @w;>KTg:5XzXf ucd7;!ҡ/ (@-0K @ @8py؁p# 7ރ.AM K~6o 4%NXm~@Ģ\_(Lm@ (!#pት<\8`z2^@~@ t%xq%aG~  dw)Pw'g w`'{ `]$<_0b o=>}MU ,'bHeg`uB2pbx  7uap cX$zp`F!(6' ug 6pq87 gPkRe(Qgsp   ߁411(&`FMă&W-`}=BJ1rހr)_cUwiu'0abo m чa)x  $p FэXzl 1 :p`Bp0 o0&%0 +RJT ` s LL+bP d gGdS3C0 @a%z @)6 p 0܁~8! _' M %@h,x mP~ZH=yYY (x"p pgz gp*p|IZr&0 aE6߰eВ1 PW *a : P-]QU P!6U  mPѰuYbL  [xz  P0  pxIPI"p @ҔZb  dBP!@  &0 & qz'sTtl"0V%m"GV ·x a ! $߆,f=)0Ue [ ?]FP Z! `z Anp`ѦqZذ|ڧ~T zʧp @$p :Zzک:ZzJyZ`ꨐ*ZzګzJ `Z* :Z* j:Z抩 ȺlyT0j@~ʬ;*p 0  ˖Ѐ Ѐ ;۰|:Z";$[& 0 o@ n 0ʨ pPg`zP0]zPR;T)۩ p! 'x 0@~אGPo5ۧ{ @0 `m`U;[+W Юƺ! m p ^t }JK K@0{ۺڨlٰ [P+t g0ktK Kp ^@[{k۩ʔ]{Q;C0 Аd ٻۿڽ m0 K0 K˼@G0 op"<$\' !5;  Ð`[ PP[JL'˨?`!˧X b^r:╺ 0苪kV  Vi>䒮顭 F` ꩀ``껀` "sH "0>Է< v`T@@a־,V}:QZܱާN Y N N+1R `Ԁn MVI./ H:bP O\D f@v D|A@ @2!'p.Պͧ ; z@6nެ=_ ?[J?NY `U?@ RoiR._P ` n Nvv|O /fy?8DKg`m@@A[Jذ]bM43vƈ,ݶeɏ0۪#jeΤYM9ub[s;>%ZTh<#|SĤVKy@1E*ֽCSUbjʵ+fH.9k]heGW7h #pTb c gСE&]iԩUfkرe+Sk]S@GB2=t4Mň=ܷ{n\r~&xW~ywy裗~z꫷z׾z!ϩXvZ1?lɥe-}L~P$` x@&P d`hK&_-eee>(FJP ]œp iX9lݧC?"F&.J:Ζ'^P4`ɕ hMhF iLQc$cxƚƈIeBhڬxFF G"!3Ų, zP#Mc#HHGd%ˈGLG3i IPѰF! IËn\Wђe--8I$Rd/It(f#*Id45]fSqMp"ʗ\J/. %A'Tth4#TЀ!D@2p%S 7 jFThE-zQfThG-JN_bX&( /A 6/Q'a 64D9fX ejS+MhhUzUfUi/E >s0CIiLX0 8^ m-OAqg(p@L8Um$osX&VelcXFVleL~Փ$9V0iQ4b7 Td3@iCp N@ՈYWfҔր5`jZ66A2HZ5\VUo{^w~z&g*C:Mmx5n&@ag C1!o |dB fp#^O]A#iС0hT"Xc{4q6t8p];X3A_Fa[ \lF4b YX-1Q|xÄ[ < d03 rLN~/#fs g<~rs;YЃ|hD;*ЄftcDGZ=IǫTIiAzңssS5tz`AꔉԳeQ|eWZ؈5d[|e(7Jx%NuS\4=lp&m +щT ؼ-.l2> kԕ51F Oϩjurf"4p#< '&CN hC6h*i"'"˨Bi\ 4a  (íp']ηIR? =!E=jRwS(T mxPk v.PP2*@BT@F7ҕ~jP#YﳶV!QB&k+xivLUWh(dmJ{F9% R˷|€(U *0䜜 \Mv Ahe:SNĶWm/`}|[UFr} .:/3 `k*;H'p+K/ (?۬f#C#>lp=k0YS?S@ TATB-TC=TDMTE]TFmTGUO ! ,<!1"83*93#:3 434/7>@<3B=+E=#%A9PBHD;JD2GMNI7.NRBOKVO;TPDZUG9ZYb\Jb_TjdTni[sm\XneRrtativth{td@u0yoyt~yk[}}mPOo:Ab0UFNt}P(&4?MbŐ`@4m~%PNQ?ab}C6O6?'J oR"ɟ%'Q@֩~n[̦=uYQjk͜MჰưsͰ]װG@ffݳP͐6žRw~Ŀο߿lMgéwݛѻĹŴƺƺJȵɻʴ[ˎ̻qšϽߒgtòwԝԠսև֮ւƲ۳ܸܽܲܭܐݟ⢹漹ĵԛ뺧 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+;F_Nt]?d۫vΧOx~]xOz+ݭg#~r{L3>Lc@c=c,dYd9ؓ :]I}(NT>#>\B(QB3B'#A#, Fi>rŃ".1w"ʃ6Is 4)P:# bB-cg=c1=$tO?sπmO=N:3i>O=砓P>ڪkP#;_ye 'AqB1~"

c:\N% 8<7 iP=>0>HT>7< <0>L6,Sޠ@>0+N GH?z t`C'7N 2BW=ݣR@|@! wC1 '}AxR!8*!nVc^(Z  r8 q@ w[>> cb@I a؏;Q x# 9za 7C^ #6P.f6[H\08>x ~DT$qcP#N0L q0($a[=`v\J B,(B"G{ Q`ЂIBw<#8 \hc%Kj#!Y|HX t<$+@ t(p L[^'p; ܋ G-N%CHP Xtl` QI$% 8 ;$!x9ְ#C(vX NB82SYx n7";%ze~"WH-6ֳ:j`W)GAi+h"ڇ!pՆ&Dw(D(qeVAD {D‹ Bz Pmgg[Fݣ#HtqILmKMr$H=_ź;dY$ QB Gp^`"nC"]n(D" (I~KA8;v@"_@0cHo[9+pc;+<=-M{bZ:JYjSwf}+@ (_(fp +?|!Ltc&slWH*><@F  \C\` \R[A x X~ -xûq7GhA}k 5X ~0P#@Y`B@,Wt he @=  =վv2 lr*@4 ƪ $@+Pu(BhG-`;L(<8@,P˃( {A VQ ,%@Bh ^ 0n鵝m:Qog ΰA  d! djtH.(E@$1oGc,u @w;.KPf:5XzXf uCd7 ґ.@-0J @<8pyqp# 'ރ-A- J~6o4A%NXm~@Ģ\_(Li@ #pት<\8`z"]@~0t%xa$aG~ cwr)Pw'pW w`'{ `]$<^ an<=}MU +'aHef`uB"`bh  'u`p cX$z``F!(6& uf 6pq87 fPkRe(Qwgrp  ߁401(%`FMă&V-_}=BJ1rpr)_cUwiu& `bo m чqa)x  $` FэXzl 1 :p`A` n &%0 +RJT ` s LL+aP d fGcS2B  @`$pz 0)&p 0܁~( _& M $0h,x l0~Z8=yYI (x"` pgz f`)`|IZr%0 a56ߠUВ0 PV *a 9 P,]϶QU 0!6U  mPѰuYbL  [xz  00  `xIPI"` @ҔZb  cBP 0  &0 & qz'sTtl"0V%m"GV ·x a ! $߆,f=)0Uep [ ?]FP Z! `z 1np`ѦqZذ|ڧ~T zʧp 0#p :Zzک:ZzJyZ`ꨐ*ZzګzJ `Z* :Z* j:Z抩 ȺlyS0j@~ʬ;*p 0  ˖Ѐ Ѐ ;۰|:Z";$[&   o0 n ʨ `@f`y@ \zPR;T)۩ `  &x @~׀F Po5ۧ{ 0~  `lPU;[+W Юƺ l ` ]t }J; K@0{ۺڨlٰ ;@t f0kt; Kp ]0[{k۩ʔ]{Q;B  Ѐc ٻۿڽ l0  K0 ;˼0F0 n`"<$\&p 5;  Ð`K P@[JL'˨?`!˧X b@B=D]F}HJ PR=T]Լ.v `b=d]f}hjlnpr=t]v ɠY]m׆}؈؊،؎x|m h@^؜ٞ٠ڢ֑]ڭۭڰ=Q`  ^ @t 0 b pݿ ڍ ``=Ӻ0]}-֥ק P R@ROURP`ۙ R PU PZƀ!`  "Pb pm( .⛝4^6~qOj\}-g Q p Oݐ p X@WOߩ @EU  ` P,` ּ 6MPd @5`6@ p  ->†08^~6հ հAn U@ UPQW[ L]ME g] mA WP p` 0;06 T0Z6@m 0)0>03ؚ?^ ^^PPOfVP E ^ -0 8w!_- M Pe? ; S0c`@FH/ާL} XԀ݀nN U@ ?fÉ]^q? !p+(ώ>P3P0;p68O Soym|RsS Z aO bU[1OfO0 =@ L@ [N |Q! ^ W;uA PEF࢘K.5nG!E$YI)Ud2Lay#&Ɇ@BHAStaJ5T`իݨ)RKmXZ1ceJ#3'&k3*O9eˇ3LMO>Ƴמs)|7|W}w}~?[XZeCwF5rQ uz dȸLd`-xA fP`=AP#$a MxBP!P2|` hJ]Is4b%WaCQH!'Qb^X$^QV"Akd pa;dC8,Р4 S0A ! bG.vtz5 ed|5Q^lsgdt&A] UW )PH%\` =iЋ^74/#O Rt̎ d?PSЌs6_ n˾@Z#/ِ.Ȁk-⯼ݣ2Efdh*@0 0e@ AIB7E"@OɃa?T[-8tt.t7 | Ҥ;t :+06"23A( p@?Gh.U #F|p6Y؀3!1)6l47CR1†\^b:!ggxE"3#AaH S?S@ TATB-TC=TDMTE]TFmTG}THTITJTKTLTMTNTOTP UQUR-US=UTMUU5P ! ,<!1"83*93#:3 434/7>@<3B=+E=#%A9PBHD;JD2GMNI7.NRBOKVO;TPDZUG9ZYb\Jb_TjdTni[sm\XneRrtativth{td@u0yoyt~yk[}}mPOo:Ab0UFNt}P(&4?MbŐ`@4m~%PNQ?ab}C6O6?'J oR"ɟ%'Q@֩~n[̦=uYQjk͜MჰưsͰ]װG@ffݳP͐6žRw~Ŀο߿lMgéwݛѻĹŴƺƺJȵɻʴ[ˎ̻qšϽߒgtòwԝԠսև֮ւƲ۳ܸܽܲܭܐݟ⢹漹ĵԛ뺧 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+;F_Nt]?d۫vΧOx~]xOz+ݭg#~r{L3>Lc@c=c,dYd9ؓ :]I}(NT>#>\B(QB3B'#A#, Fi>rŃ".1w"ʃ6Is 4)P:# bB-cg=c1=$tO?sπmO=N:3i>O=砓P>ڪkP#;_ye 'AqB1~"

c:\N% 8<7 iP=>0>HT>7< <0>L6,Sޠ@>0+N GH?z t`C'7N 2BW=ݣR@|@! wC1 '}AxR!8*!nVc^(Z  r8 q@ w[>> cb@I a؏;Q x# 9za 7C^ #6P.f6[H\08>x ~DT$qcP#N0L q0($a[=`v\J B,(B"G{ Q`ЂIBw<#8 \hc%Kj#!Y|HX t<$+@ t(p L[^'p; ܋ G-N%CHP Xtl` QI$% 8 ;$!x9ְ#C(vX NB82SYx n7";%ze~"WH-6ֳ:j`W)GAi+h"ڇ!pՆ&Dw(D(qeVAD {D‹ Bz Pmgg[Fݣ#HtqILmKMr$H=_ź;dY$ QB Gp^`"nC"]n(D" (I~KA8;v@"_@0cHo[9+pc;+<=-M{bZ:JYjSwf}+@ (_(fp +?|!Ltc&slWH*><@F  \C\` \R[A x X~ -xûq7GhA}k 5X ~0P#@Y`B@,Wt he @=  =վv2 lr*@4 ƪ $@+Pu(BhG-`;L(<8@,P˃( {A VQ ,%@Bh ^ 0n鵝m:Qog ΰA  d! djtH.(E@$1oGc,u @w;.KPf:5XzXf uCd7 ґ.@-0J @<8pyqp# 'ރ-A- J~6o4A%NXm~@Ģ\_(Li@ #pት<\8`z"]@~0t%xa$aG~ cwr)Pw'pW w`'{ `]$<^ an<=}MU +'aHef`uB"`bh  'u`p cX$z``F!(6& uf 6pq87 fPkRe(Qwgrp  ߁401(%`FMă&V-_}=BJ1rpr)_cUwiu& `bo m чqa)x  $` FэXzl 1 :p`A` n &%0 +RJT ` s LL+aP d fGcS2B  @`$pz 0)&p 0܁~( _& M $0h,x l0~Z8=yYI (x"` pgz f`)`|IZr%0 a56ߠUВ0 PV *a 9 P,]϶QU 0!6U  mPѰuYbL  [xz  00  `xIPI"` @ҔZb  cBP 0  &0 & qz'sTtl"0V%m"GV ·x a ! $߆,f=)0Uep [ ?]FP Z! `z 1np`ѦqZذ|ڧ~T zʧp 0#p :Zzک:ZzJyZ`ꨐ*ZzګzJ `Z* :Z* j:Z抩 ȺlyS0j@~ʬ;*p 0  ˖Ѐ Ѐ ;۰|:Z";$[&   o0 n ʨ `@f`y@ \zPR;T)۩ `  &x @~׀F Po5ۧ{ 0~  `lPU;[+W Юƺ l ` ]t }J; K@0{ۺڨlٰ ;@t f0kt; Kp ]0[{k۩ʔ]{Q;B  Ѐc ٻۿڽ l0  K0 ;˼0F0 n`"<$\&p 5;  Ð`K P@[JL'˨?`!˧X b@B=D]F}HJ PR=T]Լ.v `b=d]f}hjlnpr=t]v ɠY]m׆}؈؊،؎x|m h@^؜ٞ٠ڢ֑]ڭۭڰ=Q`  ^ @t 0 b pݿ ڍ ``=Ӻ0]}-֥ק P R@ROURP`ۙ R PU PZƀ!`  "Pb pm( .⛝4^6~qOj\}-g Q p Oݐ p X@WOߩ @EU  ` P,` ּ 6MPd @5`6@ p  ->†08^~6հ հAn U@ UPQW[ L]ME g] mA WP p` 0;06 T0Z6@m 0)0>03ؚ?^ ^^PPOfVP E ^ -0 8w!_- M Pe? ; S0c`@FH/ާL} XԀ݀nN U@ ?fÉ]^q? !p+(ώ>P3P0;p68O Soym|RsS Z aO bU[1OfO0 =@ L@ [N |Q! ^ W;uA PEF࢘K.5nG!E$YI)Ud2Lay#&Ɇ@BHAStaJ5T`իݨ)RKmXZ1ceJ#3'&k3*O9eˇ3LMO>Ƴמs)|7|W}w}~?[XZeCwF5rQ uz dȸLd`-xA fP`=AP#$a MxBP!P2|` hJ]Is4b%WaCQH!'Qb^X$^QV"Akd pa;dC8,Р4 S0A ! bG.vtz5 ed|5Q^lsgdt&A] UW )PH%\` =iЋ^74/#O Rt̎ d?PSЌs6_ n˾@Z#/ِ.Ȁk-⯼ݣ2Efdh*@0 0e@ AIB7E"@OɃa?T[-8tt.t7 | Ҥ;t :+06"23A( p@?Gh.U #F|p6Y؀3!1)6l47CR1†\^b:!ggxE"3#AaH S?S@ TATB-TC=TDMTE]TFmTG}THTITJTKTLTMTNTOTP UQUR-US=UTMUU5P ! ,<!1&72#:23/83*:3# 558C%;4@<3B<+E=%%A9IB-JD4JE:FMRMCVO;$PSERMYTEYTK9ZYb[Jc^TkdTXfZni\Glmsm]yscxtjeuo~yjydqzrb|}m^~~RZO>pC]L0z2uAO~'5dw}bk{VP`@JbHSzR4br /MKCd$:{dm+ުTΡVxd;7z wƃ@PPhƘKk}ά2wĿ}FöθijmƾƽƳvǶǿǺɠɼ]ʽOʆ˷q;TüѨӝxƑ֮Ķyj˖̐{ԶԥԃꦹܻyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ 9F_Nt]?۫I9uΧOxN?>GrgW"9X|D;TJ.4;c;蠟;"Ѕ~g;ݨb>|3PاDԳ,ÎA%(T#t4N>|ҟ@က@7Xa{!n@>=0; 4EM $F+P8# ZhB+գ;簣33$$>#ȓON~.JN= ш<#N8@ܑ>aOwS&z7I)th?#a??9c!K7I)4ᇌ &`#1P9RF18pr$y"nSӈ, ;08LQ^8p (>xaEy?Dq;a)R[XD7s ɂ|lEE`6]8IrC0x;1I>+;!9<" c >Ё+J=ϸ3CN6P2ɸN' . )I{tÍ@x>HR.| Mlq)EMC/|È2< -N4ч"+8̲ l88@6B̠u=:̂ |ԓg )SޡЈw#`!$?+Ů-bFDjB"g P觇'C Յ-vQ- MhgtSЈm) و|jF t8yj^ QHA6<*x;AzdZ rC B.+h"BWG4wB ( }4C(B?0 l F?\Zʥ.[l98} nH%u RLy !մR0r8p vb,XA$^ !&O8>\iJ0@T$xp7P HWь hFԱ &a Piox' {h򐆥q$ȣr~,ug,O+vn::5I#H'&0w䠧=& uh~F3h! UW7j D 8<`y<h!0w@re\5$:#&BA.|Kͯ~]2$h1|2*Bt<(ɀ1iI⩊" I9a(QÐ sc.B`%QkK2t`#);m a \`@ #!%2at!Ɵ%PyoĎp O<)x9N2KLA  "Ŏ,SFB ;lWhzG9,iga"@ĘP"e88`Kr0eM ǾШg4!7Ptp0,A?Ȃ5R}8PZ@@@(!OA@)! r  x(@p(G..p vxشD` ` Bz@@3 b9G1 lǁ8 ރw.A XN`oXšJZZ,"m:HE*`zǘp-jBd'8H9`"r XS@$>`KcL| * dX?$@)UXHnt,@ eh9!.4V!<taGSGzXT]C3@Vp (:C Rc ʃvZpCP3HSp 1pjDbxqed07)dP}P Pyy%}D4z`WhG&x}RP  XxG@0I( b7{70q70쀆qP~LGL5 0` Pr(/ %Mpgq/PDi@CX$Ggpx  0  $FUP`'0 Aiadd=H$.'Ixyd /O8@@jշ kv)hdXRqpK(~@ th#t .1Pg`lm?3"ǰP b@|)],0{gy'$X Pe)` `H HiЋ'⃱GƘ %rH$QH%h P 0{7DO!=s` @=9r 1 "( L isCˣN4-g zA  Ӡ vWPk`p$# U 8 KC eܡ  b :9bP =y Q )[)FM8\A%kp-#g,X% %& v ,` T&p,/`Wa PWPf P `0  Xe'(Pn'e ~ Q  ZP '0ǗP0p 0䡵xHID %  @!e  000T X%qIXP1 ` Ӏd26*WAh_ Ðz%':_әX0эzHAfej0Zz:j j zњ`%0ںڭ:Zz蚮꺮ڮJʮzjگ;*j ð KJZ;[{:ʮ [$[&{(*K ;ɰ X [JJ?;+[F{HJ-ʠ 0 O ! O+ ˰Z O e;Ī@K۶npڴ > s47 9@Po22 j %]kP2e`*;*ڰ` 'X; p0 9 v !.Jʰ@] v p°Ƌ " p[{{t ۾ 0O!pм ۸ۼX < [p ~p@ @[||닮𻳎SK#P5м@  Z]ۼN ]}@Y :*%@\F|G1\ۻ)-> 0 bV, Ön/H': -DoLGIKQP!@Z\^`b=> 5h}pi2,!np0@Vu)1$a\(CD0p 0 @ِ mڠڒivqT afON@}p`0 O ON`T@' r0r`@l~&aԍ T ΰ΀ N ` G `W = p ~p PZ{z{*` @| !aʽ T` T .~ mp}} G (d*E j,.~` Tf  2N=>-j 1 R "B_1FFJ LR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogСE&]iԩUfkرeϦ]mܹuo'^qɕ/gsѥO^uٵowŏ'_yկg{ϧ_}p@ 4@TpAtA#pB +B 3pC/g! ,<!1&72#:23/83*:3# 558C%;4@<3B<+E=%%A9IB-JD4JE:FMRMCVO;$PSERMYTEYTK9ZYb[Jc^TkdTXfZni\Glmsm]yscxtjeuo~yjydqzrb|}m^~~RZO>pC]L0z2uAO~'5dw}bk{VP`@JbHSzR4br /MKCd$:{dm+ުTΡVxd;7z wƃ@PPhƘKk}ά2wĿ}FöθijmƾƽƳvǶǿǺɠɼ]ʽOʆ˷q;TüѨӝxƑ֮Ķyj˖̐{ԶԥԃꦹܻyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ 9F_Nt]?۫Y9uΧOxN۸?>rgWb9X|T;TJ.4;c;蠟;"Ѕ~g;ݨb>|3PاDԳ,ÎA%(T#t4N>|ҟ@ @7Xa{!n@>=0; 4EM $F+ِ8# ZhB+գ;簣33$$>#ȓON~.ZN= ш<38@ܑ>aOwS&z7I)th?#a??9c!K7I)4ᇌ &`#1PH9RF18pr$y"nSӈ, ;08LQ8p (>xaEy?Dq;a)R[XD7s ɂ|lEE`68IrC0x;1I>+;1N9<" c >Ё+J=ϸ3SN6P2ɸ'N' . )I{tÍ@x>HR.| Mlq)EMC/|È2< -N4ч"+8̲ l88@6B̠u=:̂ |ԓg )SޡΕTBO?\ࡋ.zM$QhlxB wX2p~ăX 9ʕ9h@& q4X(3HAQ|H qo H@VAKG*7<H:"ă)Q(B I"=ph/Qx"X"A | 7zlbBG>Јw#`!$? +Ů-bFDjB"g P觇'C Յ-vQ- MhgtSЈm) و|jF0t8yj^ QHA6<*x;AzdZN $T@ȅaMDJ&TR(e\rfE& 臫ࡃ@KZe+v v"('\T VɃ.XA )!6X Ps .V+5 $+B &ȕ`i*#}ԁ:v$La 3:s /2amCҰT=y@ԏ)eέ@;2)v\DŽ#h8D JF-2HZ '̡ ϑG#@-䥰Hα &D'xD1ف|KͯK|2&с\CXEBʁG!%;A`"M0IH. dV }D!Rl0:b@))Cv6SpЀ,0o1\`KcL@| }* dX ?$@)UXEt,@dh9!'4V!<!taE7zX8]C3@Vp (:C Rc ʃnX|@m H0Sp 1pcDbpxH&d00)dP}pP 0xy%}Dy_TiS6dEF$`}RPp  UwٗG@0Ff bͷz7p70q}EGK~ ` Pr(/ %Mpgq/PDi@C|؇4yG耟px  0  "6UP`'0 iExi FVDrrxpGrq@| n(rȅ](0 @ ` 68@ q(*P8Cq(bglm?3"ǰ"`){)]H,zx'"X  e)` X 3Cf'b hrH$IH) P (z6AN!~=s` @=9Pr~ 1 "( L isCˣND-g yA y Ӡ vWЁk`p$# U 8 KC peܡ  ap 09bP 3 Q p0?b j8IPi hQ@*ߪ P @@ DK° PЫTK$+ WXO; 9 b;d[fB뭝D+r ː 9 I& 'Ơ  @qk v` L  Ьg۹; p д '8 p`ʠLprtI 0} p`( k*2` 2P+ڻ۽ & J pk ][;‹ X p@ ޻ ̭ۭ KH#5 @  O۴R+@D ]}@Q( /*%<=J&;@Q+ #ܴ>p @ b@L&`hj @J U k ` ]$BŁ+<L ŝ/*}X :Ɣ\ɖm$У[ @ =L0;2P* 0ڶ p P{Ɨ\|J E[ /kU< * P a<,LΒ4"P\<Ӽ΁;-k2̯ ]`º "=$]&}(*,.02=4]M/K|: d=-?MA GP!@6PR=T]V}X4]5@^}_=2,1df0@)1$aT(LPt=-vp0p؈ NPؘ}؝} #9h2j1qT afOpN@}p`0 O ON`T@ ' qq`v֪ܸ@a  pppppNۣ PG= П7z'0{'  g}-@ @0ܱ ~ܾmPGp` !)0y8x@R$@#>%n ` Tf03nAG` G 0p@G^cxdSNbp T ZpP 95rN.yi FN8n]QN0 Y  G0 pp O p BP#o-`ѡG>pp 4 !t> GG)N fPWq)`qPg*d P@)"Naa@ D)$Y~Adnd>Àq9<@pA_ 1FJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogСE&]iԩUfkرeϦl]mܹuo'^qɕ/gsѥO^uٵowŏ'_yկg{ϧ_}p@ 4@TpA, ! ,<!1&72#:23/83*:3# 558C%;4@<3B<+E=%%A9IB-JD4JE:FMRMCVO;$PSERMYTEYTK9ZYb[Jc^TkdTXfZni\Glmsm]yscxtjeuo~yjydqzrb|}m^~~RZO>pC]L0z2uAO~'5dw}bk{VP`@JbHSzR4br /MKCd$:{dm+ުTΡVxd;7z wƃ@PPhƘKk}ά2wĿ}FöθijmƾƽƳvǶǿǺɠɼ]ʽOʆ˷q;TüѨӝxƑ֮Ķyj˖̐{ԶԥԃꦹܻyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ 9F_Nt]?۫Y9uΧOxN۸?>rgWb9X|T;TJ.4;c;蠟;"Ѕ~g;ݨb>|3PاDԳ,ÎA%(T#t4N>|ҟ@ @7Xa{!n@>=0; 4EM $F+ِ8# ZhB+գ;簣33$$>#ȓON~.ZN= ш<38@ܑ>aOwS&z7I)th?#a??9c!K7I)4ᇌ &`#1PH9RF18pr$y"nSӈ, ;08LQ8p (>xaEy?Dq;a)R[XD7s ɂ|lEE`68IrC0x;1I>+;1N9<" c >Ё+J=ϸ3SN6P2ɸ'N' . )I{tÍ@x>HR.| Mlq)EMC/|È2< -N4ч"+8̲ l88@6B̠u=:̂ |ԓg )SޡΕTBO?\ࡋ.zM$QhlxB wX2p~ăX 9ʕ9h@& q4X(3HAQ|H qo H@VAKG*7<H:"ă)Q(B I"=ph/Qx"X"A | 7zlbBG>Јw#`!$? +Ů-bFDjB"g P觇'C Յ-vQ- MhgtSЈm) و|jF0t8yj^ QHA6<*x;AzdZN $T@ȅaMDJ&TR(e\rfE& 臫ࡃ@KZe+v v"('\T VɃ.XA )!6X Ps .V+5 $+B &ȕ`i*#}ԁ:v$La 3:s /2amCҰT=y@ԏ)eέ@;2)v\DŽ#h8D JF-2HZ '̡ ϑG#@-䥰Hα &D'xD1ف|KͯK|2&с\CXEBʁG!%;A`"M0IH. dV }D!Rl0:b@))Cv6SpЀ,0o1\`KcL@| }* dX ?$@)UXEt,@dh9!'4V!<!taE7zX8]C3@Vp (:C Rc ʃnX|@m H0Sp 1pcDbpxH&d00)dP}pP 0xy%}Dy_TiS6dEF$`}RPp  UwٗG@0Ff bͷz7p70q}EGK~ ` Pr(/ %Mpgq/PDi@C|؇4yG耟px  0  "6UP`'0 iExi FVDrrxpGrq@| n(rȅ](0 @ ` 68@ q(*P8Cq(bglm?3"ǰ"`){)]H,zx'"X  e)` X 3Cf'b hrH$IH) P (z6AN!~=s` @=9Pr~ 1 "( L isCˣND-g yA y Ӡ vWЁk`p$# U 8 KC peܡ  ap 09bP 3 Q p0?b j8IPi hQ@*ߪ P @@ DK° PЫTK$+ WXO; 9 b;d[fB뭝D+r ː 9 I& 'Ơ  @qk v` L  Ьg۹; p д '8 p`ʠLprtI 0} p`( k*2` 2P+ڻ۽ & J pk ][;‹ X p@ ޻ ̭ۭ KH#5 @  O۴R+@D ]}@Q( /*%<=J&;@Q+ #ܴ>p @ b@L&`hj @J U k ` ]$BŁ+<L ŝ/*}X :Ɣ\ɖm$У[ @ =L0;2P* 0ڶ p P{Ɨ\|J E[ /kU< * P a<,LΒ4"P\<Ӽ΁;-k2̯ ]`º "=$]&}(*,.02=4]M/K|: d=-?MA GP!@6PR=T]V}X4]5@^}_=2,1df0@)1$aT(LPt=-vp0p؈ NPؘ}؝} #9h2j1qT afOpN@}p`0 O ON`T@ ' qq`v֪ܸ@a  pppppNۣ PG= П7z'0{'  g}-@ @0ܱ ~ܾmPGp` !)0y8x@R$@#>%n ` Tf03nAG` G 0p@G^cxdSNbp T ZpP 95rN.yi FN8n]QN0 Y  G0 pp O p BP#o-`ѡG>pp 4 !t> GG)N fPWq)`qPg*d P@)"Naa@ D)$Y~Adnd>Àq9<@pA_ 1FJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogСE&]iԩUfkرeϦl]mܹuo'^qɕ/gsѥO^uٵowŏ'_yկg{ϧ_}p@ 4@TpA, ! ,<!1&72#:23/83*:3# 558C%;4@<3B<+E=%%A9IB-JD4JE:FMRMCVO;$PSERMYTEYTK9ZYb[Jc^TkdTXfZni\Glmsm]yscxtjeuo~yjydqzrb|}m^~~RZO>pC]L0z2uAO~'5dw}bk{VP`@JbHSzR4br /MKCd$:{dm+ުTΡVxd;7z wƃ@PPhƘKk}ά2wĿ}FöθijmƾƽƳvǶǿǺɠɼ]ʽOʆ˷q;TüѨӝxƑ֮Ķyj˖̐{ԶԥԃꦹܻyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ 9F_Nt]?۫Y9uΧOxN۸?>rgWb9X|T;TJ.4;c;蠟;"Ѕ~g;ݨb>|3PاDԳ,ÎA%(T#t4N>|ҟ@ @7Xa{!n@>=0; 4EM $F+ِ8# ZhB+գ;簣33$$>#ȓON~.ZN= ш<38@ܑ>aOwS&z7I)th?#a??9c!K7I)4ᇌ &`#1PH9RF18pr$y"nSӈ, ;08LQ8p (>xaEy?Dq;a)R[XD7s ɂ|lEE`68IrC0x;1I>+;1N9<" c >Ё+J=ϸ3SN6P2ɸ'N' . )I{tÍ@x>HR.| Mlq)EMC/|È2< -N4ч"+8̲ l88@6B̠u=:̂ |ԓg )SޡΕTBO?\ࡋ.zM$QhlxB wX2p~ăX 9ʕ9h@& q4X(3HAQ|H qo H@VAKG*7<H:"ă)Q(B I"=ph/Qx"X"A | 7zlbBG>Јw#`!$? +Ů-bFDjB"g P觇'C Յ-vQ- MhgtSЈm) و|jF0t8yj^ QHA6<*x;AzdZN $T@ȅaMDJ&TR(e\rfE& 臫ࡃ@KZe+v v"('\T VɃ.XA )!6X Ps .V+5 $+B &ȕ`i*#}ԁ:v$La 3:s /2amCҰT=y@ԏ)eέ@;2)v\DŽ#h8D JF-2HZ '̡ ϑG#@-䥰Hα &D'xD1ف|KͯK|2&с\CXEBʁG!%;A`"M0IH. dV }D!Rl0:b@))Cv6SpЀ,0o1\`KcL@| }* dX ?$@)UXEt,@dh9!'4V!<!taE7zX8]C3@Vp (:C Rc ʃnX|@m H0Sp 1pcDbpxH&d00)dP}pP 0xy%}Dy_TiS6dEF$`}RPp  UwٗG@0Ff bͷz7p70q}EGK~ ` Pr(/ %Mpgq/PDi@C|؇4yG耟px  0  "6UP`'0 iExi FVDrrxpGrq@| n(rȅ](0 @ ` 68@ q(*P8Cq(bglm?3"ǰ"`){)]H,zx'"X  e)` X 3Cf'b hrH$IH) P (z6AN!~=s` @=9Pr~ 1 "( L isCˣND-g yA y Ӡ vWЁk`p$# U 8 KC peܡ  ap 09bP 3 Q p0?b j8IPi hQ@*ߪ P @@ DK° PЫTK$+ WXO; 9 b;d[fB뭝D+r ː 9 I& 'Ơ  @qk v` L  Ьg۹; p д '8 p`ʠLprtI 0} p`( k*2` 2P+ڻ۽ & J pk ][;‹ X p@ ޻ ̭ۭ KH#5 @  O۴R+@D ]}@Q( /*%<=J&;@Q+ #ܴ>p @ b@L&`hj @J U k ` ]$BŁ+<L ŝ/*}X :Ɣ\ɖm$У[ @ =L0;2P* 0ڶ p P{Ɨ\|J E[ /kU< * P a<,LΒ4"P\<Ӽ΁;-k2̯ ]`º "=$]&}(*,.02=4]M/K|: d=-?MA GP!@6PR=T]V}X4]5@^}_=2,1df0@)1$aT(LPt=-vp0p؈ NPؘ}؝} #9h2j1qT afOpN@}p`0 O ON`T@ ' qq`v֪ܸ@a  pppppNۣ PG= П7z'0{'  g}-@ @0ܱ ~ܾmPGp` !)0y8x@R$@#>%n ` Tf03nAG` G 0p@G^cxdSNbp T ZpP 95rN.yi FN8n]QN0 Y  G0 pp O p BP#o-`ѡG>pp 4 !t> GG)N fPWq)`qPg*d P@)"Naa@ D)$Y~Adnd>Àq9<@pA_ 1FJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogСE&]iԩUfkرeϦl]mܹuo'^qɕ/gsѥO^uٵowŏ'_yկg{ϧ_}p@ 4@TpA, ! ,<!1&72$923/83*:3# 558C"<2@<3B<+E=%%A9IB-JD4IE:FMRMCVO<$PSYTEYTK9ZYb[Jc^TkdTXfZni\Glmsm]yseUvuoyp~ykydq|q}mS~^d>LpCV0z2uAO~'5dw}bk{VP`@JbHSzR4br /MKCd$:{dm+ީTΡVxd;7z wƃ@PPhƘKk}ά2wĿ}FöθijĻmƴvǶǿǺɠɼ]ʽOʆ˷qذͺ;TüѨӝxƑ֮Ķyj˩̐{ԶԥԃܻyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ 9F_Nt]?۫Y9uΧOxN۸?>rgWb9W|T;4 .0;c;蠟;"Ѕ~g;ݤb>|3اDԳ,ÎA%N(T#t4N>yҟ@|P@Q7La{ӏ l@>:(;r 4Bҍ +ِ8 W\+գ;簣33$$>#ȓON~.ZN=<38@a>aOwS&z7Ith?#a??9c K7F)4 &] .0H9".8dB $OvB"nS)Ԁ ; 5@Q8j (>uaOBy?8q;1("XLC7C ɀ| iB68I B*x+1I>F,81N9Q)I=ϰ3SN602' % .(I{t@u><"E.| `A)B#J/|H2h +N4чJ,5Ȃ lk84@ 6Bu=7ȂO yԓOd B)Sޡ9D_sPʗ:PND>ΕTBO?YԑK.w#Qh`xBđ wh2P~#HD `h9e9h@ q4E>A'(*&PA1%"*!h}Pņ'كF ADu 6%ArUBQ#T-H<B-0QLAHG|P "? G,Ů%bFDjB !g Hw'ՅE-rQG- MhftSm&G |j؆0t8yj Q 0A6䱅<#'X;1zdZSN $T@ȅ1KDJp%TQe\bfB 臫ࡃ@KZ%+p v(G&X@T TpɃ,P ) 3 Ps 18 PvQ?@s%]DU!=߸|st ]U3|9D:P.j(LC!_p`Fuw@7 vCG! bș9Y > dέ@;2)v\DŽ#`8D JF-2GZ &Ђ ϑ#@-䥮HΡ &D'XDف|KͯK|2&с\|PEBʁM%;A`"M0I. dV zDQ$\-F^YΌvHOaTO,)N#N8 a#~h" H@EA#P24ghs0-$Nғ1HW> ; ( $c@.[W~q!`]d`?F=C .v ynBC x(@R (`8v eq`F }J @ @o ?x(@j.,` sxVشC` P bhw@=Ґ1*9b9G1k8w& bL`oPšH:Y$"m7@*Tzǐ p Rg66r ?0 `a |p 0 q ׂ8z CPE?y@T@ ȏ$`` -0*^҃cı-=h@ 9qn`(L A`(| Dy#]b W>=U v*@dr( 0 7) y 0DEe6eCVdD*X_ P$Z y7U} |"`d%h)||)yU0 }S!Ppy_@t4T($Pr(' %J@dPnǠ- Ah?Cz4xG؀PX  0  "&UPp`%0 hDhi FFDbrXjpra执h=| nr\( @ 0 65 !.H'`dkk?b3""`)z)ZH,zx%`"U  e )0 X2CF'R pXrH$HH 0 (z6AN!p~:p` @:6@rp~ 1 "( L icCˣND-d y yӠ spW`hPp$" E 8 KB `eܡ aP .)_@ 1ى A P =2 pjG@h +#d)p`X!pn! v& 5,:@ Mu 4ߩ`W1 pW6 @ `P0  (e(md t} 1  PСZ0 0%К00P 0$<9DU  P' :V- @T pX%qI`X ׉ P Pd2F*w]1 # 51 `ZQhڪmR+ z*ZJz !ɐ:Zzؚںڭ:JJ޺:ZzʮZj à {j ۰گ Š۱  K:*+hP& 늫j"۳>@B[qߚ @ À=0H  T;X&+ [\\ʬ ;hjl$뭜Hk*r ʀ 6 `M ){Ɛ =qh`sP I  뵆<۶[{j:0 % %8 ``0ɠI`rzM 0z `j0( k*/0 /P1;⫰ۭɀ{`Hj `kU 0 Tkj@[+h{w f;\|˭++L"02` SVk~B Z|=`P( .h&zF|HH: Y2˾ p)Q=@ /1 B)  9|P .Jn*=v|x\KNj hФ0 ~@Z,~д3<I Ɯ.}U  uǦ|ʨ {#K 0 <ڿWð;2:~ƌ Pi0\ĩ؊ pI; 1H[ŷ0 L۫0 D|޼n[,]<В*:[=-<霫zЇk]/ 4;=$@]0ܯͮ5]9@B=D]F}HJLNPR=T]V}Xͩr!-o_aݫc -gMiMkB#Y=t]v}xz|Pm2 }؃}2Q,؈0@)1$aS(I0=-p0ڬ Kڼ ! &jK0P ^KpQD c0P LQ` ppq`)`qqW><ܲ} QͰP K ` P D0@T0 p( {@p PzGzG{*P7  Q@ Q !.#^pM} D w(a*>ȋF>HnP` Qpc`VnqD`@& D 0@pj``3Xaun熽` Qp |1@p \5"n2i iN(nvqK {P D @` LP` ?P#сj~̑P3 )A>p DDLKcT qLQ@g)d @0 Ena` gL.F.{an^`:6^LCV0z2uAO~'5dw}bk{VP`@JbHSzR4br /MKCd$:{dm+ިTΡVxd;7z wƃ@PPhKk}ά2wĿ}FöθijļmƴvǶǿǺɠɽ]ʽOʆ˷qغ;TļѨӝxƑ֮Ķyj˖̐{ԶйڥՃܧܻyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+9F_Nt]?۫I9uΧOx.?>GrgW"V|D;$JL.(;c;蠟;"Ѕ~g;ܜR>x3PاDԣM,ÎA%Ď(T#t4N>yҟ@`@aG7Pa{ӏ l@>;(;r 3C F+P8 X`т*գ;簣3O3$$>#ȓON~.JN=<#N8`@q> aOwS&zÍ7Ith?#a??9c 7G)3L &^I/092/8dR$wB"jS+p ;6DQ^8m (>vaCy?0+9!94C" CC >a+I=ʹ`J3B60/ % N.sJ(I{p @2v3><2.|dQ(C.xH1h *N4ч +6ĂI lk74@6BĠu=8Ă yԓe )Sޡ:D_sPʗ:POD.ΕTBO?Z؁ .xq#Q:hdaxB¡wpA2P~cH pp8e9h@r4D>Q((*&`!%"Ҫ!h}Pņ'كG A@v5%A rUBQۻ#S.H<B.0QLAHȇ|` #?+Ů%bFDjB!g H' ՅE-r1, MhftSm& |j t8yj Q!064'X;xqz`Z rC B.*\"BW.w ( }(B?kF?\Zʥ.Ulx92т@z jH%m LLy!դLr#6iU`.4 # G+ &ȕpag"}!؁:r#D 5:sc.D2alCѰT= aș9Y >>,b۹5v#@&Ŏtc $b8L$i\@&*7$džDsC&0\A8a@GAگ-Ё J(D1Y BqDlQ&@$rp*fKw@!3#p^0-;q?C|S +giS#<"1FhA#Ё&H84C;ZtO Ɇ-`YSJݠE<@SRL,f@NbA1`%9p`"&Uvc_qhT3`88 f\(j=@ x@'Rh EڀxQS l Pߧڠ\@ "΀ϡp;\ $Іr @XM 12 (@.o ؀o@Mj#u N;_@9l&V0d,* n`& F#87_j W Q?x :?t,npO}&ae%|[$`CY("|#P*&[lbH1PqyD p,"H| @ >ohC8@`'=E8qnP*L A`(| Dy#]h6T5a`W>>Uv,@'U&0s"( 0 ' `yy#z0Cz_UhEx}RN [ 'V~ q|#pd." k2})`yV J~TQQpyit4T($Pr(' %KPe`n.0Bh?CX$~g&)>%P P PPy"6UP% pJ`PFD GփDrXmV&r (>0}XPrVf8 Pp 0 Q66.HP@.WPö#8#@ .  pdbWP{Gy*p"V 0e(0 `9 `d6x">z5 O p0H)D"Q`o dd`1 r0np(` ,#` -)M p icCˣN4-e yQ*` @x7 >P$ 0G2{P\@$Di[`X`9)< (O #-{H2)əJ2 jT rp *#e+ppX$ # v&p 6-; Nuq 5`rWA `W`6 `   8e&( ne } !  0Z %0ŗ`0P 08SI9DД)X]Y`AP I P  ݐ IL E^'$ ѐibd2|)W!h_  O6޸01)]`٪V@1ګOb+B)` zȚʺZ jZ @$P :Zz蚮꺮ڮ:jA J گ;[{ z ۱ "+;#+)۲.02%ۮk9V*z˯:;C;7;PR;T[5P  Y+@Y` d;Oh7 knU[v{x{ ft tЁӫr*00 0@Hkt[۾!{Z 9+ ;"mx0[;VP =  lk "<*zCkٵ l028; b0akY  3  <>\ @`p`I|}N^ [@Y|Ȉȱ ǐ[J P --o^ pxg` i fb`Ȋ|˸/ZJ: * ƀ g  ܓ?  &i2J l˺ 芶j ΐZ+ BY[͚ *۬ R J*)lEk?S $;jժ|{+]S,""<FKA ܊i[JLNPR=T]V}XZ\^`b]?Mlh hm}k{sʹuY c׀؂=؄]؆}؈[}3pWؑ]41,]0@)1$a]jPIb0}p 0 }۶ ͩh8hfi!qRP _dM`L ]p@0 MP M}L@R q q p 7D #qmgx-܍ߵp _  pPpPpLޠ` p㫰E ` zz' 2 `p @ R@ R 0..2Np]m E "hzJ W$IVNXn ` Rd0PfnAE`05 E 0PpGV`)ŸA蔽@ RP  P/l5Bꦎ-9P0xBW0 P`@ EP 45@P =}PRᮛʨ^PLP}@ M7^=p\ԕ XKg͑Z` JBiO4_ p=\>S%FO zA7lIp`q_oBvz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogСE&]iԩUfkرeϦ]mܹuo'^qɕ/gsѥO^uٵowŏ'_yկg{ϧ_}p@ 4@TpAtA#pB +B 3pC;CCqDK4DSTqE[tEcqFkFsqG{G rH"4H$TrI&tI(o ! ,<!"0712*62$83):3:3#=3A3 [4] 55[6:Y8TU9H\97C=+E=%>G$>6C>3MAKB+lDoKE6fEGcGTeG\hHcQJ4SLtvwoyr}yq~yky|k|x}V~snRAc1Nt|?an.|eV~ϏN?P`4BISf4 zi'g}HϟSxVf1䵩>>sɜɯRmIJM睴duw)Ҽ½ýۿޜğųźǻKǽUȻpɻɳ{̼̹̊ZxͼоѠҾԯ°~pĸƓq۳ۯܼܺܲݭ☁դ䱮ִ՛ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+;F_Nt]?d۫xΧO?>GwWh|{\#>c@c=c6cYdO;Ĉ`:p}(N4O>CK>\B`qB3B'#A0 m!ǎ><ƃE(U,>>یM;k20fCS-LAϝx?㠓P=O=GO~"N>lAK=Î:?0#cӝ>爉>Nz҈?B?DxMB96d)P'Ae6 T`?qaNOPAKBxH(9N-#SP# È;2yCPxkaFӏ*s̡I:A! p01lQhѩc>`&O<30H*H(BM~j ;`0Q(G6H+ڸS5O`6# 1@|C{s24P|QH,{9hcO:|JA:/0AM&GLO1HK*B*X U#CE1!I>`a?d#O V,,S'<@H##ӴӤB' "=Q! }`$ƄmC@z)c P2_p8"p:HuA` |z7Fo{#> IxR,`G*!0r#,Dw0Џ#"ZLP#j[&QtO@|֏4ԁ?p1P&"FBāi=A^ ȕz"tlrDA&xRX#?D!2m"B@B*80dB(G=lCF4Q:2u,O!B0, T%=1Q "7FȢQx6U"A&_P $ Xp!П-%;Y^BH;ޑ &܋ G4@P6dHHu@5@"Ti fit4b 1{G:SA# 7a U7OeVƯ̑mHjwi6JH$P`_MZ])M QGngڃ fGDCG: MU%R4uYmzEpD9ԃN:;ҚQ@hb"LKͭnw%ABvg.`YM%J2.S#HFrKVx¹۽: Un[D,Gd`ޑϱ11u6 ` ؃Dޡ\Rm2߻D$=HⓢTzXvT] xɫH,ȎuCPS9R $!ЉPx` 6 jrC XdBV.@*HPA<C= 9aH:t[BC<` gnF>ﰸ =h,@x&PzH`jB#Aq:yҰU2 `0*CW<y(%,Q h;p1tv}S0H:x0ĥp'TаAsvA7AЃo6x3x_)/pt v xSl7y6xBw\.NB(B$ EHzu@X^<)Pŀ)p0K/sQ|÷)?`:  jF7^3` D&p? ?d!`p~ X8@EtYS )'$RlPI7%  zL!d4G.-w2hG1RpÐi2TbuE u FtCv`ZgnL&^Ũ]ug  $` sBы:ptuf |ڰyQ %0Q \my "I J Z gǤiL+rz cw  -sYP'f `և_7 )"P$Bvp&\p(V`bP 0 Wp AeVa@:=(wx"^ey\8-0@C0 \QO;ju|Y  ia!5R OOI|3@KUW( W8jN(p#  3@W(ap@x7 tog`` `@q p O(wSy`p|U't)a B@6 Ef k&Hm!@|,'qT[&bU&p4.ZU]YWwr^ ʠZ'$ˈvJӱ ZwbeY,'Z-2:_1d4&P<ڣ>@B:DZA;`JLڤNPR:TZVzXZWJ9ʥ`HdZfzhjlڦT:rڣc:vzxz|pp}zI:zlY:*z Z!P3w` r @ m!P pW  0s; [6{8=0M@xgڣxy-fmSE9`a۰T @˓L{I+V<]kHY vw` v +[kd;Yp㹣6 uy J!WHN+X'ඖw` 0h8;[PiɆ!6!0 w+; "{Kڹpp@ W!+jۨ;lUDZ+{@8k ^:|l\MpP  "<$\&|(*,.0 06|8:<>@B<L ̐I ɰLPRxfڀtV1YY:: %AH=d NGp@Sl,୭\̎8KDWsD! cdQr s; yk6<<JȘo,/Gi,5wI(rJ*c 1AmB2D']hB.ѥtM8ӿj>pItJC SC:lj$mh:el ; [.nC 2(F!<2VՑժV\seJ BX@]kfdNfuYh! hkDAPB)  k `)4eb@^C}tupQVmղ)R25ujub+޵ )E(H8̌vdK6i7?:mSBIJ˭Emplhf>)0h„ l;ol&`ɴF2l 2ᅝa-bvVWifn;oBvoO|p hk @ܦ0) 8V=? xֱlA!_"(:(:ho DkCn.b8,㦛8蘛P)~m꫗d~{{~&|W}w}~뷟~4Qd:x@ tlEPA-xA fP`=AaS^VB](AuT03a mxC0$DvC "C^ = hAdbD(Q" xE-H TQc$c8E3Xdd "p`MYF(9\kxDhGZ-')JnA:GpChHIs{!PʙRx[ OB h7oq,*9E]^:6s Fm4-sw%ஃA8k, gG\ ?]C;5ut蚮r9y<+-,-l$Š<8cG=/b:<!B;)v<0H\P9V; 8hlʻ3 Ʌ"ɒ,S1s1֓1EJL&|ʿ=c'J4;3><$kK@KKt B˽ǻKľ$L>ӿH;LTt 4ErLLȔ3 L3bL̲66ǀAp! k-mH/D{CH%b4MJKMӷ4lbCUTDrrڲN v++hj 1C34N$DLLE.:ȃyCE[ ,NrŷhNT(1;Cm75\N\!k%UzgDsN00|Xbؖf؉V=;9 0 =X Ye(-َ;YPxMYg{ٙm/3}m r{ ' Xl {+Z٣Mf  a@u Kɯ=% L0mp.;a&#vb2۪ 42ܲd0Λ9<6;fcr 3߂룿k EVd8]c?!@}d0uޚdJH`Ld!\OSKQ4PNn]S>T& =fյWNX ɁH*ԑHe+eS>emx,HJ)rf+NHBĀHs\p+9Bm<+Ā\@.tWݣ1O8]խi>L`8U@Cm ;C.mpN@5,t CN^1[69'O HSB&ZUeya'0p0:`iE)iB\ iŃ@f;A`tԆh=+}d\0yf jX`mȅ+W(n ,`BFǷk'x <9I%U~5jml@:XܱhfwLƈ i*lRtY^pҚbfF}$`=M&e*>#xYjPxH);l؎ ϱSi.~ v 4j<-A:?Vmw,On`F۸lӑi@ ܵ͹%pPl͑fɪ &?ȁ(J pd]MnT ccv\(\6NfdCHZd%Wr!qZegX''(![(r-)eUM U20r]:5ms'2VcSsW<"=$W 0lW1%PҰ@7&׋OhnW9(~ʙnR~񩁪tEώZZPV'TbuKkKas ty, f,j8uru8^+[v`Qa ժuRbȶ+Bq_r).*Pk[80/9hIqwA*c;c4 q=xȽ;<c"0W2Bֆ#>[>v|ޘϷ7"/z1>+JzW#1c_mMW#dz:19w5:"Y; d{&D^&jg/tn Bt O`r>gD ~*nyxmpgt0)duWU}Wt Wj'Ζ\HXG ^hjDi|Uu;u0 NXvPpت R]x^5ObUD"Y٪ƶ6+6~OGz zz9|GvZCy,h „ 2l!Ĉ'Rh`+v7r#Ȑ"G,i$ʔ*Wl9UAh)"''iU !#B4@>"8B<,k Kifi ǒ-k,ڴjet-ܸrҭ&A#&8 Re 'J.`rj` "#aa0@[+ׁ6 @h-زgӖ.ܺwN^@v6! `S+Fm:o; jᐂ. ?,ao{x 8 %gPATP2  NBIxsj!X !(^%x")5"-8ׁ*8#59긣G1#A#E)"pB*$&y$Q~$B|hMj%f=)%aEeAw6.-I%T#L%u'&yv d)FFb 9)tKj':Zj`A)Ȑ kF P'djF5A9 5)-Be:0Wڠ(x0|0*Z +'MkEPpHZ81Q .ht @ X-;H(<;{qD 6eQh Q#q6d!+TA\EPVS3cDSA!O9j 1DE0lA,<=$eL5dDM4 A4 >=M'u}3Va=>}xB@7UboO?TCt)A6YDT8 N8N"z)W_j#E/B@F3Ш7QA-|>WqYs=)={cy祷}Ɔ~{B@AXpB.$@9 :O ( `x4Q$-4! ,<!"0712*62$83):3:3#=3A3 [4] 55[6:U9HY9T\97C=+E=%>G$>6C>3M@KB+KE6fEGlEogFcdGWQJ4SL c@c=c6cYdO;ؓ :K}(NTO>cK>\B|B3B'#A#0 N T$>ڪkP#;_M;i)'AqD6# Vx?avN=H!- S$Q Aʡ"Op#)QDn"# "fI\+eg1tK!6td+?9 2-b&6]:.\!?b_Oy^ ɐBB!:"jȃqI bNL;SN ^<7`=H)?0AH{¶n =@[#aDA(APB *uI^+bx&>DJx,Ԑ ]nVIv0Џ$"ZD쁴$8w븝'Q <-6a?p1@&~1"P Gl F'C xQC"tljLA&xHME ]C!A`VQ(B9聇'd6ri(΁cu !Gh!u/0Ў J `1Q4;1 tG,0,w G40X  L%$!%AKzaW)n0P<$$ J4"'2{D 5H "*CfE|(ށD{Ђhc3MHSYG" _CFndž;ZI0:X̧aU д %NBt|U!"Q!8SŦX +sa 3$G ǜuv5IQ$:*&O.ͭnw p[$h'{fmAڴ JX$Os (c$TE@!]Z$OE:-p"]a@IzV/0H'ىH:P`CDB0KA"H .޶d7u+J ,?]iQm*cURq M/ū 3BRpl*GHA da6ѩatU򕅜T@@HX Z$ ɣ$01 VPm NVn9Z ڔ0\`Q@|AZhtW)Ѕ d!HG.&," p=M-"A0\@2p@^Fh@Z#pHKhZ(0W]gXA@-8汬s !,ׂ=(- ꟞) +LEl cD!hJ;vg[%`>@.85mLA N!": C-x u!\ mX@0DhCűuE2  ^,qCK6?=H♚@,aqG*0%B @0b @O?Ɓ * @!=?| D^5Q644y{G> a @t!C,a J +֡ #z)` 3䉜' F7U40_{4|m|yM-@}5 x2 xb),t p yRn@_ pЁ%zuz$@Pa x 7.sB e H ,X$s4G|k< PXWtREFp< @(eq`Ő~ X8`Hv`S 0VdxB@  py@0 AG#@%HF4^br-3#WG U I ^Q VsN)wWabaGS^P\ Ћww e^H(v_xwp`B Pw'$Gd @bk  ǸZ @0&" L +ѐ)KِUѐ{N;mL̴"I:>F|Њrw +s[Pf `3:bW )!a*:paVp P ѨG e]Va:-p"eex\DЁ+ @=0`\AOU;@jw''H@$u#UR! ROJ|2@MUW WxjN(p"y w2@Wxap@z7Ptq`` `  p MHwQy`|ypa+tXdZbI`5&0lq4qTtbRZZ&po ]\wwr^ ]'$xe1vZj0"z02X6)E!:<ڣ>@B:D ;EJLڤNPR:TZVzXZj[Zz`:dZfzhjl:]m<*rZvzxzxY ȧFZz~Y :z,jtz [@Z:ZzUکT )Y!pnŀ!F=j)@K@[m! e2 )p(sJzؚZJu= u@h@  u[pf[]Юe٣ mڭT; : 4 zp/`0` w pб hp6ʰ6{8n:^ !:PM`pzgʣh|,00<@^5b;dK;A ?NKY;`kHyZj>zS pe[{zR?{੣5 䵷J L+ v u:)w rY+<lR ɢj!t!븢`@ U!;:˨< kTjC۽۾:[{?Z9Kۿ]˾[<@L pG ʠJNPRJ(ɠ$q )hP`p!* ǬPʂ~ \|؜Ǵ<|<10l< g0<lex8f@̟|@u<}C Ƞp `ΐ}Ħ&p<\&}(m0 4}`go` p  E=@ӷm > :S&vl+)fmGr1Ŭ 6ڀʏ `ʐoM o Pvm)׀؂+<m M 0 pp ڰ0J}k P g |_xYWvv b 6 ps `>Ӱ= @NA9`Hus,x J FP2#,ޭ (v @{W0u!"p:= jÊ!p0C; \J Q@/r0 `0 kg츠O]`?k_ <kpc0< .#p?F}E \3mhCg6hfz)c`W"}lDŽ͔iCGK(\JM9uOA%ZQIt*SmYd(;>sECixqܓDVFNL`pKHNN!@] Z nڦQK[7pڬUʳu׹kkر]Nxygy<:ܶS'W׼u֥:ajϜiRQ*]:*Mg0T' X4BF%0_p@ 40@|˒ J-@ȠBIBlI(0!&Ià*ǎD:4p [x 4Ѧ,Dܙ:(rJ*.;!/mB0 '^lRʙ:tM8rl&m=p%@i ,P.UpPJajP$Peo3y \4DC 2,`3%\jli1ɢy+˗6-Z@ (^'%q(Mmd7 ;!R1hㄜV{ #D9C~M|d$K MҕSc|e,K~GU&s{e4Jq,s,3Ys~ |gztXxp#ƥP˵qutW]_ljyC)栲\.`g~gI{0cͧ>D|fg/hQ}y6mZB)'q{sb$|"ӿ䡙}:ϯXo_%MhOͣ#]G?%۴0:QxS8?@?S8#ӆWKED)2>{(8@Z! D?$A꫶ 68x-lQ%k-XB x҆b% 0 H(-PSX^¼,AD>i&|} ]7]𮄠hQW_@vS ]rBp9r!898m8)p,3445D>ˬ\{ ıZҩ>‘QDXE@ZDN,K4EɱY9˅( mBZ P"9m؂ @"h3FaL, 2XƄqhRmc%*J\%aG4;>L5KD̬$ƼDŽLdʴL`̻$?dG>Ӵ/4MC V \MlMה3b MLjAxABc)-mX2DsCXf7̲{&8ܦȘIԩ8E,PWT S@$3+9NI[>=(^E Nx|#O](&@IP`,8G("0q< = Ǹ者1P 8Xȧ O| yWTЅ mxvQQ R! /| 908rVCIJm,R*cQ.8  KCAabT<3=LKS8F?EFuK$HXTM`LRM5UUK3\UV,TuڃXժYԳ[(4]=^UhBMN ]XkA@8^T`խa%VKV# ``  h'oRٹ@.faZd ~\LDkQ8Tyar4 7m. „ 遬(Vۄ  kx'&c53~ԱԠ@ccɺ\ KEFu'-ޥK&%+64jj;\E'ĀR օFY*qR(R񚊠G$>6C>3M@KB+KE6fEGlEogFcdGWQJ4SL43P;cOzس T(wN1 @(R߉͓O9ܒ<5?(`_]C ҸCG0h6;ܢx 1}9<*i';C: ?3~::W:쨳#(>sӏ;餧*-D`ld i&{} ? <<0}Clܒ?dDZPd+)e D7N(Fy2@,>%<yCL QE: s$\ ç,BGVM:G q(k$?\((ל S,a-b&8*4#3X^;L*.^:?DtH'܃D> I M :FtǻRGn}T"PIxd0 Q8u{rҰ>L ũD 3AJ:Dg? ӸE1 'Vh%c!HU| hy;0 ! T ,l!> UnAfV"&M8E9@# eQ@>գv@ǥ)ThŃB@0;$*3cAZ 1=J r! 'cҸ;d{aHssdG=`KUkG7`/8c >ۀ!uL# =!8'D0È"0`0w0 =iT!TGAA;d)IE7zlRKC=1QR倴d*Y0TKaJ G< _`4B>ViHBG^HtEU֚da%yN=Nh!w@&&a*c;@TкlgKe szyOn NJ lb%,Q%t!2Zň: .[F,0G>"d~H; C DQ $uРm~y^<Ep5bcĮxb;uA5S4fȍT ԑA4gqҎmpp li"p0Y86MP[(1\A Qbb6 L^uBA0؆%tBGn6va_k"x:Y`h cS`ȵr!&`XЉntu@:@*)y ]8wbU 1H@XS L PkCBpB&"D8i0U P=~9;|<> PH`K?y_]SEmuFq#[ }Ѓ nL q FxTpp^ Go"dy%(D.M"(I#UHpxIڠIdX@Bu H'Ptr){j;< ti>]E`/Ѓ;!p; 8Xd_} RȄ~=kSLhv pc0xAR8@ 0f7$@ wyoR]k`*F0R@Ӱi*GTRnEfus<q`% `~l UXH(~@uYv`A v$G8c Vj  XY W@P6 J *∘2J S% g&$L* @ cxvP~ 2gp|m`5(`uƀX۠ vBup[p(SP0 ` ˨ dP`:&ۨ`"XArH\A+@F0[QqAilPPH`_pQ'1T!   !pg' @v :gv%x @  )Qx ;pьiQx`ͱ ;Qh ڈBЍ5 ŕ^ ef!kr! & q/|F1J@Ukr(OEZlF2UT_ul n%uABYpW1t:lQЕ:xJ*,)ڢEp!4Z6z8:<ڣ>@B:DZFzHJLڤNPRz5SzXZ\ڥ^`bU:fzhjlڦneoZvzxzfN5&ʧZzhSj4:Z*N )Sp!mp!F2j)`+`&"Pu)LJ )p(@:Zw€IP5j0 p0N }P@ o@ 6N\ B j o}-LP.:2 6\|Q@Il ,`N PrnP} vx"l^pʁ胞p?zHZ-[P@64ZnP }PA + ?ߐns Π ѰNԠqM ̿.TBM̎K

$ ΡRp d oc5fh@5D"sN:jɒ& TP9| IBUtQFu6Q :DĹ/!r)Îmr'#;a=/3T$ gk6 4si3(_s!TK*usZjS֠A%!LiP`-x@^PS`@*H NAP+`YByP6: }C y.bW6C$ 'vbpB#FQS $fA 40@  .lc Rup,i>: (ǛB _A`zƸb#?+>2Zd_lC 62 2.B5dx vALa( HQD/8bcؗ ._D*d 0IFS{,ׁi^F2)d Ft X5.ŴG$, `;DR c#x$l&TH+`PFThE-zQfT(7=vBFʙ]L:. GhVK]䀽 6xP |j#x`",TSu+>zUfZ"͈JJ/-S"`DYրA._qS (v]5#{8vj@=vVja {n:]j)=p*&`[ 0)d-a/O#t@;PH$ XC 0!*t%cq^!"cBYkR"`WlUnmV%`T6~g$m !Nsb&xeol= D '՗SgXU}p=2xD!Cg lXŵe]p3Z c*2q}̽X0|dY:.2 /Y-26'gQrq+cp&s6jY,䲗ݬ1aϼ<HeFİwY(l %61'OU#t[xhL,nFx<"]8d"@ jitWLz\d'`aP dK/L+^m(|4!.A*`hZõ@S6= хKIH")voz&I#s[jpb;[1m{ g5rU h)M~o\I`S#轍 eENsBC[vrE `F jCe!0Pu\@e@'$NtX#/}_ÿe}tvZ@Sw_y'vs O0 /+5댤G|H'OU(Z#֚? IN?s۴ 4@Qãp+My: xc0# /0?I`x5TXASk?Kʤ^K `ێa]8mXRX_HX«TGSR%;fg{&x)\ <~ q>sCz@'w9AtʉRuӃxG@%C=33$>KK̽۴51ڎP&0QxBVpA;@8D5NAPڎ>܆`Gz")xW0+TT4Kq+>l=F=%=CLmL,;Nt0]Dh CX܁"(1$dNg9Om0wIF\Mc,lX++8O H]S!=؆\P55CtQJH=#@H=Q s-RICl#6=8$3'%3=454C93;Aӏ@A%Tn >,;KTE3مG9ʗT8+uH"á@HIO@ӺRQ*R-$L'"!(HX!UU%#@̉%R Ӛ;0@4+$VںUcԤЀ^#0 LWVno2\LsP0W9W[Wt0݆~eM<;!Xw RZEXiV7oPxC͉c`XX W %|W忌9P8MXuKǤJVQ0?^:S$J)؟$Mɷcɫ51T z [՜I4]ۗ=2Ժ[u0ۇ۾*-;\;a+\9E\b>3^}3Me\):\ǝ8CURUeS"E = E]S e7:XD$PڵAM_s%%u”VpK(Z^浤}%7jCtRĔ0-t[e=,Y\%"upU!߬ߋ#GG1iKX6@Y!m q|x8 ` .rQm*LQx ^ama=[Ү ܎$`!(۳bk*&+&,fbqb![{I;c4F㖔ehc7nc+]b01bc}cBm[@OA^BV:n;"_УDnE`확/ ҅D10. HCFdxH EМPI6`LY4r(T]@: y1pVg(A ,^@@\/Q@ YOP6W@Da#&|B1 ޥzL&]0$c_/M>7+QN+1H蕝]y_z%xdd%W0'V踉] S$"qei|^xB4>{F>ni}i-8%qeqyMmi3el@ܬߚBjFhj&8,IPjۥmm8CB&arlA;|q݌l%|匨D{ysbF\Dp3_@Hx&Lm%Έ9nWG+j hBDq-ommp4qzc/qJZW" r"7#q-r%W(&\}ԹԽNr\` rUc]V3<$Ul\]/Vts1<3r7/4_[U͌Qp8lb`6 _CG8ߵ8qO&0=DctDuQgXeC(6P,r8uPO\/2w4=3DvVvИFhT}R-gcwElD[a{Q!%٭Z80z~jym&p7;m_() Wqb邪yZxx!`yA?tY'Gy#yy7]_,X/zzrWJ "x~bzqKU;; I N*NuoL6cGy7K"E@s NB`fg^-Q_1,)Vd@O{\ $FHj& He Ɣ46@,<^WxաvB(4)Bl|\uT}cSm?|svj<xvRć5uuMk׷OޫTjƉ*7sTf|}VnijakwHm5M 2l*g!h@K~ Qg۞b %pbn$PP:w'РB-j(ҁ1m)ԨRRj*֬ZrkWǔ$J AJ;9p):n3kmCt+u=W/30!ģ7s3K.m4ԪWCU' 7QH-cH(aC/n8rY3o9L_3Ԣᄊ Yv7+Eހ0ȳo}ӯo>C w1 8`p f :|I8!^߃j!!8"~x")>"-"X8#5H0#Nv#A d=y?:1$QJI^HZy%}J4 vl Nb~Cu۰ '"|g,206Sphc!ٺ 0:)~:blݖfi}+|'6aGN^xg>y??q<?t ;%?ě;g쇿 | R` Vh3A‚d! ,<! *2*72$93*:3:3"B3 a3n]4` 55Z6;Y80S9GD=+E=%>G$>6C>2IA,nA~OBKE5iFGhGfdHWRJ4rKwRLG~g'׋]tv *LPz?jb̤[EiȮUİX滴&Il{̬<{ӼɤýĽ޽⏾ĠŻŴǶUȻȻJɻɳp{̼̹[̼̾͋xϡѾѽүİǂŤÐpۮܼܺܯܲݵԹ☼凧ըڹ켽 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ˮ%<F_Nt]?۫%GwW;i|<$ M5hS=ɣ='=΅~g=s tB-8=/cPs ͣ* ݌Ï#':7T!?rN"o:"(ߍ8,>`h d *ِ:Kj4c=c2O:$T?Sm=ēO?_R;ꬣ6h!t9aO?ުOQ>ڪQ3!< z!e )j&{~$q ?<<EO1wc-XDqKB Ir8R<c PD#! Ec VX : Ɖc$@O&XʤSLK D&븣 7Q.OIB2L>$ 7h9`IES1N2>< "H8裏,tPC $N!@N =*jJ6< 3E6!i?IB,Z R#L2,H>h?aoOy_s3dx@:#B%asF?#y\:e $Nbwh#fm)@|t) xG>Pa!!@#E<",dU`X*{!1%Q|$ 0zW3{OТ#Z4Za%$0w@SP 2-5?p2` q2 P )X?ZȽ" J,pu#;,ȥfDLV` q4Bh # hx p,p .R ڸQyHC E6#?3jDR/=84ڰ"f ȣ,ab3YG"P6_cF 5D@Oae1 CUc6 R@5xX=P!qpZ:GtyN=Lh!w@*&iT=ugA ނxH\Z ";\` &Y:uc x4% PDP HO x 6&EC"pI+hZ(0W`At\g`0-<)԰k@t  1,@'=&=3 ꞙ)(CM5L e lH3Nf[G%;w1'v))hc ! ^4%Rys\ mT}AFlm0u # rN!X?2d 3F3tK]:p ejjHH~XaAhc- E@*^h b>hx(P=4x'Q&xbv@&lTD%&AaX.yfR>Dc]TʠAAu!t'7Ak7x`1xa).t s xRm0hy7B'\b$AbP_,X M_FZ B Ix0$s46'|k=S P`tc^"`/p=kcpLFv ~C [h@IuZFV dxC0  0  QW#0POaDB`)x5#7(# q F`E`sW`a`HGR^0P6|QpoMv`^q˨_'vk P%n7$G¸c agk  YqyX0@W\ny 1 0!,ڐ)dKUڐ QP;mj`L,xА99Fhw~ >}n`4'vǐXP n0%90`aU`vR p ظ﷍qg QeW`92I`"p 0TYȇ  ȁD0[QpOU>v9 SpOjQQ>ҀQT uaV @ Fwx ! @Q  S8wW``|Xgta `B70k NsG!  0gMFaJ98 U%mFViw0`5bv odCY|ba!j,g١j0Y1Z6z__G!B:DZFzHJLڤ`纱۱+ʥ:#+3`p s Gn!   /P ps2kz0NPE[Zb;>yGJ`،z,F`yFhu7p*|۷~TXAI_[0PЌ@msiF:[0;Y pBz' 7]kb!Zf[;PPB$ ; MK;;k=`lr) 9[8Bڸ6ی@ی0׹B J<[zh \KIj LK,ܷ<\$\¡\D0  U0&2(< ,!<3>%WD LNPR%ΥYzۤ#g Ip dJzr $ d N`Q@ a GM 9=piЩ`V68^p. 0mHq.Q &z~Y ^ܤLz0R @բ  ߀ u ! N @ѩ^@ .: -^뷞8$,xK؅qm~pPU\ .`n`,ߎp ڷT_V_ʇpMX:J PwB0R  q @@ O ! p` a ֐:4a  *xHM!Up5:=ʵ0ݠMI͠ 'Hc0@W/Y/ J]@f+;kkmKƬ2!JmC j0>9p %g/`Im 8p„[2k2H@1M\N E5n.+!l;zȄ)E2d9M uPyΌ8POw8Ai.a];&UmϒiR%3m@#_X:I͜EsD[ʹp,Z'\B cȑ%O\e̙5ogРrִ,1j ֜M)B!TC1ݴҖzxLIim|QK;N#Sx ʏk\v `iR D9?%ГPvp*ХLA5gu(-&PJFI $j" {&,)`|/Fhƀz mH"4H$TȴJ31 );7HJdW; NnLC& HL1eILÑĉ )Lmeop!{nH? +RL3ՔC91PB4xxgxǖuVZkV"<`$۲7`P3;$BqZIlѨ3;ܓY3# 9.EMk0N"Mw^z3S4  UZqW 6`L"0Oc245IdILG/MdǸ?3oO$d@VxR\&Rmu"uhA"PgX5azZh@RYW8ldm#[N3lNٴDg2xI9r9hM5 sz9|fJѣAtZ3K]vkvUg۴ xMc8 8)! qN+ ca#0 %‡(Djc00 璂6n]yW:pv L`88P`-xA fP`=A3.frVB  ` mP;a}C QC$b;#j)Id"oD(RLMbxE,fQVD-q@ji-&/ ͐yf8Tc^y0h [XK.3{Ep ڰXr<ܺ4bC#Ifrl4vA*Pk˪Y{6g@n@h1>':~t}P*Zғ"}iLOÔthL:ЛtM CPZL]]ZvFXҩu[1$?.I,Bfv"ykhW΀/I@Iil1F䳣}[3lxӈyEU}o:$wKiA &Pt)iz `Yiqp0[X7=N,')L&ܠf(NOy Naݍ眊xmHji8Pb}kQ2HByՋsgt@흉n'1gJ@=b]sGMޯ'i t04(~xʝ7uݎG5Cu\@@qA!ćg|/El &>bآDi q*vo \SM|N;S򕳜c|7}M;;ZoiC_ED.W»?.~gQOQ?\@|@#:@d@ $@ " D @ t[ ,@\6ABP#TP65?\6"Am1Eض!86p9LL@@R[`%3y*z$dy[B=kB{%`:T B9f>( #& /BI8k8T`p>.D+/@0dK ~ڧQ):J9_08&` ah(/a8*ԈZ6, 0I;O:)p,XE+2-!c4,ʿt[@@`L@m LtMM\ԌMdsLMYMU|PN,N4sAmPBREd|46(ˀ NlH)<*4DP) 0X.m8D<sCp(,5\7:J,9 xE% 8@X -؂O(-p)XbT Mu6;jsOLFX+Yr҃Xe/y%ZE*䲃QHH"`&#$UR cRc*ծoL C(, ]#Sɼ3/6S؅ؼ8&eP[ K3S'5PB=-u\[Ƚ43D)R5Tު]w3e>eA+:ϩո5ߤqeߣq%_e5_WUU3z^mb3㰱%MN&;n`\Y= -" `g` }ϡݡfo b"846C`Dz@`29I8a.$azbɸ{Fm(7P(v)ҍ;"@-F/126D!Jr*˓:;ӆQȴ 0Aô/-=dFJdEI۽L,˴pU;N$OdMG5LKLz-e;J!+f27bcFde1eZMdflfffof^f.fw{OOs5tVd]X%zgxvczg=g3gu[g*8#10,PB.>yW13:dJևM -Pd0 8ix5L]p&P!&5<..;Ц 8y$E`8JP` ``N.i>%qhmN05Vhx"ba@#NDҊA8Axa0b/:kew1x8ӆdLɍN;0/0L&r5G-EB8L6 GhM46 Et҃횺3:.nvNl?kHk>ȏ 4Af';pi| `-&. ֆDx35!LF̺>G/$ p.Rq4`-m:4P ! Isa @:< UrNI#pyʥ%苮V*p1F5e^C:<%t5hofJGoKt:wittO3Hg_*u=uTo-U}ŵV_4PX?"4u9zX!*_RBUv#"Ev92Weo4Fb!>!a -oh ݃Vi"j(Rb~ WxꞍQ4VL ]wv=Hb cv**'vGxѕF!CP:0 Z37"`g^gc“IixC?za`׍0W!=& e0KNMQ7Cؽٱ-5&၀wGN^\]3ze%Cofw&4G`t? ]j_@tt!f.o?LJ\V|Q }$ӏ[O}D|(I`g 6\$0}·`l{#m["mv|-*(YZ$ޡn8{2PÍ9 5L <Ԁ,CC~uԦ@ە W&\ Ĉ!1zqL ɍ].$ҁJ:$n eƮZ&-j(ҤJ2m)ԨR Zg*֬Zr+ذbǒ-k,ڴ] x |TZ 1mhmKψy \]Pit`S7s3Н-m4ԪWv`th颒(x`O P> /\ɾP X+ƁDs;x[/o<ƆHvO ~0m5/s7AL< :7!Z:@{%LdzhC UD!e4\?7nA~JB)KD5iGfHMeHWPI4sJxSLc|I8R6e!OeCb#>ơ JpHv*ģFuxQ_!O1䌩`ĩ_{ͭWs ZFU㵳³ܴE϶Ϸw۷Xw֥θvý设:ľwǿϴPܡιĹdĬŴcoƼǶɻɳɶ̢̌̾ͼjSÚϽυоtҽ֯p؟ڵۭۣۇܼܻܲߙq H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+뮥<F_Nt]?d۫ ϥvΧOx]xO#!=== 4!Yt;܃`:L}$NDO>=5=iеH=l3C%谂>?4 KC!E8q@|P =F"Bxb>+&+s?ꠓ==ǧ3~ O>=: ;P">Ow%zN:ʊ$`? "$:ʣ%j|)P#)A&?=pO8~,O\z?TXJО,\qD8BOFyR@Hk\)?Ȭq=1vF:Ĭs SbG1ѭö|c>LO)Hqcl8"$nbOĒHS~*.(?XN8Hw8@>_2N9 3 -SR:C||߻hƞ-?-X F#BL{|Vq `B)0;6`jP$ݏޢ;H*,,8?Q+J?O,?aL{9@O>\=(Rǟb18a )2.xR(шF B@C?$ Q)ihP"P)z!?R@>:vLMk,p4Yi ~hiiz#kQ}$NEpIh(& v UCq,CΤXxA>~pDXg"y R,~ R A9졇wcY>A>;cu@<+K!dBPC(މ=8!}4 % 34u! 48,p8ۑUP B(no0H7dsw0då(? H Zd#–IA ]\bcCрoc4WO84i@̏a0iJ'M$J;Rȡ1B z0<}pO-̤#y=`hQ!hw@·%1l*# Tya ,BܙSE'AW)&N;. ԶpN8$(B)eXLdN(xdGBK_IiPp[5*V[k$: ʻ Z[{5;ۼ{+ F 0ϛkXP ػ{۽Y[ q8;۽W P <\| <\  "<$\&|(| 0l P56|8:<>@BM؀ O ]  J |i $ H}mn*n0Pq@p+8@h|ȺCf}tfi<08ѓB@XUU $ V2pآc$p(L+YZ12mi]4Iv5J W4h  IYnWaŎ%[Yi~۷Y7\v GL`1B$Z1uS@NaԵr]IpCB&ܭvLœ8g7Tc"TfMVdosѥKwWAwʼn.{=ٵ/(xcN=]b)$(0p7TP  d0 i CCqDK$-zDjhAF3:&b: $%&T%3j.$@L%!V:^ ߌf1 0c* c'sM8sN9ױlဆT"4i-h)@eLtQH#tRI.HXL𠒺81PQK-7[ G=jeǘJ+Yl@ڀSî5Yh=;Z P@A&!RE[t\r5\P4R %^(! G )M`5 4Rp`#&!!GV@*1C`Vk3gUcg8TY.qvZ[vZ$eRhPt{gATRܵ c>ftlzW08!G ̲ÙacYa`Aasڌf2f`fO _o h 'DokjRlQO+r3H:3 :!: pB:&+ Z草~v؁é%bcH-cS‹>,h%qL1Y7_Z;#_|}k(g+~'~P$` (@i|NXE" e-kĂYPdq>Nv` MxBP+da ]BP3! 91b!9 EC 2'saxD$&QK\a xC `bD,Dڃ4+Qc$c{ 4Q84c}E8ovIE P WXa*XZ8Í$d! i5&!8Fos0p>R7ntWV` 2ede+OH52ҕD$m>JZrA npLA% 9e3p2*oygcSzT/` 9$ḅ;-@tgFj$h<\WB:Ns M`X@E]ie2B^(P4\d/`36킒Jbuh] )4FLjp* v̘FU0d).tB[jWUUc%kYzVT9M1إ>D?uv1׺2̜ja kBipZXɦuiLܨ' k3E1a]Z_slmm{[q)f9O & b\cPjh l [L'[I'~+PxC ^(Pv@ C 8Pjn gO`UxTagXD"=a&.JA 4[ &u+f1"]X,]Z1-;|T NX{}p0 \@, (x\A#|A]M=rA AA $ 6 6< w ! +(> C& EQ<<0Ҁ-n%( e7]0a.S3px De0H@0j0PLʊb*n TY7]p::-:͘p8M ą8tHSC n&؂ \Ё8ˌ0 Ylx!x{D\94I~IL4Tp-p:Xp4̼ z" <-}ʘ3h$Ɇ,"׋9;(-Dbpc$7 0#'8T   ͬ 3JLŴF$BӾ>?r(`τ+9˴dX˜ ߳M"܌3{@`00$ȑ 7"#,3'F:O.BO P- ]-;P%<*d]P  P 4BM Q3 أEQ. GOQ˥]jDV`]Qʼn99o1-H'a a X$,b ';XxV,AV+HP#$UR:+FT<$ >PUhǾ(XH>e$A]P?ӔS;.9HH#ʔā ]/]ء^0phI Ax"RuS52DKJbMe؃0́0%bp ,9>l,>TVh2f}뺞$'o*  ٙKxK^˾ԗC* WO8ȣe{7Ii:2$"8$P\l  guh($e5Xg׍3@/T̿@X朋vۯ窌ȁҙ6ܯyZZ"ڢ]DO@ cd]0=7[]#T۵eֶ,A q21rwU5K*d=2\C&J75]/Dݺe]$eם\43HT0׽,j@FCH4P4HM ^ "T_r5=>p^2&'qe#Nu"`|'d6v6o#ߩբTFs>#G 4.z8MXUT)Rl՛HB[` Iˊ+ j-71VŧX`EQ9~e<QͿ9M ጝ^x- Y):.b؀Z> ,Mt%().ELZbڈ"s/cuc<+z4c4uXc p@@n1A)d"EɍddJn#1 MH Nd2SF9OVe\VWehaYTe\Z9Ae7 fa(Zճ̨UGF4fBBd!:^GC %J+S|ɴʀ;6mapV+b5-:Zcg7rwV5U(=f!(y)m#prӁ KucE<ƈ G#8v!D5CǷS8뀎; 9Gk&Q&`Vլ ι7S8~}εk>fc.i^ja;Sa &J0V}̘꿊 г; `hV ڲ Fa׶,՚Ӂ#T%Mk;&: -ckZ>8VNN/7[/k7zx? H@A-nN) (Nj4Nm=Ot0E[h M" DFnvo,AL> FP\R6Da}p  pTn ?5YW+_Ne31_[>jfW*D0גWnƀQ^:=p04 qB^ !mi{k K LD~rVR,2t/`EEH7eEim6] i +E!PFЈgh i$sr*7Ri86pHHe8Pmsy$ |,9 ĎRwedH&DHdt)sG~U]׎9HTM- ԚYTݑIքu\7P8ckמ֠V H]ЁoUYG5.LM lomlV&JߩKKvw_}MX">lJØw'qe폝SWYY p cg?$NiUOx3?6M8.ŝTN< Ψui)х@3X]\wnUp kxϬoVfg!?K&\ hҵ1G0'7ÿWeƗLJj4ʷ/f?c[]fvQѿB7}\o "`x_oׇ} y z&HHc*^n"E(EEg{s(Jۀy ,'f~0&\xsLn(>(gKHhb$a2l!Ĉ'Rh"ƌ7r1""Gbg$ʔ*Wl%̘2gҬi&Μ-׭ŐB0XaoR|m! xȂtN@+ذbǒ-k6ȴJl-ܸrM ax&M*V<`g'Sl2fjI3ТO_߸UE2&Le8 27Em8btj޸duv؂q85n@ԍ7z,}#VObb[фd$ 5\6Y6VG-oL$ *Ðt<}y6u!rE)HA .,Tբ@H@0t`a'  JR@a ȅ 3h!P[d)O!j)a 0C+]aPf 1yiO#21eRC aDUiNwV-mt\Q:1؂Q H # 8D!BAERk5vmKe!Tp#8;t!VKX4 l'Z$[yE&P3$ D` IABN-inBt"?@bGZ/D  a.BJ `Ǿ.~ȓk1$,rQe<:~C@:HIZRD"$X1E#ԁ wƴM!x2dil =Π2!'XHNr1`bɬ#8I@! ,<! )2*62$d2p83*:3:3#@3 _3b 56T5L[71T:F"<2A=2C=*?GIB-B.#C>QDsDKE4kEkIF;eFTsGsgHaUN1L݅uNt_}A An~,|J3(Z=[Qo`@IMK73@Ra"Ɯ* oHuN)$bbhIȣBZLw¦_}Ūìk~̮]`֎ٰCKLo˳sٵX϶}ҽv׻ٻn߻¼˼6,־ųƻƠdxǵUȻJȻɾɳʭ˔{̼̼̽;ͼZ΅ѬӼԚqo۵ۣ۬ۗۈܼܻܲ߱ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ۮ%<F_Nt]?۫%wW;o|<d3`x4 ':M{C)擏=#.9$T?Si::'O: %ys t9]O?ީᏆM>jM!<\ziF\Z7oӏ7{VXQ;x VA;xX+mP7&EQ:0>|$`d ?q=$B/zst@=%sG"XqG BM:FN nr0?<HzsTVdހ?IȻM><#9v{\q@-ί9:q%,.wSxKr/.l&_ O|3̏=y/5 u I%JGެM*s,^ސY7 v:ZJwc%$0?8L6H`  jK>+x|V1~<"ZH70GhѪ~ā&nP `@ paT*N`u0$Q+h  2Ѐp 1 @s,I@k Hh@$BVЂ87KPA+,ɷê>Xy0f1Y@J(L )A)?!sS45-X{"5Rjl 'ƥ+ H/` @u@H?`Uh7,EB 0` IJBp ra ",L!~o,]=h~$ p_, $ hh*'~E z#g:a <A L$44v;nv/7n M s\W.mv4A*\%ƘJ^J 1>s Gvns:`%u:qMGxչE¦#D]J 앺nBqݸ/辐sA#d0/ ʻ[y ~Wrޠ1W_-Wz `b4# QC#PPbL1BRhԲ|:P.&ReܖP&Sa\g\vRY`U}QЄ?,0ZQg # w_7Px_` PplvP5a @dt 1 .T )bLrG), A9iH"GpF8E x` v wipudɠT @h ]{U AS} ɐ dxwG a6ᢋ׋7P"asYȇ[8*pG=0UQL4Q5e&>&{a-P?r[P! e<'" /@"\@/.İngf1ppDi a <)"` effxq(p 7h,떕@`1VŎqDM e&  04ATw&-b#iD&F4YepvX)_']W RYZAЎo[%yą(=l9Yyșʹ̉59Yyؙڹٝ๝Y扜y깞ٞ)9Yyٟ靿y ڠ9IVF   "ZW "Vӡ#ڢ.0Y 'p  fb *pGj* e 7z [vZ=B0k)lڦnI٩ p/ Rlre  Wa& kGyZ? J Z)' 'zpZzrʧu   1 r`pw{ `o n rspJr©zؚj5 ߊ-}6`G qf[((}wU1` Xۚ 1ڭzjRpz[ސr^pWm ʰ4[6{kW V'@ Y";&ްJV± ް!;9prV  8zf{h9;6i!i 2X[9f["@nzU(˵Vj5= Pi{չI i{ƹ5 2˺J@@;3+5K D` қ{r P:pXFpp۾;[{ۿ̾ @  <\Ѱ "<$\&|(*,.02<4\1 J{+!3Y0 B<ޠ DJLNPRĥ|ۑp LP , +`!p钾9n@y?nb Ap A^ ~ AlP I^ qP +<́`q-]c AW(s(C q^?x~Zi}nIՉ p!~>>ĕ^l+l#Vs O0Ag@MP N0 P c \ \#f\qShӞLNĥ  HPʁn!+@̀"ap^fn r "@7}H{'[O n 0V)̂Le5lO*"p|0ccpl0\ 0PU*? άg0 1Й "iYi_ss'pPiwmA;]tHI ROʛN pYp^\ p]Wp Z; -$)b-n zCA Eț-[uQcpE@. t Ma̰a eQI.Eڎ^;휂'TzON ukԭanX%:\*aA/B r2aDfϲPEO3PYg47+>r.egСE&]iԩUfkر Ғ)ㅱ0\tQ 1ASnnɼB.F7xDB@7QiQeg V-p΀SKϧ_}p'K- gqɖ9bpB +B 30\d>d!MvHn!1H/H  6@N;ĩe6c'pcoJ*>Fo6`B ?&KTsM6tfN8AE9" 8 \Ip+Foh G!/2EQfkf9a:JV[u,?SfhP9\sW^{WH?LΔb1 Y?•}un8~xlNl&߲vm{nn{on-ZC d w\qp“qk+ǯ3|s;sC}tKW/B~_(_ @<8_7 lІ$Ѹǩ eH\q*X? fP5?kF Ü9F mD FWtNQ , zPC^&U$,@x \6t,,ap*Ajh0CA6F@)1n0 !P 0 W#HHΈĞ-Y%*^Ȁ9"ڰB`HӠSx0F+DвAXňу /\4gub 0EpFIlfs!;\ j hEd[EG=QT#%iIMzRԤd|ʹ/x"d'&$=CZ@78Pt!xH> J {bQ&hW:c%kYewX$3"6M8a F7Q`y1@ T BHAD-.AW-KQZU,*Ӆ L&^%Lp;u" $<@xCj9c *^VY8\ZBAdU ]d(D,stiŠcP""b *rK ]n!&X#78x U :>#cg`"^pM`hEbK'qq}|XC|d$ٹDfr2%YS6]|e!欌e0s]&s09c 6YEY6/|2 3wf|h//΋r,?dN]a@oTQع-@}ՙѫdCpBp-Fa(C6qJOYEfY}l2щPb[-6ËNX3.Dkl#/I9`ZvG@ @! 0̑Ħll|[uA L*E4R-q ]җFxFi_ވ2 &[w}=M m[ Oy'-Oaqo8@cz>BO ]yre+mSVѧ iPJ[l!T%AUXM[uT_={abqk]1Cz+{:<. 2QZ;wJ{BZӢvEk{;U2IdEH E0cE|WMdv~w 6kAc1keWPh)_`de*ė36+|aٰC!@;DZ?[b/@C@ $"d@ |(@ Բ< Ad@DA\AkAD>AA3278A#ܜBK=41V(#4$T¬k0HI54]+#B-l9(Y j![LDT57e{>k6vg".6*6 P8Ni)?Drz@Oڂ nB%Uj;0R8oxO0G8DOdۮ%xxکz'E43,_D@` EkÅ9˴˩L{AFo0iFFma$p"R++«?0uũÀǪzT3F3S,*Ek .9Ă))`D$(08ǐ;$I0?0 0C[e1a ʕJ2{@h==آ#V 2NbĄ&@W!@M*C,O3oLjVj$Nk@,H5P<;Ŏmx89pl@( %PD+(QW*Xo'p>'q0S>UӮ9ÂaPX#=-P%+?̜e.E$RK4 S:؜;I+QE05V B[1\ΔϬ0<)hFf9;hZ=V:[Se3zCR!9: Q4hgHnUoDe("v",B?26D(h&,pxdQ,Q4 8IƁafх>PX;*}XX:T'Sl0xLWmH(pmeٮrٗQ"Ǥå2 (}k2f Zy=Z'ǵLǸʂaUkȪVzcn&{H[zH-ȂhZ@HmCbۅ;Fpy5.op|ٗ8 S\҅,(/m2ZM({KJ@Kԅ]]S,ڽ]3S]ݽB-̑^-FAu)uJ=P^t38߅TU?`a=ܺV0yC m".LJ[VjiE="S0ՠ`!WCr%ZPZ`Ww0C`` ^ NfWh3 X.XEAXeӅ:ldb2:¥)!Y8>V2@~.G;ZmZP dr㺂3聂h?P?eл]['ۤ;[S[n[lx۸ŀZZuDc #_`eZcHk[eVM#!`ӆE]No[YN$a@R٭p2f\\˽0H9-Xb/і?X9 YmƽS/Vh ?_ 2qdލ8uʠ.na뽈LaQޥZ.+Vj$jMVS&j 鰞X%>kݝUkij)kAfkf/an_P|<X?`!wUSpl~Ɇ>` 4VP8mXop% 8 Kl#4mq u4X$+h;>&H*uV2@0Ea6+ :ejfn$,m&NOkpMCd|C*f53^"NPso/Po\]Zϖ pЙl.uQ8-WiJ"q =-=u51FFvÚSΡU~R).*Ei6m)P81sY܋3Gnr}1UJЉ4]chtBA&7t*ݬ==>?Lt:t W2@^8SU_uUTITV_EtJ^ZR[u\w\^_`w&v#50|Uec†PmP0m+47jG c!l0WvonB&zx%wɬs$!І!!lwlwk'mچzW~ v_v)ąٞ no84h= >mO_Vq+ٔl?xlP(ֺ, X# eo€_0yP(mPx!6Jn-=zͱx m֜ctu uzxǂhN%QMpۋŹT]w+QQk%&n8fگu}{φu8_9t;Չ f]xI pXGZ!y{9SÑꅰ?8,S,„> h'RxC$0:#Ȑ"G,i$ʔ*Wz%̘2gҬi&Μ:w'РBo(ҤJ2m)Ԋ.Rj*֬ZdXVnlٴm떖[Ă].^t/.l0Ċ+6ˊ+Ȓ'Sl2̚7s3ТG.m4ԪWn5زgӮm6ܺw7‡/n8ʗ3o9ҧSn:ڷs;Ǔ/o<׳o=ӯo>? 8 x * : J8!Zx!j!z!!8"%x")"-"18#5x#9#=#7S@! ,<! )2*62$d2p83*:3:3#@3 _3b 56T5L[71T:F"<2A=2C=*?GIB-B.#C>QDsDKE4kEkIF;eFTsGsgHaUN1L݅uNt_}A An~,|J3(Z=[Qo`@IMK73@Ra"Ɯ* oHuN)$bbhIȣBZLw¦_}Ūìk~̮]`֎ٰCKLo˳sٵX϶}ҽv׻ٻn߻¼˼6,־ųƻƠdxǵUȻJȻɾɳʭ˔{̼̼̽;ͼZ΅ѬӼԚqo۵ۣ۬ۗۈܼܻܲ߱ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+;F_Nt]?d۫xΧO?>GwWn|<d3P`t4 'ِ:M{C)擏=#.Ǐ9$T?Si::'O: %ys tO9]O?ީᏆM>jM;\ziF\Z_7oO7{ӍVXQ;t V1;tX+mPD7&EQ:0>|$`d?q=$B/vst@=%sG"XqG B :FN nr0?<HvcTVd݀?IȻM><8v{\q@-ίN9:q%,.wSxKr/.l&_ O|3̏=y/5 u I%JGݬM;xBB#5#cT͙T[Qk@:J*ݨy'#u;C1Xȩ 1Iw]%pu6:TD7̐]I00f@q#=N @,5ݣZGМB5}/LJ5ԁ?Fx'X?nwQ3V`/HMK YYBH4(w#0j vO+v 6v sQG=5"g VHȥ:G xtwEfhs,^ݐY7 v:ZJwc%$0?8L6H`  jK>+x|V1~<"ZHS70GhѪ~&nP `@ paT*N` u0$A+h  2Ѐp 1 @s,I@k Hh@$BVЂ87KPA+,ɷê>Xy0f1Y@J(L )A)?!sS45-X{"5Rjl 'ƥЍ+ H/` @ u@H?`UhD7,EB 0` IJBp ra ",L!~n,c]=h~$ p_, $ hh*'~E z#g:a <A L$44v;nv/7n M s\W.mv4A*\%ƘJ^J 1>s Gvns:`%u:qMGxչE¦#D]J 앺nBqݸ/辐sܠA#d0/ ʻ[y ~Wrݠ1W_-Wz `b4# QC#PPbL1BRhԲ|:P.&ReܖP&Sa\g\vRY`U}AЄ?,0ZQg # w_7Px_` PplvP5a @dt 1 .T )bLrG), A9iH"GpF8E x` v wipudɠT @h ]{E AS} ɐ dxwG a6ᢋ׋7P"asYȇ[8*pG=0UQL4Q5e&>&{a-P?r[P! e<'" /@"\@/.İngf1ppDi a <)"` effxq(p 7h,떕@`1VŎqDM e&  04ATw&-b#iD&F4YepvX)_']W RYZAЎo[%yą(=l9Yyșʹ̉59Yyؙڹٝ๝Y扜y깞ٞ)9Yyٟ靿y ڠ9IVF   "ZW "Vӡ#ڢ.0Y 'p  fb *pGj* e 7z [vZ=B0k)lڦnI٩ p/ Rlre  Wa& kGyZ? J Z)' 'zpZzrʧu   1 r`pw{ `o n rspJr©zؚj5 ߊ-}6`G qf[((}wU1` Xۚ 1ڭzjRpz[ݐr^pWm ʰ4[6{kW V'@ Y";&ݰJV± ݰ!;9prV  8zf{h9;6i!i 2X[9f["@nzU(˵Vj5= Pi{չI i{ƹ5 2˺J@@;3+5K D` қ{r P:pXFpp۾;[{ۿ̾ @  <\Ѱ "<$\&|(*,.02<4\2 8 B<  0HJLNPR4P V 0 Ĥ pT`͠ MH@ۋP`0  P,6܅ jְ    -= c c ,=@#$ sxykIyUݠ  BB =KH}@ hm0  P= A `@ ]6~Li {1е `ݝ*͕ qp~| lђ} c !ŀ0Ðw"a }=xF@ 2BLʹ K-՛@#"F ` 8>^ZI 䙜'I  $A`| C P qP K-́0Y.`>cf^8X8HB tN?p{Zi}nHՌ p"~nĘ^l+ l#Vc o 0AgpNP N0@\ c \ \#e\-qSxۮL>Ĥ  H@ʄ^"+0@"a`n?n r "@7}H{'[O n V)̂Le5 lO*"Y|0ccpl0\ 00z}? Lzp~|ސ\p ğ  5wI9wbvM?Ǯ R/Hp X H _ '`"ep 0 oܘ~/nM~&@ IXE C4]AP ? ED`8+ٲ\5wid@#O097pfgOg );wFNZu=]'޷ovGO:_&T2 WǦHEnu/-ij~ vߧܑB/ 4@T*Jf`f-aBhkƙakedJ4DSTqES/hi$aHDCHT>J$/@h;H$>؈CnjA24LeabL؀ iZ-,sO>O@+"`CEr`0_$In =s颍|&pFROqɔMq \ o L*4{WՌMahC@p%PfuYh}TMq:SUǐ "n4A 0[+e0b$sn|%JN0; Fdh-8ƛ]UxaՔ:TFCxM s78h2vdK69EiI 2&u&8}X%D 鈥kE:p7щ'"b1 a?VXunI9ynno|p 7pW|qwZRL+l-5\o#rmK_SW}u[wuc}vk׼GxA:`ֹ{|s!|[~߯i\(TFG|$ w!9 >ܸ_ XAP$:}  xBp$Ta BCHtGH8Aȟp c$*H `FQcC,j| 0`$.Ґ%̡ΠB@2-@Xc@"VG0 &!fPd7p\$0D@ l=Ub)4Ct Є:P!D֠A,tipcpn (eb6Fb b뙿RhU!cq)|aH(yNy:UgJx* @XXYh&n\ME)%`5ErA (!*0QwT3-hZT+eiK]RT3iMeOh DO}b" Z@! l 4 HpR-C 3@ (DN&2R"vLNV |(Hz1b؄@ npZ6;@jCeНL $DPY!-h"C8ܩU!E\M{nѮ>eP 24lZX! 'S|)"JN7n0W' Qiu:gmuGIV- P 0=%Wl9HhA۝B\1p6hvҢe (tObf Np`ݨB1'PY:AX++bŠ@:ZXsq}3͘!?Aw|d$@fr $$GYJή|pSrmd,Pr͜:0Y0Fݙfϥysn}2 l{psuLg@ AqwgHʁ#: `wmAldP՜[5P$b]]?WZ֦tlꐇ8D~Ϊ3 :VZ݉-va̫Ѩf QhGC|T& "HN"HB!A.rȤos +ڣҖԥ܈_ 1Le2/P4 f2Z_̔8~Ǽyʂ0О+? VB* 0T7HB# !BՃ22+C,+JTȈ* 8ǔ 7}ФZ!kڡm=tM~جK+.RDfdDչ>@#,mX(=2%mT8kN7.#8WաM@498n>==P#@$V 2:%JX?%J@2S:$AdTI]ITי7MJTDԴRE͢8P $U4SEQU0VmWU#dY03=cɴU\+,EPVcʡEV$aьL445)hn :;h_Vi-r,<Ck!LYHE&x$3s%D61ҧ2:#Ht$# IjM (h&,p}1~W#[V%k@N@CoTX]9ҊWY [fQl(|%mH(pqYѺX]-;u432(o2f`ZsڧeQ|Hs,&PXPEȻ,2gxV.-[-r Ԃ,PV 7>;@Fp}[sIn>%X/؉Ɇ>5&]Ȃ\b|Jt̵2J^'2s?m޷JA4ޜxE_y^]_u+VCC4Iem V0} 23,NӡVnmE@4."S5![v][Zy֑{hG)` 0 k+8 HحĂpXX?;ukb::-Da*T؂#O%{E%Y% 6 nhٗY5H] UnA)M*+3 ,.bXF!YiS(ZFBZ^$EId)dC>р!j=Ct2 _XP~>fJu5N&ץ5 ͚laLSNɆ>,VP80∝np%h  O#4mI%;Ub+OJLEVc7nR7`a(cP0/DelvnAmYE^ eI0Q!K6(O0ʎp.T+iKv\V6r ^fZ[͓ mxpJ! n^eZϹ (P#9m(̎ά't^>R(Fh z:;r ZέҘI[>em)8.a0&205E@hS0FtIr5ޯS(?=TtMSNqI\^K"ySTOuTTTUOuKnumkYAO_u^G+_Z`vv25\6vux2  vl|zvhGrAյ!lxWtmfkBIOF;p7grgT!І!!l`Lwkpdچ{g|Yt?t絁oaNąpwaS@Cr)T~x4xQ=lBmn iwxU0X36. chnלry;*lv ~o%"p34KmዞBY! lP^z# yå {v,x^Vp-l ]tƷ+y "It%P&n8fX %*N}X}ַφs6R >?5 Ym8E~_~ C7f/iU8,  |@`@72l!DW"$@7r#Ȑ"G,idHZVl%̘2gҬi&Μ:ws:Z(-j(ҤJ2-'ԨRRj*LVhqeE[Ć-{+ڴjiy+׳kE W]u/.la2n1Ȓ'Sl2̚7s3ТG.m4ԪWn5زgӮm6ܺw7‡/n8ʗ3o9ҧSn:ڷs;Ǔ/o<׳o=ӯo>? 8 x * : J8!Zx!j!z!!8"%x")"-"18#5x#9#3R@! ,<! )2*62$d2p83*:3:3#@3 _3b 56T5L[71T:F"<2A=2C=*?GIB-B.#C>QDsDKE4kEkIF;eFTsGsgHaUN1L݅uNt_}A An~,|J3(Z=[Qo`@IMK73@Ra"Ɯ* oHuN)$bbhIȣBZLw¦_}Ūìk~̮]`֎ٰCKLo˳sٵX϶}ҽv׻ٻn߻¼˼6,־ųƻƠdxǵUȻJȻɾɵɴʭ˔{̼̼̽;ͼZ΅аѬԚqo۵ۣ۬ۗۈܼܻܲ߱ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ˮ%<F_Nt]?۫%GwW;o|<t3`x4 'ِ:M{C)擏=#.Ǐ9$T?Si::'O: %ys tO9]O?ީᏆM>jM!<\ziF\Z7oӏ7{VXQ;x V1:xX+mP7&EQ:0>|$`d ?q=$B/zst@=%sG"XqG B :FN nr0?<HzcTVdހ?IȻM><8v{\q@-ίN9:q%,/wS‹xKr/.l&_ O|3̏=y/5 u I%JGެM*H&zt7L|GyEpP vn&(" 4tT &:Az ?1A S!^.{09&FQm j*(xܱ@ 7tuM Ch&5D#>R!%Xs G! N8'%!xsb +Z,41,sԔh!xw@¼2&AT=:D'ްD#p\J׺x'$:K`:恢I-@ቒ ?7DȒR1E%-kwK>X²pya@ItģDxgE2,u"83 "0rh:d0FӶ屍\mJ 5;J`NZiNi=ZFR b{4C g?[h ("Q<Wju9! L |!YI@%lݱVH@&$F@%Q<>+G?-Fj #xYhK? q tN7(00w80* @@ '8;]uA 4U 1@"-D|$eH  > Hb^*0ZALg)C*0 p%wX[0,#kZ ŊPD>(7d*{jךfkOZ@J<@!ƥ+ H/` @ u@H:SBM'1`E :nqcLrPc CX `!` @xZ uD7@+0# x a@kwb_  T@ x@$P?Ç.ȟv գAP?kh`AE H!  -1 zBz xB2*]O=l9+o{8D9M uOˇ1&;R,#-p \*xjةGjIk]8|@q\vnr~ pÂh{a; |r_p~!#7`W3y` w~y&"Wz 4rޠ1\`6_w{QmP+&A0b t1E'T#$5@-R}:Q.&Rϡ VV8P6S\\vRY`}A?;7IPZ! # # _7\_p pqvŁa Idt 1 .T )rLrG), A9iH"GpF8EMy` vw jpuiʰT @rhP]|E_X~ ʠ px7 Aa6bP"bse\8*pG=0(UQLDQ5~#&>&{1a-Q?[P! Bf<'" /@. ]@/.0oo:ppPi q%.p %rrrp 7q,VՇ@ 1WqD;   04ATwt鰃-c#iD&FYpX!`'^W  ^ oٛp\9Dž(U=Pm9Yy؉5ٝ9Yy虞깞y՜I9yٟ9z jp J:z VǡF  J*,ڢ.W .V/:<ڣ 'p  2gg *pS**o" `P2S? f' @- $^¶>zxz@Z&jr2 7 "Pw6 P2_p"Fa0 @w稐  sq 8:٧ 2 E z q`b E  :' g)26vJ:ZVc䉫ޠgFy &7j0prx*sa `r w~7Y j[ۣ:ʮ#Z*WPmp@  2p &7@y:ui51pղc i5 ' ʲ.[K  `57Fnp Br;Iidy 1В o9P[S+U&{8) e9gk5nаV.pK;v+k[;0[;[m гKK D [곽 ;@ : @;`ۼ۽:  5p޻컧eWp p ;| <\L  "<$\&|(j+ .Ґ 0\6|8:<>@B`3J.yP.pb Aǝp Rn ~0ߠAl` Zn q` KĹpq-nc0 Qcsi}] W LZ NŴZi}n[֙ p3~>_ť[m+"_m#VcR  l Ag@^` N0@` cl \#x\hr_ڕL[ Q ؈C@o2 B4TsM%heabL؀i`F,O@tP*$Q8H9*": IrohC" '޳h,q2Yȅ.abW`m͂)BtWuYhPW}u[wuc}vk]Vn s{otL}7xW~y揟x7l^y᫷`AZfz|kץzMQPpA"JX}mo=-WPw`7>}AWDd  m$ѹ"evJh@P8! U@*L F ,$@F@?1n0h1"!@S 0 HW$IPϊLM&*^@.ԁ 9'۸B`HӠSxc#h|v)0zahJ Ɛa!Ich 0EFJtux<՝RJ%;Ё/JD)chdlDBaKI"D'qM܀;cxK l#%iw Z+eiK]RT3iMmzSS gE쓟@ol# EEh8TF%ъ  )z7Po̠*WQN+f1N(|aXmLԁֶX;ߋec Tc$'y>r!+YS^v|e,er|;&gYM|fՅyk1f8Nlw,Al{ދs;:wHNh?G:Vt:4ų fC@>:]]9@[Z֧$7BpÜp=F(D"vsXeݑOYMOglrы`^Ϙ5:ÍNX;Vd{2IA\D"HHJR"% 0 J( mǰ[hxa&.F480yL`$s4BFv2cC+FVt &[x>UJt^ P򐰢@(-a$to8ftFB R̗l]8gm^HT"LH+*ZW* bGI-h`]b' #\|+`ۈ!bXQ(2)Z(/^lZ-^ζ-v\Ȯ&#(GJ`s-z";=>z ⽐+͋ފtCH6+Ke1`lsR)`f*\s0N1MA1a@{@9{>@zC1@*? (3#@4 A,lJA@tA,  AA?A!A苲B&d"4Bգ1C5al|B($ 44 aàQ6-;.lB/B2е "ڔ-lC|C89i>6~kS#66*6 P8Xi)Az{X"k(*\%g(#A@SoHx9Q|C+%J*m`*#E6-a@b,FKÊȹH(;Z*A $Fo0i#FFoc\%r$#Z꫿ *,?wŭG| דn٢-ǫ3H=d3GsaB /˨2+C,H4ȉ ю8G H#,ȅmX(=2%kT8l7M쮁+8TT܆M@498n>==XH$V!2:d9I&@W("M*@KqNJT^j$Rk@,h5UPGnx89m@(赊0EзQ#+ĭHxH0mp'L QSrSX%bPX$U3&)$@mSS85,?fPG}F}TG}H]SeTI%3CբT.N8LնQMO5!DTmUeUtW̳=k͔UZhX;,X׊M'e9g`we"n4gWe+مQ}sD;2=n2g8Z|XãH,pp0PEȻ2%h`4װŲtвŠԂ,PV7>; Fxۼ˕>I\8| cڅ,?U-.۰lJ`K֥O}JS]߅+s E3^M^ [^^4u^m%6U<."S,~A-`L]kW-ZWzhE!`~ʼn0Xl 0X;Mm؇]](IX&VP\DI$΋5TmVِ"ao8YeY򈤩0Xa$9bq*~lg:VoƽZȵv$EI8? dz+*tZڊF ڮd dr麂;联?PPQR~ b<'ܨc{[l[ 0VLl #8abuZ>=fVͣe"dۆEǭNo7nc,Og)*%Iϥ ҽS#A &jvӒuRSc& e ]35@歐J(oaK~iQ^ Sωj #ފIx^.ԘիЬ1߮k߱>^QNk8sf\eu,_ \,k=1,ll5t5u-Q.anzWSЀ,&4\mXNh@ vX7(]0.x a>ҞV^3EXɭ4Y$+h;>&h,uV2@80I:eln9mY{Ą|kMCd dC@+fHP:^Qf6z# ]_e< p n W4E(X#9f(֬/jqór% &hl>h ." ^җ֩K?3Nܖr;>1#G-*Eؑ6cX@oA'_ޮՑjxk!y%8Phk\P{{v,(^[]ю(a B!8ʼnZ|{ȇ5ɿԡx?lQ RL P|?!]Y8f%:0n#wt6җ >=Պ X@7U~aW 7S!yYS˙<"i9,{ n1l!Ĉ LHDE7r#Ȑ"G,i$Jֱl%̘2gҬi&Μ:w'MuR-j(ҤJ2mjr%ШRRj*֘ʊ֭kV״jz׮hҭ6Zy=/.l0Ċ3nl'Sl2̚7s3ТG.m4ԪWn5زgӮm6ܺw7‡/n8ʗ3o9ҧSn:ڷs;Ǔ/o<׳o=ӯo>? 8 x * : J8!Zx!j!z!!8"%x")"-"18#5x#9#=#A I;-! ,<!))2(62$923/73*:3# 558C*<5A<3B<*A-)B=IB-JD4IE:FMFLEVO<$PSTPDZUG=ZZa\Sb\KbbXkdTqk[Glmrnbysc]tnxtkqyr}yk|lS~^~~v^ۀpnsALV0{2uA~O'5xd}bc|Vᑁ@JbHSzR4br /MKCd$:{m+ޤdTΡVxd;7z wƃLPhK}üm2wFöijݰſŸłżmƵƝvǶǴɹ]ʽʸڠʷO˳˼qȮTĨӠxƑײ˶yťjΖݤ͐{͹ԥԃܻۧyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ++%:F_Nt]?亁۫i%uΧO?>GsoWY|dN;t 3 .0 <s<<"Ѕ~g<߬>3اDs-ӎA%(T#t4Ԏ>{ҟ@㈐@a8\q{o@>=0< 4B $+8# [lB+٣;责35$4O>3̣ON~.j=@qOwS&zM8I) tx?#a??:c A7I)4  '`# 2 9b2 9\$Ow"^S꣈/L;@:LQ8r (>ޓ*S  WR!.VpP|O?H8pYq)]XE. *,)э=uԡ 8h, uS5; >7Њ /c:b *x9, $890,_s!ɘ:PP8NΕTBO?]K/xM!7B@5~W…L$+A! X<A@7ҐUHtt3z\`5 SBİ@N C < pܣG5,eC a(2c)t(@x_sX3kHG5ұNL(@6awƒ q =GBz= ZqB0X v8 0 1%s案%dG a,t<ͮI$5wxO#&b>NMz|]2$hg1|+btt"~(ɀQxI⩊ B86 sA=H;|0$? R}22|`#I p' b :# 9 t@q[5*9I"m1ޛǟ"5NS2GrL`0\O!}&Ҟ6Pd8 %AWX~H7x!jhHyp$峴C  Pld`3N(@9p`2'Ѕvc_sh1euls -`) 0j? @(Ʊ `+:Ѐl(qt#p>%  C0 "@.#p\ A0Po^d  i!Hh3ЀgwЍqt9h@㊎C Hpǂd(?C;@C l]xxCt8T xP2l:nxKơ \|`E1Z  hM0 ``@Y?$ 7+2V,|N!gl _t>Qi# A 0$+fVB|0xpD0= z ?Hwr,BH \Pʓ@P@(驡G#Nc2`\C5f()ePy~p P) Bx%~@@Dy~_NhMc?F$|U PO0wӗGA`@Ɓ kR|)x Yp G}S1S|Us@`T(4Pr(+ 5Nhq1`Ec} j\=M؎: 묯X{ )Wƶ|p \k`| 0  p  ۯ۳ڷ} 0 ̐}ȝܦ* ϶ٵz}Ī* ` ۴] m=p&P}̍ 4[<,{kE@ M >,0D$P ü.`jz*^ *0-1>0..~6^..B>Dު*~a\JnHKMOQSNU~WY[]._^a._^4;dj]hn[]NmCyB}̪.γ> 0ی^ > 菾> M>^~ꨞꪾ믺6pp]a8&ρN*$qaЮ]Ҟ d@ dMc.4ۮ@ Oy*z|6hVqT agQO@p@` Q QOPT@ћ Wp@4 qhqqѐ O Ġ G@PX@+? PoG y Wi*'edI_Ko@ @p_cG ~ G@ ؞b!0X3X$Ypoo`p Tg@'`d/ G @p0Q@s- )?Q @p Ǵpp_#Gp 8`Em ;!&W5G!E$YI)UdK1eΤ)Ӝ "wN'gEhGFoב[`9k8 Y5֎\C3&0F.+*2P]y_|odt![GJ;2ODr̓'X8c @:Qܩ $00` ,d@ N9kc`'^gsWĈ+-;v֣3B>8xe K=rϧ_~Ks9p!4@TpAA#pB +tA 3pC;CCqDK4DSTqE[tEcqFkFsqG{G rH"4H$TrI&tI(rJ*J,rK.K0sL24L4TsM6tM8sN:NO@tPB 5PDUtQFuQH#tRJ+RL3tSN;SPCuTRK5TTSUuUV[uUXcuVZkV\suW^{W`vXb5XdUvYfuYhvZjZlv[n[pw\r5\tUw]vu]xw^z^|w_~_x` 6`Vxava#xb+b3xc;cCydK6dSVye[vecyfkfsyg{gzh6hVzivizjWjzkk{l6lV{mvm{nn{oo|p 7pW|qwq#|r)/! ,<! ()2(62$:23/73*:3# 558C&;6A;2A<+E>%%A9A.JD3IE:FMEKFVO;$PSTPDZUG=[[c\Jb]S`bYkdTni\Glmsm]ytfjwo|xppys~yj|lS~^~~t^ۀqnsALV0|2uAO'5dw}bk{V~`@JbHSzR4br /MKCd$:{m+ޤdTΡVxd;7z wƃLPhK}üm2wFöêĴݰſŸłŻmƵƳvǶ]ʽʸڠʷOʳʻ˼qȮTĨӠxƑײ˶yj̖ݤ͐{ՃܻĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ++%:F_Nt]?亁۫i%uΧO?>GsoW9Z|dN;SM., <s<<"Ѕ~g<߰>3اDؓ-ӎA%Ԏ(T#t4Ԏ>{ҟ@㈠@q8`q{ p@>>8< O5G 4+83 \p+٣;责3O6$4O>3̣ON~.j=qOwS&zM8IIItx?#a??:c!7K)4  O'a3 2 9r2 9\$x"fS/L;@:TQ8v (>ޓ*SXRa.WtB|O?H8tY)^\q. lэ=uԡ 8l(  usM6;(>7 /c:r *|9( 48901a>=1 NyHͅB'c@N89WR >xq/䡆7Ks%5~d }@sb1#"5l!3{CU&XWZMn`—31R+Ni`D6`K#d 885Ed k :)(ؐO8ɠ=>dmu8:%P!0+c @%ey7b,C -iMpZ4 փ>H8 4(uMi`15:VAp ^*`HP VПq@ R.`"\KpB :JbB0 #Y]B1,B;O0F;q KJG2 LX ,P XBZ;qtS j:1NXġ{BϑPwp,VlDp)!X^5r|" 1L y0 BZJ ϐpkIc.hiሉz|K_ !dLA,Њ#J2vDFjax"xA2"84 `rPrҎ((ɏt߃ H(܉tHNi1HEZtAŚ%Py̱L (oԎq O<Ʋw9c H= j 3L$"Ŏah( {C ;$@fhHG〄HL)kVbs$ j ,@耍͑H8:4C)`;8lla;@PQRND1NpŧZ F;A);p2 d EȻ7 H/D ػf0=DlZ"P 49tc@rЀ @0`SP.v@)8чܺ.`<.5)qb0=ebu֌C=a A3  ! c$ A>," @/#"&V CÏъ 8 O89z B ҜG$0 6,Z`2V 8a &dz8 }PG5,Cp'c0T>@Jzk|ȈȊ@̭Blfۋ`l _΀lFz  |AJh  9hr "t nK}\ovp ؠ9b;ļ: 5~ɛɋ?&,0l 0;'"A` Zw(PSk̟ 0 ;z"@E"" Yl`[`Np ! mP:J \ʇ ΠR_ }@ PR}'`@ܟ% X ϛ| L m@9]NP.Ь.` DM*j60ËCS=ٔ]ZڷJ c*F j Ѐ }۴۹۸- 00 @lʽ]{,H{@ E;o ` }۶'0r]P<ݷ3O;ڸ E0 ۩.0 0m">l.:Ê  ,2> 569~?> &ഇzHJN J>TV~OnZGZ.WNTnQN}&Ƹ_.q^^PKGkz~,0ۂN>芞n @疞$j6pZqegAhk >X*$a] e@#I$Nc.4î@0 PP>P>5zʑgV bh Q0P`@0 Q QP`V` ppGqpqqq~.`Ґ P I@`Y@O 8I@ Йwzzzm*@{20 V` VP G/EIpIPېp Q))3@"1AO`lLL? I A@B-Zj V Fq_#I r0W})& o@*FΝ$܉+ .^QED9rQQEtEbV"pEZ9 wb.#uOA%ZQI.eSQNiΆTv EÕJݕB$xh@R&#. ٹj.TvC a" $Ճ7sR\e̙5osSRϹӋb7֨&w"ĝ}gqBRɕ/gs^uٵo]ghŏ'_y㮢g{񵫗_}p@ 4@TpAtA#pB +B 3pC;CCqDK4DSTqE[tEcqFkFsqG{G rH"4H$TrI&tI(rJ*J,rK.K0sL24L4TsM6tM8sN:NO@tPB 5PDUtQFuQH#tRJ+RL3tSN;SPCuTRK5TTSUuUV[uUXcuVZkV\suW^{W`vXb5XdUvYfuYhvZjZlv[n[pw\r5\tUw]vu]xw^z^|w_~_x` 6`Vxava#xb+b3xc;cCydK6dSVye[vecyfkfsyg{gzh6hVzivizj/jzkk{l6lV{mvm{n.Ϸ! ,<!2'62$:23/63*:3# 558C&;5@<2A<,E>%%A9IB-ID4IE:FMEKFVO;$PSTPDZUH1Z^F[Xc\Jb]S`bYkdTni\Glmsm]ysfevo|xpoys}yk|lS~^~~^ns>LCV|02uAO'5w|dbc|VP@JbHSzR4br /MKCd$:{dm+ިTΡVxd;7z wƃ@PPⶲhKk}ý2wĿ}FöθijmƴvǶǿǺǽɠɽ]ʽOʆ˷qعξTļѨӠԼxƑײ˶yj˖ݤ͐{ԶԹۥՃꦹܻۧyĨ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+ 9F_Nt]?۫I9uΧOxN?>GrgW"V|D;TJM.0;c;蠟;"Ѕ~g;ݠb>|3PاDԳM,ÎA%N(T#t4N>yҟ@P@A7~La{ l@>9$;r 4?ҍ E+P8 W\т*գ;簣3●3$$>#ȓON~.JN=<#N8@Q>0aOwS&z7Ith?#a??9cK7F)3L &] 09"08dR $u"nS+p ; 6taLy?0q;1E("XLD7C ~| iqL̢̆]8I)R,x 1I> +8!98s" CC >a+I=δp3BN6/Ƹ% N.J(I{t@t >4".| `1(G#-2;$r72P8*N4ч +6ĂI lk8,@ 6BĠu=7Ă qԓd )Sޡ;<_sPʗ:PLD.ΕTBO?YЁ .wC#sD Ǔ$pvˇ B#+"\:  Q.0yE"Oy'28AQy0 q @i}Pņ'كF@Dt6~%@pUBhg;Nۻ"S.@>B#.8QLAHȇ|`A "?+Ů!bFDjB &g Hw'ՅE-rQ- MhftSȠm& UC6qQ+PLmȄ !-@$[#6Zo U0r!LR?p U#G@0h`qGlF?=x ВV.u d0.ȑ;dP @0i X`LA֤Lrc6U`.x4ċ" +&ȕ``~bej"8<9PG.j's0~sX! !: >d@D b$TEqW0(r`T94!(He:ᑔ# ĝ6Y =- dV xDQ$\-FG\Yό0!>y)R}34)r PA &"bA:@E1!Zhhv0,$qҁt)rLb(&ҕ3D(p1Lp ؒq!`]d`?F9C 0v qnBƃ t(R* (@(E9t e!OA@) @ =?xb (j(-,` vHٴB` .n_#ց6± ( QW9q`q`p{8G6+2 C4@DnpS@؅"nyۛ1+(OjF| x-(D! T à $!_8lB (LB  }"QrCL>gH+qoXHIHP4 e8Cp80PE& 0>Lzf<_PEpS@ 0@eDr( 0 'Wj`y } @DEe6Ad}*X_ P$Z |'U} A|$0;)-}})@yU }RQOP~0q~EGK~ `2L%`Z -d@f@ ,b F;D> -Ї~XMwHVjaxDP%P;  @  !6UP*oI`Pӡ pDbrj@pre >} nr}`p @ 0 66Q.HP@.V@#8#@ . v z)Z(zybPRV/7 HPᐋW $@Ћ XrxM8 g P z6AO!~9n` @9<@r~ 1 "' L޴ 67 0,ۮCTUPJ2;ʱКCSKPS˴ PZ7hjlKAp ]>q |8;C { }  P k *m; :P+WP ` < ǰ + y~kP/` 0[vj  hvqj [{^; * * о  &'Êǰ>k`X */0 /P d{  ЉQ``v𲳐rU x 0{HJ ۮP[~[ j 0 ZlY q?l  ;j IU 0 7jw`“`{ ۵ QzYc ` E<Ē<ɔ\ bmB.@^=~HnJ~NC^T^zO~WKHl'S>R~jlnnm->*N˭uS,%^膾j3pj)J^41,0@)1$DrdN4p0P Kp0ƾ^p^5z}gqPP ^cMPKNp00 MP M|K0Ppqwgqqq ǡ. PͰP K P D 0T  p2 z@ )gz@{`{h`*{OFa P0 P +/)-pN~ D 2TZЃaC8N` Ppc^o!D`0 D ͑0@CPP;(O@tPB 5PDUtQFuQH#tRJ+RL3tSN;SPCuTRK5TTSUuUV[uUXcuVZkV\suW^{W`vXb5XdUvYfuYhvZjZlv[n[pw\r5\tUw]vu]xw^z^|w_~_x` 6`Vxava#xb+b3xc;cCydK6dSVye[vecyfkfsyg{gzh6hVzivizjjzH ! ,<!1&62$3/73*93:3# 558C38"<2@<2A<,D>%%A9DC+ID4IE:FMPH4FNF$PSTPDVPrgWb[|T;4-c;c;蠟;"Ѕ~g;ޠ>3اDS,ÎA%(T#t4N>yҟ@@A7Ha{ӏ l@>98;r O4AM +P8 UT*գ;簣3O5$$>#ȓON~.ZN=԰<3N8@a>aOw+Ï7'%$wӡ=jk|;,@_2+?p(7` sT 6㸓 6d>@a ,Z6"BPC2,2 6Dyᴁ@jAy?0q;!(WHу7S ɀiEA`:]8Y) B,|; 2I> G+71N9Tc" 3 >QC+`+RM&Ɣ 24 1 c *"|R::tc$|?D3G3WAJH.;8 83P8*N4чJ+5 ̂ pk84@6Bu=6̂O qԓd B)Sޡ8H_s Pʗ:PL@>ΕTBO?X /wM$A:i\xBwhA2`~cPD Ph9e9h@ s4E>A&(*&`1)"AҪ h}Pņ'كE0AHF$#aJl@jc{Xq ؖAȂw&|8 9<"ޑ",>A2hŸڵ=ËH[?x I~!4H -.MhetSȰj&G USD5qQ+PL@@Ȅ !,Ԡ@A"a]c5ZЄo 1r!HR?pTCF@ i#FqHhPF0=x њV.ul8,ʑ xZ hH&] Ӛ3qd@N;T .`' |d #H W B=wBqoF1IL#Vh( (9 =yPR0a=S?:3 GC 5;tPȤؑr d;t|rZ:4?{c*t+)DjB Zs0~sY! ):4?d@  b$TE aW0(rbX94!(He<ᑘ ĝ7 Y =.d\` xDQ$\-FG\YϔvqHOGaTOz,)N#N8"P84(Z(ы?gA;j1O!tC q @1|vA@a  @9X; e9.(PBD~ Z ha58~Ak $@8 ؁FaHvv7~SmЀ00px@{xp" @̡ `/6-%0c䷿[ Q[9q_=Nc'u Tp–ToHšL:]("m68)XzbȘ `7Jǂc59`v `S #@`JCH@ pp*c!H7|DF!eO(@qD A@ -y?[A(a{"A`7r$NpT@8ʃ8P B.^PDPS .`bDs( @ 7gj0y ~!0DEe6Adz*`h^ P$[ y7P} !|"0;'+| |)yP }RaN0~q E7cI~`2L%`ZP +d@e ,bxF8C=4 +d4xdG$?$@ @{ !U@*oH`@FC H6H$(Bxa )H8?@FЀϗ h#g]QqpG'0~0` lh#Pp sG$`Bd0lk0?r3"`  y)[y![@ eJ9Q q 1dUhg"xrhK8g 0 zVAO!ʠ~9o 09:`r~ 1r "' L icC˳ND-d ` Jg}6I v`Wh U  KBj[`VfK`X#)*0O PgP{@8()9T)֊F\Q%hp0QP\ɖ|ɘ\@0;!m 0 @ [cLX ˠ  [m@HP @ |mwܷǔ`JkʻL0 1_+ v |Η!0"P20ƪ &,;}0F9 a }?R8 2ȋ !`d̲xk[p|Ԭ`?[AΉP2=ӡ:s D븞ϯ? Џ^PЩ,0}Vຬð;- ͊ ͺ [[pmÎ mÔL|~m6} hq@ u\l(-}`}H@ )Ր-@ h  x@} R j} ` 1L/9ȝm$.[ !P< @ < -к JԤ  P̀ `pz P H **L ] *pF 0̚{˽: пP :~; f}븣P ۲nݲۿ+p: ^Vc R. ίqk*W><#ηtYN0寜Ͱ .Z +O~S>tUY~zk+5KK Ͳ ŀHpJ5u頞~.jέd^ f~ [+ h,NyN>~쾞ʞ.NnĎî:?x^9n~C 3Z}PZ%}0 %{+WA 1 QOa,0@)1$a+@GC0:p#TIǝKr@ظGZiŏ'_|ȑ-%C[׎D-装ΩOT qb1 (> *@ $J4DST#:FP֩/6mTG\"F;HtI($J,rKZK0s-IL4TsM6=3M8sN:NO@tPB 5PDUtQFuQH#tRJ+RL3tSN;SPCuTRK5TTSUuUV[uUXcuVZkV\suW^{W`vXb5XdUvYfuYhvZjZlv[n[pw\r5\tUw]vu]xw^z^|w_~_x` 6`Vxava#xb+b3xc;cCydK6dSVye[vecyfkfsyg{gzh6hVzivizjjzkk{l6lV{mvm{nn{oo|p 7pW|qwq#|r+r3|s;sC}tK7tSW}u[wuc}vkvs}w{w~x7xW~ywy裗~z꫷z~{{|1 ! ,<!1&62$3/73*93:3# 558C38"<2@<2A<,D>%%A9DC+HD:ID4FMQI5LJ=$PSTPDVProWb9[|TN;$M-S <s<<"Ѕ~g<ޜ>3اDS,ӎA%(T#t4Ԏ>yҟ@@A7Hq{ӏ l@>983̣ON~.Z=԰<3N8@a>qOw+Ï7'%$w=zk|<D,@2+?p'7` cT 6㼓 6dP>@a ,Z6"BP2,2 6Dyᴁ@zA?0q +71N9Tc" 3 B>Q+P+RM&Ŕ14 1 S)|R::tc$|?DK3CE3W1JD- <8 82P8*N4ч +5Ȃ pk84@6B=6ȒO qأd )Sޡ8H_s Pʗ:PL@>ΕTBO?Xб.wM$Ah\xBwh2P~cPD P!h9e9h@ s4>A&(*&`1)BAҪ h}Pņ'ݣE0ADF$#aJl@jc{Xa ؖAx&|8 9<"B,D>A2`Ÿڵ=ËH[?v I~!48 --MhetSȰj&G !USD5qQ+PL@@Ȅ 1,Ԡ@A"Q ]c5ZЄo 0r!HR?pT#F@ hFqHhH0=x њV.ul0F,ʑ xZ hh&] Ӛ3ʁd@NG;R .`' |T #H W B=wBoF1IH#Vg( (9 =юyLR(Q=S?B3 GC 5;֎tL#Ȥڡr d's0~X )G:4?d@ D b$TE aW0(aX :4!(He<ᑘ ĝ7 Y =H.d\` xDQ$\-NG\YϔtaHOGadOz,)N#N8 `84(Z(ы?gA;h1O!tC q @1|vA@Q  @9PF; e9.$PBD~ Z ha58~Ak $D 8 ؁DaHvv7~SmЀ0 px@{xp" @̑ `/Ra6-%0c䷿[ Q[ :q_=Nc'u Tp–To@šL:]("m60)X {bǐ `7Jc59`v `S #@`JCH@ p0*c!@7|DD!eO(@qD A@-y?[(a{"E`7r$N`T 8ʓ8P B.^#PDPSp .PbDs( @ 7gj0y ~!0DEe6Adz*`h^ P$[ y7P} !|"0;'+| |)yP }RaN0~q E7cI~`2L%`ZP +d@ep ,bxF8C=$ +d4xdG$?$@ @0@xHbQ `$ i1dd`Drm rd ؋?|!n8r~օ^ppg PP @ 651.H`P.T@ö#8#p -  0;aW GyNJ!F[@ eJ IA q 1dUhgג" xrhK8g zVAO!ɠ~9o 09:`r~ 1b "' L icC˳ND-d P Lg}6I v`Wh E H KBj[`VfK`X#)*0O pgP{@8*)9T8)Fؔ\Q%h0Qp<@&PX# "6 v& ?\ T(@`Wa `WF @ `0 (e (n{ } X(j {` 0$ P@ Pd'*e CFH@]`Qƀ Ih H @0@T pX%qHPX Pd q2֧)`W@]:Q%کX М`1a5;wOzQ) zȚʺ: ̪:zњ׺ܚjϠ ~p0#z:Zzگ;J*Ϻ J Ъؚ  J ~ ۰ ";$[&{([0 ){2K0̠͊ `  ;HJL۴N+;O: ʳ ;VB˱{Ujl۶nˬQۯ0{B/P W.*s+:$9{s; °Pvk)[묛 !( px 0v vpTl `^  pV``v@[@`?`2 [pÇ`@ɚɜ|BܯP[[!m @ [ele ʐ   h|'ߪsL  `̻| 30a vPΛ!`"2PƮ (\[}H) a ,@:h; !`fx {[p: ̼`?0[D{ΉPܱ:ӣ+u+ D [-;} `@Vڬ°: / ϊ Ϫ [[ m0Ðy:<=؄]I!̀R:!dž(^nn~{5{z}pZ%} *.㛭+Wa 1*Q, "@@Vu)A$a-@IC@@B/@0>@@BoPg1hSi:<J0p ]J@OC0 c0` {KO: q1q 'qqrQ?r C ̿};[P B p.dC%NXE5nG!E$Yrd9%=a4;UOΌ2^!čg)'>BS5NwչZN ѵ *$2`Yiծe[lQszNxs0>7B9.ҦCf5~(p*DBD50iԩUf$)R=%c̱~ᒌkPw|4fG(w_DWy*!)Fİq`'Vկg)I[ݬ!JH%|ĝxPB)oN|!q`1 (< :@" =ZtEcF:+`؁J!v%Rst̡Lh\+grK.rvrL24L4S1M6tM8 G8N<?<2A<,A>$%A9DC+HD7GMLK=UO;TPD*TW[UG9ZYb[Ja\Sh_RdaLfaTjaNeb[jcSjeZqgWni[qiVnjcGlmsm\smbvqczscyujzys~yjk{pX||k~sPPaqzAsK{/_Suy|"B|-bbc|V~@YJK6bn~'a c7ME'GtWdf1Vѱ~ YqͮjGoU滵úͬ6ľy߸ȿv»µOĸܛĹijĭűoȷȺɠʉʽ˹лP̻͹xξμcìڥҸzs֛pȈʚۼ͍k̶Џԩ՛ڼڵ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]U۷pʝKݻx˷߿ \ᢚ4eZ̸ǐ#KL˘3k̹Ϡ#k:LJR^ͺװc˞M۸sͻoוFȓ+_μKiسk<3sOȽ_R<+ߍzy} g_ݧF% ߃%݁Q`k&߁[mx!AhbH!kn|}[%-x\]`jqC7[%&p`"x+x X4H!HHI AX ZɇGlČxZ%hqA䚐hƋuV $M怕Ģ]`%b4aXfXIi`rpٰA9z*  e||@$Op0+r0)% ğD!,&Z_mIk,܇-%jj.E< q0Bd0%]@BQr t0W&%WAbT0' !p)@b p&hr%6 4ő $e8|B @rB!$\D%묩,tAݜ3g  Rbv%蛾62B x@F%og΅ZD `'`P6` pDv&ž}ЄĶgfdpB  tiI6A}Q)D EPljF(-%(pdkCCf`& %ôbaB5<{|l@/ ĐF.V2v}MɁaj-!,T iD d0=', I R m8X  D$d kB OA2JeYH $p8bH`/L㓧>ȧ @,Y"~IЁ"(|͢Z8q V)>n@Y OHd9ȠS!*p- AɂMTc5=Aa*dFY !H)Xd %P ̎^{ AЧ6!N ︦."zDM=zqb*A \H&rBy`[\;(X:^q;%0w'3I^DDG1ND9G& HpJHpc%҄StCZu\-lhHi'MDfO 88PձФ&'d oH/}gu@ T)OE!~*CP F@NfJ 86COA,m[aJ%G׫p zlBnƒ T%0JN03kѠ ikcx ́Smg2M^5 \EUǻ"b,fQ#(OX 5C"}ֶNF4 (l֨p!H #4 DFD#5nYk:c2PbuFzwS p 襁LF"ʇvҍQ|Pb'䕠,|ki*źpI_ !.G^O8'pT^A资4E99ABQW H.BjnCKdɤU CH%([a(It+A2sT<"rtGNU_+:\s/OHɡ7i@ЇNHGz%xX9Dб e|AfQ5!!\ C lO-"s8RQ,$*?ȓ#6F-Vqw y'y= D&@?\Ɂ~b e>DRs}P0P13|'? _I*j,`M㡎who=У=^z#G;$u ~@Q`r/P yrЁpvz|'P~|4X/|'t0` g7  _7@ @ 3 Y~ I0: >7PSr]'kqp Qr` pv`\  H `p[uF p`0!|68qW}t@`@5P 3 3 p@ @` 0ptP/ P 3 ɀ @`ɠ ' 5 w s`\@|-g@e70 P x [P `@߀ v, yt~C` .p 8 .0 R0ˈx7P p0ȍ`r u@ QwQP {e~Py  z !!yx'~/ t3pJ50 :P .:9ь 9`@R~.pG&ZY[{7L`vנyP zL`vي8h"p mp`P5 88 p +׌ KauPXC0 yrP Q`yG\l IF@H L{̩<$|zi"w 5Т.p90 .8 ۀq@~:u9θ @a` + xi R ' v`vG` L`ivנ֐ ``F Q` sw/1%v(j 7 p ؀ 30570/VG:.w@OJew 5e0 .@S X0 u65וy{'Fp`F kFuv  :٠ڂ|Ǩ@9@`5 ZףOgУZG@i ۯZj[*P1 0Jhsg'w]` wiv {*{ *m캳1'" gZG0  Z^ jSxfsha r1<=XGДp '0VQ$=SrqCi478-L"$;8)7kR 0PaYYhyV+ej+hD$n ,@U<뮇+q;R'(x3-A%'DI|$& 9S Eຖ0& P\|5;:_+;/#P*+ip<2d*b|a#-^%uCt4N &DadK|*_4 k1^h3;RԻ>xpR f %;Wyq  W?q^3e1\/-p] -pF+\\K4@_#Em` %uP&<  Y\&2J/S 3{6K$oO/C b0dt61LII{"w` Py |@_LtY rK4#@l\R2;}CMl0h'QFee5aYrУpɀ !xpwMI{,lq@pQnoaL`s ^N {ec@H?b`$8[6E.l &i_$CjLȈɰ< p@`谘BpC JxA_H Jp@lOW _B 1 pa - ``ϴ0 f4pE j0`m@ 0#"H36F5d0ъp@ "`< 1p 3`ۀ p~j0 B Pp  >@ }W ذrZJ $G#PM# P@hPδ@ 0O@ [$?5#]sfp+`q`  rp `~09q7y XCpp5)w@ 0 @ >n,J(C-3.-|]=0  `|w~0 K;gpap PPh0s~q00pܟ,0 @@@Smn6@lMMP٠NU Rpa  gg:@ w~+PؙHgl7GunpJ Z, .Hn-nbP0wL@ -oW><0w  <Bhp}pPNo0` ִP0 [ '}!#` c 00O@p*0 7+ :pg- Q' @p0#@J|j n՚Po dpMc= ~Ӑӽ<~$cO 0wЧ } tܐ @Пѣf+ǟP.  Zs'Zzk+$XA %%NXE5nG!E$Yb%M UdK1eΤYӦ.nthOA%Z(ʝI.eSꠎQYnu(RaŎ%[Thɉ#(]T*ͥ[]y_&\aySeܸ&$O\e͚M< eϟEO\ziԕ9k9lI\( Q]o'^qɕ/gsѥO;*Zٵo{j,xs6Or4KuK(O2eDI&p@ 4@TpAtA#pB +d2pCË֤8̰D 13ʦ/]r>pe]f${G rHT$H$Q*II6kV0{1VX2>QGsL243n@HCKpYdVŅ=hVzQMZ0fRiTFq jhx)^&,)"\#>1.lD4K53$.M% %+ >e xE t,i[wuRV/9}\>g@zVbS]D(FQ1xXU;dCNrT RЂU8V)0 w&3<^{xhyI'o%RM E[=IP&߉ 494`#2A4Qxt1Ci D<'4C #-a8Mxqp1rUF({-F "]d5OQYІV2M dI S&eQݮd+ Ko&qa)v5;eo{ٛ"׬o|[~M;w/j\E:pߴ0} \^2p)VW"T(VW2 Dh@ĸрsm|'&<;pL BD-jq|d$'YKfY&G)Dr|e,gYNyre0Yc&sͼc %qf8YszC d9@JYЃ&t ;/G=y4p; 'tm}k\/9JGBa+!ްF;! T6P69a +َȇ,"A*jrahF a8x1,w:)`^SF; ' cӀȑCp±aщ|tXUBֽ ޺ s(  x}s |';a,"Ȃ# Ɲu,z #屶B "(6a1"z~w: &B'ȑw" c@y@=Uҁq_{ ӨaQ|,A`Gi$hA wq {]-&,XdUw0>G"o _%myH*=/a}1 <` hX<`O#c <d ҆1d5;K#Ѕ2rX 8`f JH ? @l whpXX'X4=p#HC- w@"8@#V3q\ҩԩ(#T\jMB*BHx༿3eXwq0:JC/|46qK{ cf2B=CCC@ DA9,DC?<2A<,A>$%A9DC+HD7GMLK=UO;TPD*TW[UG9ZYb[Ja\Sh_RdaLfaTjaNeb[jcSjeZqgWni[qiVnjcGlmsl\smbvqczscyujzys~yjk{pX||k~sPPaqzAsK{/_Suy|"B|-bbc|V~@YJK6bn~'a c7ME'GtWdf1VѮ~ YqͮjGoU滵úͬ6ľy߸ȿv»µOĸܛĹijĭűoȷȺɠʉʽ˹лP̻͹xξμcìڥҸzs֛pȈʚۼ͍k̶Џԩ՛ڼ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]5۷pʝKݻx˷߿ \ᢚ4eZ̸ǐ#KL˘3k̹Ϡ#k:LJR^ͺװc˞M۸sͻoוFȓ+_μKiسk<3sOȽ_R<+ߍzy} g_ݧF% ߃%݁Q`k&߁[mx!AhbH!ko|}[%-x\]`jqC7[%&p`"x+x X4H!HHI AX ZɇGlČxZ%hqA䚐hƋuV $M怕Ģ]`%b4aXfXIi`rpٰA9z*  e||@$Op0+r0)% ğD!,&Z_mIk,܇-%jj.E< q0Bd0%]@BQr t0W&%WAbT0' !p)@b p&hr%6 4ő $e8|B @rB!$\D%묩,tAݜ3g  Rbv%蛾62B x@F%ng΅ZD `'`P6` pDv&žЄĶgfdpB  tiI6A}Q)D EPljF(-%(pdkCCf`& %ôbaB5<{|l@/ ĐF.V2v}MɁaj-!,T iD d0=', I R m戴2U\; TaMhz"8@ ?A@ 0)؀G 8 l<ib|t!Җ%9KO>p:PeYCP '*RӇ9я7"K4 lR3wwjW"D_ 7YtIjL'(LDY !H)Xd %P ̎^{ AЧ6!N &."yDM=zqb*A ZH&q@y`[\;(X:z^q3%0w'3I]DDG1ND9G& HpJAhc%҄ StCZu\-jhHi'MDVO 88PѱФ&'d nH/}'u@ T)OE!~*CP F@NfJ 86COA,m[aJG׫p zl9Nƒ T%0JN03kѠ ikcx ́Smg2M^5 \EUǻ"a,fQ#(OX 5pC"}ֶNF4 (l֨p!H #2 DFD#5nYk2cJHnjdR44@H$ݠ@РNQ#j9XU >5_9#q-MEX,< ɼ$23 5[kQ Nʋ hxHt' LpP^+TjL#2UXsr BWDj[[nMrI&mv݆nx>5Uo| " gHio; p?ARd!j4GN\K9\r/OHq7i@ЇNHG:%jxX9Ḏ e|툺AfQ5\ C lO{-w8RQ,$.OI\6j { ikiG= $&@?\q~b e>Dq}LxP13|')(*j,`M၎vhoz=ұ#0ڀ>`W3>p50+nuyQ{-\@ j [`Qp { [Q0 _gL BgH%GtP_P 0P0rP 7 ` B0 Q8`3@5P `0P  qPy@ 8wr Xvy@ àP `P @ְ~P ~h  0  @ oy1|&r~C` .p 8 .  R0ʈh7P `0Pr u@ QwQ@ {e~@y  z ґ yيW~/ t3`J50 :@ .:y9P@R~.pG&Z Y[{'L`v֠yP zL`ᰑvYzy"p mpPP588 p +njKau@XC0 yqP Q`yaٕL` v iǜY7&}g P. XZ.ٌڠ .Pa` + xY R ' v`vGp L iwv֠Ԑ ` F@ Q` sw/1&)j 7 p ׀ 30570/V7:.w0OZdw` 5e  .@S X0 u65'{{'Fp`F kFuv p9ؠڂ|#Ǩ@90`5p ZOgZ7@i ۯZZɠ[*@1 0Jwhsg'w]y@ wiv {*{ *m캳X@p:`0 !pyѠ%'r6gcb r1<=> MI @ya`ui!ESi0%jiV ?y;Cq$B^` rpVe6i+U6ejh4Lb 4Pkāp7]"1}AMb3@ mG װrZpJ $G#PM# P0hPδ@ 0O@ $t?5#]sf =p+`q@  rp `~09q7i XC`p5)w@ 0 @ >nJ(3-3.-|=-0  P|w~0 ;:gpap POX0s~q@0qpܟ,0 @0@Smn6@l=MPؠN]~npa Ў g y:@w~+OؙGgl77unqpJ Z, .Hn-nb@0wL@ -oW.<0w  0p =xч@g ><BhP}pP>n0` ִP0 [ '}!$` ! c 0g0@p*0 7+ :pg-G Q' @p0#@J|j n՚Po dpMc= ~Ґӽ<~"cO 0wЧ } tې@Y>Ќuerr P. a qZz?#O@ ތ#X8M,-dC%NXE5nG+i:XI)UdK1eΤ 5OA:2QI.et):ĉKUYnhTaŎ%jԳ g\*JΥ[]y_&\a$.fL\h%O\rfͤmvrgϡ%s&-iʛ3K :26h.zBT\H(o'^qɕ/gsѥjٵo=kZy7M\gấB'M2i_p@ 4@TpAtA#pB 5%= 3pC ېh 1$1@l2iE\O\fEY,D{G 24:qJt2͚\̅^q'sL2˄44T3=%1 L190dDӲ|3VLf =Zh TPQ5CuTRK5563^hn"N`FUWe&[k=]^u6t-oUK`Mfhe`%ȔF0tSw\r-3U G VM$Yh64ɠ"pW>" '_aUH,(&  x8@pu"hhX[-P\mqco5hV;tcTLTZ Q!8D w2~IKHWr|P%zlWU\ i $`ff-B3Ґ EH+d%&U H@@O `Q,_(@\tD(FQ2ϪhlV*@ V B*B&@b8aЀ`bA0Ë2lO3@4 1`=! \5 <꒨)\hb'=IQ;21BD&&1Bn##4Q\W!fq%4 .n *P3GJF* h⚴"ɓYgs3l!h2'ANxSM pYT:0A̖ܳ aA[ F9Xf`W3 3ep ELhH4BE5 ``;O05[0EgQzT ѳ;"X4!)VR4bϢ(ӌYmT 3fR=j\{ "E kRH/ΘYZ0&"U{v!Qz5EVEFvE@\ ^F!j_=YF毨ԙ +>]`o“dU0ꛆeO5|Ҍ3*ӄzeREb4 Z5e<;Z AHhm"8Cڍ,ea ZB$.*\b'ezQ^{^7oiE_=̀ lH~>wP/)l] 75@VP"QClXFf!h-OmnmDҀgAB%-=&r|d$'YK.9vd(7eQr|e,g)N&e0Yc&sucvЃc6f8Ys2yLca,f+H8P :ZЃ&t]bg\Gp8iv@p9}-CIBp:ֆum}k%#:)B(`4Vh'd VX& 4Y8Wda h@.*^9.qk/AT:,聏%' ;-L$-`!wg}]DT, ŇArTKK>oIha /;*C= ?s=C@ DBA,DC?<2A<,A>$%A9DC+HD7GMLK=UO;TPD*TW[UG9ZYb[Ja\Sh_RdaLfaTjaNeb[jcSjeZqgWni[qiVnjcGlmsl\smbvqczscyujzys~yjk{pX||k~sPPaqzAsK{/_Suy|"B|-bbc|V~@YJK6bn~'a c7ME'GtWdf1Vѱ~ YqͮjGoU滵úͬ6ľy߸ȿv»µOĸܛĹijĭűoȷȺɠʉʽ˹лP̻͹xξμcìڥҸzs֛pȈʚۼ͍k̶Џԩ՛ڼ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]5۷pʝKݻx˷߿ \ᢚ4eZ̸ǐ#KL˘3k̹Ϡ#k:LJR^ͺװc˞M۸sͻoוFȓ+_μKiسk<3sOȽ_R<+ߍzy} g_ݧF% ߃%݁Q`k&߁[mx!AhbH!kn|}[%-x\]`jqC7[%&p`"x+x X4H!HHI AX ZɇGlČxZ%hqA䚐hƋuV $M怕Ģ]`%b4aXfXIi`rpٰA9z*  e||@$Op0+r0)% ğD!,&Z_mIk,܇-%jj.E< q0Bd0%]@BQr t0W&%WAbT0' !p)@b p&hr%6 4ő $e8|B @rB!$\D%묩,tAݜ3g  Rbv%蛾62B x@F%og΅ZD `'`P6` pDv&žЄĶgfdpB  tiI6A}Q)D EPljF(-%(pdkCCf`& %ôbaB5<{|l@/ ĐF.V2v}MɁaj-!,T iD d0=', I R m戴2U\; TaMhz"8@ ?A@ 0)؀G 8 l<ib|t!Җ%9KO>x:PeYCP '*RӇ9я7"K4 lR3wwjW"D_ 7YtIjL'(LDY !H)Xd %P ̎^{ AЧ6!N &."yDM=zqb*A ZH&q@y`[\;(X:z^q3%0w'3I]DDG1ND9G& HpJAhc%҄ StCZu\-jhHi'MDVO 88PѱФ&'d oH/}'u@ T)OE!~*CP F@NfJ 86COA,m[aJG׫p zl9Nƒ T%0JN03kѠ ikcx ́Smg2M^5 \EUǻ"a,fQ#(OX 5pC"}ֶNF4 (l֨p!H #2 DFD#5nYk2cJHnjdR44@H$ݠ@РNQ#j9XU >5_9#q-MEX,< ɼ$23 5[kQ Nʋ hpHt' LpP^+TjL#2UXsr BWDj[[­mnمvMrCG&mvݵ5nxTo| " gHio;p<?AbGDBGkz9Kas a82w9͵w@ЇNGGDy8*9vP7,*0{X01s#p9⁋adhEQWpC@*0R$irި*<{L:y1z`Gӯs؃@<ΑpТ yq Fp -Prwxf ؁ǁ{W[0| w p74"w"Lw 3 p @pB`P_p_PB P>0ހ>`W3>p50*ouyQ{,\@ i [`Qp { [Q0 ^gL BWw%GtP_P 0P0rP 7 p B0 Q8`3@5P `0P  qPy@ 7wr Hvy@ àP `P @ְ~P ~h  0  @ ny16I7` : ` aIa>@p90PCX *g~9 QWpt 88@v[y L ɀP+ vyx"@00 /mPP7y'̸ ဓ/ t '.g@~# @=` ^z\v`` ig Lv0 Ywx&F)  7/ 5 Y9px`r( P@/`JPw` >9x z]L` vi9˗&}g P, X헓Y.ٌנ .P:P ɰ 8r ̀k\ e{ v`\` @ @ F` `  w02Hjo&zp p03P9` x30Pu`3/p0JCJ.pPZ:yɀ.QoCs\wLw{QpL`wqF`ʐi@`@ <`S -Ǘx !t߸  GJ0ؐu 0P:O @ L A`A`L|P APPf00Lj(T!0#:hckY#@  ``"p+ ` 0(a0p @ g `z  5 ` th~ 1 *g iP P= ?0Ly4n)<bEL ` 0@ Pw_MbAS3M0`VyAp` *Ca~/9pmX  l*P 7]qMq<yi@Q`=Ρq:ށ*<"߄^pa0؎, %zp 3gpap POXz0s~q qpܞ,0 @0@R]n6@k=MP٠MT Bpa Ў WW:@g~+ОOșGgl'7unqpI Y, -Hn-nb@ vL@ oV>< w  o0` մ@0 Z '}!"` b  w0N@`*  7+ :`g,G P' @`0#@J|j ^՚Pn d`Mb= nҀҭT>nQMPCuTRKM ZS QUUVZl/WD!c\\SՒƺ`eZxXpI.0 HeF{@'Nh l_h">RჀ{(-JdW3JRbT@j^nI^F@ !@(@g\P@)/V}u[iSN5I1>H;=UMUNVKx+B4 ~=k:똹b?o%iA@!\~tU]D;O"8KAw6M`jŬBUcF44 A{@,a h‡+bE>EYFu`D(FQ8 8يQg (A VBVA(BTBl34N8hB &$0C ?exQeQf! Qb0$pag837 -uQd'=y)vU&4ЀY4FQqa0 P 1  14a4 ĸU `D)HEZ ZXsV]HxƾhCvv-1M'Nx)a- 0 X&H@ٰ{vbA3*X3@+ьS`j2aY,o@=!иh8i @@f4x ,@@gdt h$jQyrXF6"TFUQd1Bm b,@GA #cO!S(aIQ7 V0 KģU{NR/֜4)RQd"ghԃXXtqYK>Ckg=Y42a#'MwEy!1܄?fOqe@/L >fA Vˍ'PLgd7 3,A \7VU^u|[_%mh7KS/~φ[ [ap8]JP## ;]($ i%Cé̥q81;.TC&r|d$'Yd9dSr|e,3Cre0Yc&syzC,Ff8YUa 5l *1g@ZЃ&tK꜔w;hF+hqG9ݎG/ZM^s ZXúгumC#Y|t Tp#,P K>Bq㐇1 e;V8D@a @q@f@Zwq {#vM_8F(eHK>1j ņE'qWb R1X6fbOhkZ,T̡*$"P7@;yypx1pP" +(>Wg6:ґ%KX:Nbo - D  @s{ t# :, httLEK@1^%Hc*X=]x$`ND+3,g}볌wȃ ;:`cR9ڡPux1F>[~ 7I8 z @rw}}~&pO'a2:%b8q *@8|Kд#Ѕqx>H0`fJ8? @ \ vX>hXX'X$=p#GC-v@"(@#V# q[©ә(T[jMԻ B)B@wм#eXv:q :I C.l45p Ck>x ;f2B?<2A=*%A9CC+HD7GMLL=VO;TPD*TW[UG9ZYb[Ja\Sh_RdaLfaTjaNeb[jcSjeZqgWni[qiVnjcGlmsl\smbvqczsc]tnyujyjzzs|kY}~sPPaqAzsK/{_Stuv"B|-bbc|V~@YJK6bn~'a c7ME'GtWdf1VѮ~ YqͮjGoU时ͼû6ľyȿvµàOĸܛĹijĭſűƵoȷȺݠ˹ѻPͽxξμ·czİs՜կpȈʚ۽͍k̶Џԩ՛ڼ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]U۷pʝKݻx˷߿ \ᢝ:qZ̸ǐ#KL˘3k̹Ϡ#w:Lh'KR^ͺװc˞M۸sͻoזFȓ+_μKiسk<3sOȽ_R<-ߍzy} g_ݧF% ߃%݁Q`k&߁[mx!AhbH!kp|~|%qw".x\]`jmAC7%%lP"x+x X3H!HX Gh ZɇhČx%dq@䚐dNjuf $M怖Ģe%a4aXfhة`np㩣ڠꩬ  e|x0$Ol*n0i%.**ğD!,&Z_mI *܇-%jj.E<q B`0%]0BUr p0Wf%WaX*$́ )< \B$n 3^ 7^b.ф' KdCŧ]QT |K& .?4aPM p@(-q:k 5TfxC4 ;zQDzC40BA"Cيw<;Y#㚸#5=0`!`fxFnMrMvȅszM T~­ܝ 'uA0E<8Ї A5J)9Tx-2`1WUjL(E<%vK)̀ &xzCfo6vkT4~B#}`5tA%Tg$6K %1# v"3 ;iUml@ TA>)谓$`F:b]D$sN*rIE2`!Z?5xTPd+B ueBvLZMIKDrVlњPWiZu1dΔF$ EkX6Ռsii@w$` ķεsMaߚ@P ` j!J-t ζBj qt[nCWJwMouޚwocGKa34wA  a@, ywn .A;ءr' 1r"w@ЇN919.sad~kF<Ž{#,gG5@Sr['lpw QrP qv_\ H_q[uE `p`0 t|42p}t@P?4P 1` 10P@ p?` `t@. P 10 p ?Pɠ 1' 5 w `s`(s`0vy@ à@ _P ְ@ }h  0  my0aR~C`  -P 8 -0 R0Ɉh5P z`0Pru@ 1wpQ{c@y  z !ґ yɊX~.p t1`J40 9P0 -:yy 9P@R~-pGa%Z qGb_z\v`` jW Lv !ix3WG)  5. 488 p (K`tPhC@ ypP QsAٕ LP v0Y {L{͙<)&*xy"w 4-`8@ 0 -߀r@~:u9x  9P ɰ 8r ۰̀j\ d{p L`gwv֠Ԑ P`E@ Qp i-'*j 5 p ؀ 14Ћ5.T7-z@Pjcwp 4d0 -`S X/u63{y'EP1PE lE wv 쐬9٠b|ڮ &@8p WJ0؀u?t?upj 0`SeZ{`v.Wvpו owvhײ` !>P%` g.p0Ay APy<gqr6e#"/b AДap 00TQ$NUSⵕV!÷27;-L"$2 &sk P]Yec6RgRI0rL$,0 e>+'(w3-@%'I}$% 9c G0%P\y5;:$?K;/"*+j`<2c*a`}`#-^!uBq4' %D`+˼Z|}*^$ k0^Ph3T3<xb e EWyQq 7s?E;S=@P 0Bs] ,;+[c\K4_Nm| ! @ qQV! %an+ 12-l,]D&]$2"0F]QdKܮMpw`H Py"|`bLtaϢKr4"0oR 2+|#Ml0g''6%eUȆl Wr pɀ #|x⠯gM9~,wьq@pQnodLPsP^rN x5c0H?b`$6Zt6A.| %i^$i@ / +p d0p|)50P~I5Ѕt~Ϡ5n hlt> 0P:O @w`G`<}  @`P`f  L$#/PgXY"0  ``!`:0p 1P׀ P~Z@ B0 @`  >@ ]7 ؀r0]`J ` #pG"PM "phpδ@ O@ $;5#]se- &`r@  rp @~09r5i XC`P4 9@  `0 @ J)C} %\ϟ,߻t W}p ``ّ,(̗z 1gp` PNXy~dPPApݝ*0 @@@ "@PG MPl[> p`-  1 y9@ W~+NؙFgm 77tnApPpa΂ LN6@d  0(.ߡ h~z Gp004` p pxnn?ʤ0p =xPgp  _<Bg ~Փ A  0]`մ'}%f w@)` + 9g0G O' ?/ "@J}z ՝@pcd-.RT~"i Χ | tPY?luh{rr P,z 1 _jpـ.8_Z?q'`{h9 .dC%NXE5ntX`LJ DdI)UdK1eΤYM9_OAڅщ%u.eSQFUY"Et8J%[YPne[]&'Naݒ_&\aĉ/fcNh5osfͤsiө5fkΣCK:s6hRd J-'^qɕ/gsѥO^uGAkwŏ2yӢFWsv W\ԟN* 4@TpAtA#pB +B 3d:C Dڢ4@0+ͤ/]hhTG rH"SsH$NDGDI(;KtlF04<Б(sL26X4s|̀(DµҺ2ٓROJQa1ԣ3h hL6CuTRK5UH7=^hn N`UWe&[k3]W^u6t]oK`&Ufh`ҸG.tSw\r53G VU\h4@_}'LFf08 `+׆lX BM0 \H!7 d`5`ٶ>\6hCF;aYFQ ?APz7$pţV K  l`Vw5\(`@xQ$Gfp # 2JdGpV}u[gsNcI0<@>WM VnKp -BxDq <(`icXY .Ǖ#ap9sae?vtP*{jUx u #^ff23Ԑ GFK+T%(U H@J/ ,_x}BҝTdb=]i![9wBM'XAK A`K @! Љ0ppW`@m@Ì0cE<"K GF.@Gx ?:(fR<Js`+NT t8(0Bc`~uOhF WBcp0b0z h.-I.R=gkw2WZoa ukhdg;C*e@ (hzv!aA3,(x4h;#4`f`W3 3exEc,Mhh3LMF5 P`:0N],|gQz y򓵚O6&*SfUagMh&b+BzGB ÔZ^aQEOGlFiQzWtj&O)2,cPjtۖ0WfVw%% lR~(:E36+#Nm$gt Mr[b%nq)" )IJk[KZӝnc7ÌKZ宥UVm{^5z^7z[oz_7h\B1`:4osI3֒5>v`B#&yTXLdyvP|, 9jX;q}c [/r{c#'YKfr!OOr|e,gQ~K;ю\"Z&s|f4Sn1֐~ Hs|g<9D;AztюvN8Awϑn-A[1/R90.K|jTZmYOPX hG7@'8NW#h =My #aDd! qCl@ xf  d'@ ^Ha6 Īnx{"ɫWhKvx%p%x'0H44x81rhd 9"ԅ\2`(#VZbN0<T@ B!t1pjseXٛ;4˹;4&<ٓ14f@)B0 C;C3C?C@ DADB,DC?<2A=*%A9CC+HD7GMLL=VO;TPD*TW[UG9ZYb[Ja\Sh_RdaLfaTjaNeb[jcSjeZqgWni[qiVnjcGlmsl\smbvqczsc]tnyujyjzzs|kY}~sPPaqAzsK/{_Stuv"B|-bbc|V@YJK6bn~'a c7ME'GtWdf1Vѱ~ YqͮjGoU时ͼû6ľyȿvµàOĸܛĹijĭſűƵoȷȺݠ˹ѻPͽxξμ·czİs՜կpȈʚ۽͍k̶Џԩ՛ڼ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]U۷pʝKݻx˷߿ \ᢝ:qZ̸ǐ#KL˘3k̹Ϡ#w:Lh'KR^ͺװc˞M۸sͻoזFȓ+_μKiسk<3sOȽ_R<-ߍzy} g_ݧF% ߃%݁Q`k&߁[mx!AhbH!ko|~|%qw".x\]`jmAC7%%lP"x+x X3H!MX Gh Zɇh0Ōx%dq@䚐dƋuf $M怖Ģe%aYXfhة`np㩣ڠꩬ  e|x0$Sl*n0i%.**ğD!,&Z_mI *܇-%jj.E<q B`0%]0BUr p0Wf%WaX*$́ )< \B$n 3^LQ 2k%f"b`$ hQ- :k l0%6LG51Tbٷ榯m4ũfqa "! _'`P6p o8x6NžЄ&Y@£j0]^ Qnsw2E@ CA;tL:J"U pwD 5 A%IlA%X&fD!4]j6k1YF`0"2R7n*)C$#fЄa U{f)\4FPI53*"EZ,#@„ c] ?Wp)uM(@ &xCfo6vkT 4~B#}`5R =ꌄ_p75@4 + 4 퉦 $U1"/P`NZ WÞIv;BէZ D^Ꮾ>C ;^`MƩ&A@ȀyS dqxzNDPP5S_æ 5I1YU Y1ie6EhoC&".YFkB\Qhw_]ef9UAP"yr5Ps,FjF ms4;m`PfIGbZֶ6plM[( 5VՆcU%Q}b[ ECn{ 8InNRMn,[n{]o%0H2p[O{G"qc gҦ{|bwr8yo#Aeh8Ϲw@ЇމqgQr9t/5qj#a=# @N[$E7p XƉ[!(<챍ZB1L(W@QAĢG ~ rrܣ)4G+>d\(0V ;N;8 >PW1>P4 %'puypPP{'\ e [_P q u( [P@ ZWK ',X )GtP^@ PP 50p B@ Q7P1@4P ``  rpPpy 3wЇ/\ `Lj@ ` }x [` _ v* Wi|%7` 9 P`aH@a>P8PCX %~8 Mo p 8 Hv[yKi萐`@9r9'r~. t1`I40 9P0 -059yPa 4P@Q0~-pa%U nG]iZIz\v`p e`W KvЀ !tّٜWB9  5. y4393 p %gF`tP(C@ yk` Pr񀲉 KP xvY {K@{ə<"ڂy"w 4-`8@ 0 -Iۀr@p~5Yu4Ǹ  9`  W8r`΀g\ az0 K`dwvנՀ P`EP Pp i(1#zV&j 5 p ؐ 145.Q7-z@L*^wp 4`d0 - R X/t60zv'ŹEP.PE lPE sv P)٠"|}&@8p I0Pu;t;Zu䰓0*z ꀥ~0\RЪa{0v+'vmЀlGve` !Ҧ: vy%Pp9wp: R@  Kov-g(gS6"jb1;OEK%290;xb e 5:Xy!qs?\3e1,7W`k@5u 4kNT @ qQS! %at+ 12-\,пZ۸D&]$.U a b1HpP8`%Ay'! $4;b nKr4"0m R."7ts6p9|,0h#XeNKK\&r ܰTWr簣 pʀ #@ ВPr [@J `@#`G"PEM@"pgδ@ S@ $;5#]se-  &`rP  \rp }09r5i X`>ɔ`P4 9P  `0 @dI)C} %P,߻~t W]p ``ِ,(Wzp@XpgzPpnI^ 1g@AJ-ѝyjO,0  0 n!i ~P* .垼 |Țp`- p . Ay9@ ~+IAgm7tnpPpa~ LNE6@c LP 轂2o]:w  :2|Q@`@ 㶣Hj ڟɋ2|U 0x8p`P!-f Z=Np p NUM 4 y'N-aP] _Qr/0p0h0p ytP+@ U=|10ÐzIrЫ/tPL֮LJ}z ՝@pcսc-.Ӱխd_Tnu 瀠ɷ | tPY;9[F&EU R%'^qɕ/gsѥO^uޣ9{wſ&hy|jg޻h7G .ZquωSJ:? 4@TpAtA#pB +B ;=;.p6i+m9D;HLie\ttQKIG rH"DE#TһŒ%,4g.3gt`F}rL24)WSM6k=1KHJI\o=;#M8aOKTLt HN装#.FVc0uTRK5T"0hze;V8YeinUv]f|5XaQU=V/alvf/\HFeQw\r5MU9 `U@t@gѠ} #> &`UH*(( -q ^x@r# `h`[+XF[P\^5hVtsJՙQX`Q#8E W~IKH W<`zL@l *О *a~GQ{6({E0|l9s)#idKB]zu[w}Ԧ݋f:g3WODh&J@mNd5*Z@;Z/Á)Զr8P J>㮙+``g)g3:.u"`D(fƀaH9Qi$HA ZV@w^~fF KNhfL/ʀ\> M4p@* $r8l.04EQѦ8X@LӘXaP!~G1(FpC˃3P727#W(S%VDCx4hAZuI Тz+M[Dd;NQ}R<*e@ (hzvAa3.8`4jCc4` gh3 3eҀI$Mjd&3JF9@ P`;0],gQz!S<"4AV25O6hDT-Q3XR<,BK"FRPD/̘:-K7JTUQ*LTEI`VTYmS |=91P+ &&U,fBiU'@i=- \I qMf<3MXh,Hlg{\xCZ[זyFu4Vw{)r;%oy"󦷵Uoz|Cw]kGo}+_V/{`>1p<>w6/a>3!1DM|eq2lW"\%3q}c Y9|Kfrd(#ȒQr|e,gY[z*|f4Y͓2[q5\,f$ D(+ ZH` nK@ 9@ZH[3Y8FPdvp;J8h%J` p-@ $G @kg{ۯ|s# 8, h#]'[ 80 @`a`t@Ah @^2+"*xEawtEEoW:xDt2 LiG vG_ӧ)'+p!W0v %$T8;aRdT rJr^K@\hvx%p%'0H04481rhd 9"܅]B`(#VZbN@<d@!B"14l=f`ګS4۹S4'Lګhg P*+B1C; C4LC5T5\C7|C8D2q08C;CCC?C@ DADB,DC?<2A=*%A9CC+HD7GMLL=VO;TPD*TW[UG9ZYb[Ja\Sh_RdaLfaTjaNeb[jcSjeZqgWni[qiVnjcGlmsl\smbvqczsc]tnyujyjzzs|kY}~sPPaqAzsK/{_Stuv"B|-bbc|V~@YJK6bn~'a c7ME'GtWdf1VѮ~ YqͮjGoU时ͼû6ľyȿvµàOĸܛĹijĭſűƵoȷȺݠ˹ѻPͽxξμ·czİs՜կpȈʚ۽͍k̶Џԩ՛ڼ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]U۷pʝKݻx˷߿ \ᢝ:qZ̸ǐ#KL˘3k̹Ϡ#w:Lh'KR^ͺװc˞M۸sͻoזFȓ+_μKiسk<3sOȽ_R<-ߍzy} g_ݧF% ߃%݁Q`k&߁[mx!AhbH!kp|~|%qw".x\]`jmAC7%%lP"x+x X3H!HX Gh ZɇhČx%dq@䚐dNjuf $M怖Ģe%a4aXfhة`np㩣ڠꩬ  e|x0$Ol*n0i%.**ğD!,&Z_mI *܇-%jj.E<q B`0%]0BUr p0Wf%WaX*$́ )< \B$n 3^ 7^b.ф' KdCŧ]QT |K& .?4aPM p@(-q:k 5TfxC4 ;zQDzC40BA"Cيw<;Y#㚸#5=0`!`fxFnMrMvȅszM T~­ܝ 'uA0E<8Ї A5J)9Tx-2`1WUjL(E<%vK)̀ &xzCfo6vkT4~B#}`5tA%Tg$6K %1# v"3 ;iUml@ TA>)谓$`F:b]D$sN*rIE2`!Z?5xTPd+B ueBvLZMIKDrVlњPWiZu1dΔF$ EkX6Ռsii@w$` ķεsMaߚ@P ` j!J-t ζBj qt[nCWJwMouޚwocGKa34wA  a@, ywn .A;ءr' 1r"w@ЇN919.sad~kF<Ž{#,gG5@Sr['lpw QrP qv_\ H_q[uE `p`0 t|42p}t@P?4P 1` 10P@ p?` `t@. P 10 p ?Pɠ 1' 5 w `s`(s`0vy@ à@ _P ְ@ }h  0  my0aR~C`  -P 8 -0 R0Ɉh5P z`0Pru@ 1wpQ{c@y  z !ґ yɊX~.p t1`J40 9P0 -:yy 9P@R~-pGa%Z qGb_z\v`` jW Lv !ix3WG)  5. 488 p (K`tPhC@ ypP QsAٕ LP v0Y {L{͙<)&*xy"w 4-`8@ 0 -߀r@~:u9x  9P ɰ 8r ۰̀j\ d{p L`gwv֠Ԑ P`E@ Qp i-'*j 5 p ؀ 14Ћ5.T7-z@Pjcwp 4d0 -`S X/u63{y'EP1PE lE wv 쐬9٠b|ڮ &@8p WJ0؀u?t?upj 0`SeZ{`v.Wvpו owvhײ` !>P%` g.p0Ay APy<gqr6e#"/b AДap 00TQ$NUSⵕV!÷27;-L"$2 &sk P]Yec6RgRI0rL$,0 e>+'(w3-@%'I}$% 9c G0%P\y5;:$?K;/"*+j`<2c*a`}`#-^!uBq4' %D`+˼Z|}*^$ k0^Ph3T3<xb e EWyQq 7s?E;S=@P 0Bs] ,;+[c\K4_Nm| ! @ qQV! %an+ 12-l,]D&]$2"0F]QdKܮMpw`H Py"|`bLtaϢKr4"0oR 2+|#Ml0g''6%eUȆl Wr pɀ #|x⠯gM9~,wьq@pQnodLPsP^rN x5c0H?b`$6Zt6A.| %i^$i@ / +p d0p|)50P~I5Ѕt~Ϡ5n hlt> 0P:O @w`G`<}  @`P`f  L$#/PgXY"0  ``!`:0p 1P׀ P~Z@ B0 @`  >@ ]7 ؀r0]`J ` #pG"PM "phpδ@ O@ $;5#]se- &`r@  rp @~09r5i XC`P4 9@  `0 @ J)C} %\ϟ,߻t W}p ``ّ,(̗z 1gp` PNXy~dPPApݝ*0 @@@ "@PG MPl[> p`-  1 y9@ W~+NؙFgm 77tnApPpa΂ LN6@d  0(.ߡ h~z Gp004` p pxnn?ʤ0p =xPgp  _<Bg ~Փ A  0]`մ'}%f w@)` + 9g0G O' ?/ "@J}z ՝@pcd-.RT~"i Χ | tPY?luh{rr P,z 1 _jpـ.8_Z?q'`{h9 .dC%NXE5ntX`LJ DdI)UdK1eΤYM9_OAڅщ%u.eSQFUY"Et8J%[YPne[]&'Naݒ_&\aĉ/fcNh5osfͤsiө5fkΣCK:s6hRd J-'^qɕ/gsѥO^uGAkwŏ2yӢFWsv W\ԟN* 4@TpAtA#pB +B 3d:C Dڢ4@0+ͤ/]hhTG rH"SsH$NDGDI(;KtlF04<Б(sL26X4s|̀(DµҺ2ٓROJQa1ԣ3h hL6CuTRK5UH7=^hn N`UWe&[k3]W^u6t]oK`&Ufh`ҸG.tSw\r53G VU\h4@_}'LFf08 `+׆lX BM0 \H!7 d`5`ٶ>\6hCF;aYFQ ?APz7$pţV K  l`Vw5\(`@xQ$Gfp # 2JdGpV}u[gsNcI0<@>WM VnKp -BxDq <(`icXY .Ǖ#ap9sae?vtP*{jUx u #^ff23Ԑ GFK+T%(U H@J/ ,_x}BҝTdb=]i![9wBM'XAK A`K @! Љ0ppW`@m@Ì0cE<"K GF.@Gx ?:(fR<Js`+NT t8(0Bc`~uOhF WBcp0b0z h.-I.R=gkw2WZoa ukhdg;C*e@ (hzv!aA3,(x4h;#4`f`W3 3exEc,Mhh3LMF5 P`:0N],|gQz y򓵚O6&*SfUagMh&b+BzGB ÔZ^aQEOGlFiQzWtj&O)2,cPjtۖ0WfVw%% lR~(:E36+#Nm$gt Mr[b%nq)" )IJk[KZӝnc7ÌKZ宥UVm{^5z^7z[oz_7h\B1`:4osI3֒5>v`B#&yTXLdyvP|, 9jX;q}c [/r{c#'YKfr!OOr|e,gQ~K;ю\"Z&s|f4Sn1֐~ Hs|g<9D;AztюvN8Awϑn-A[1/R90.K|jTZmYOPX hG7@'8NW#h =My #aDd! qCl@ xf  d'@ ^Ha6 Īnx{"ɫWhKvx%p%x'0H44x81rhd 9"ԅ\2`(#VZbN0<T@ B!t1pjseXٛ;4˹;4&<ٓ14f@)B0 C;C3C?C@ DADB,DC@<2B=*(@7;@(EC8JD5GMQL>URLg9I(^ͺװc˞M۸sͻ߯'e*Mg+_μН /Nسkν//}r#W|>t'g?J'n27Ɂ߃#(]l-H!~~BhG6"kl-ہAHw R\]ځll;X%!2zgÝh%& NHJ<֠8NRhu#\ %0߁ȁ$r"!t$%`Mx b$/^饔lpNix**ꈓH 8:kzz9IkNBh9&gU#ЩCVI鸕f l$|"ࣣ*toI"B pN0$WA /"&Ó&h#|P…NHRC lP$!q `e[ &*o:*Bt|nRA=78 M"~p@,  C~' d@&QY|u:P>w-Jdo jށ+xzڐЧ#xBU <Шi=Pxp!)6Np?9"8 I# $) Z Ja5fԐ IhNG$PHꈇDC0*J@2`j:rC4pw 0(qHȢ  !{:h2ب%``Rк!l6% ,6H>yT!`\&I_;1xɆp:RM >7P 4!#I#j$A7 nD'% ,ax[6*JnT@P>1{UQg^ K 7!]aV} &KuXYM_+=~Lt$ /뚄 Ќa` Ye( *9a Ę(98:4&kPZ!6K`"@adӕfYajp l@ga6%)3^@Q"Z'b[`L=-Ł%ϳ8KyQXֱhofS<f `z "tM% Lw$fP-!)R.3GDn/ "# L3Pn@<2iDຕ`E6KF1f@$2 Cnw[,eavE j3`z)IV #3`^\ˊJbJ=2%N0fJM,Y,ix͊E% S 4%qZ 3`!@{U&gPm%]Z6 Fpp!B߱7 JƸ5o} NƤ, Cn),Av&tζ)Te-n{Y"NwMz[~[8Z!ɾgH ^ptL  ;rFB.r'Srg呂R"|G p :W~gtGy\CampAw aWOwC@Q*p?{ } @xC x< O!G4 s|a1lR1S X.nUzc 1P0hGP]Wx> pZWP xq DP <`sx8xv<ȇ}g[~q x !oP~u P g6p ^60 >2` s H 9 <6@Rs0kpwׇ` Ps@ pw_\8 _p`[vD` pp 0 QX(g%7sP^@  P 0 6 p A Q7P2040 ` @  tP{ GwC \p tx à0 _@ հ~0 X ! 0  P ~{5w<ٓvI(@ 9 p`aH`a<`8PBЌ8 9'8P a7p~ $9w@w["x L)`ƧM:铔Y'. s2`I4  9@ -PW9wPVP0QP-p%,7ͧ|i|\v`P G Lv Q9ل;iɓg"@ m`PpI8PXPs P>.PI`w@ <`)zl@ P ԩL@ :wI }L`}[FzgIw 4-`8 -Yڀq0됀WvV 0`@ + PzQ ( wPwP 7w`\P D@ @ LĈzi"@ 6 P ` 2 46 .e7*-y0qjwp 4d  -R X0vpND|'DPB@D kpDp v 찮)נB~08p (I0֐v_u_vЕԊ"˧ Ч0R0:}pw?gwwy' 0 {!Rr` !@p9wP7 !{ aq  ;a.F b6p! 4a[qp 0 eA$U+չ|rVE-2,R9i7RTYeCi)L"UĹb;P[Iںc00%K2oI A^UYFLVC "PҋǕ3{ !d{)? i0Id"<H|N&be& b"<(Pr?+뫾c + %QW% 13?bL l$259 P,, w#Ul%'t2qpD;=:eO&`S*ppcCR/T`+ZP:u\@,C\E<@ %qv@M<p p \Z'EJ-# ap1)€RQ@}FP0fs64F5Ǫ[p8`%a{wQiLqBAr0K DSd#e},#!D&`[YeŬ !q03v9w_ րĤWP XI`7@ LWM (̢#Ov$r.bfc+c1iZTq`L 0000 +d0Јu6  H@6sΐ6m@hu<0P ;N a`@`mf00|P@PPf L{0;_QY!0?m,` ``@@$`=/p 2PP Z A @`  <0 -֐s6 "@G!PYK!`- @ 0 0-PP4 3#K%-AP 0` 9B!.9`mXΐ l n 6Mq,{i@Q >؞T q:CWvڤ 2 g@e:-q{O*  p  nqN@F KPPp|`G0 BWW90P'+Рjbgl'7vnQpP@ȾBaW wNY:@ %nP0 n4ɀ= w 0==0~; 4@ P @z,P ZmJ pT~z @z8p`-1fp  :p ? ]ز7p׸05_aq1 pn/Pp0 Cs+ =20zpt00v y!@ K| K .ؙPc@M`7ڮnu w u܍#w8&9w̓w.yYtp.ɄØDxm׸Dk,Q Γ&Q"ZQI.eSQNZUYNWaŎ%[Yiծe 4f[ +T]yo_p&\aiC$X%O\eoďAiԩUO10B  -8j cf g  @  v P7.@/Zy\8_vq#xM6JؗQT@QYFrgp)gBU>T7Xd$y!Y 3D. %@+ >% ƨj@(`n`p96%dvr~+O]W=C&CDe0@&%*K3(ᆫ p]@B=7! p!,>נ0@*F#@c ,3BC?$&QKP?GWڅR@(q~+ ļ@eAHAE3`xEJpLZE b/ DZr|@ [1Qd'Dͫ乆%<['/ z,3θC3`̍[ wh)O&a]Ǵ`0dXK P8&ř˓$g97 o !L!|0 1P1 F|8JJ0 j ١*3gx 3pyU z*:@T\Ly4gMmzSȡC'gPQ,<.20Ҍ`; 1C0> 7$E* 8 P V9;]hvS`[^S&o  8qzX&V:ôus 陗I(PoƦ%- g4Ŵc0`@.21Pe·NXVqbl*$LgXQSV5Mc%>":t<4t&=ʰnwۧ =.y~;^<97XӲ|4-feYAVp'D'̐c:S&L~WIwLE`poSB -6OHqA\X(fˌf4bD!Dm|1Vq7:G|d$'YKfr,sSr|e,gYjlDe0Yc&sGeش %rbf8YssbzC !jBIYЃ&t|XGx8v@p9ѼKm\XгumD Y|t Sh#݄,L J>@qG1 e3V0D q|EP5H  :cp@ [[Wr ][aPĮЋ^Ei8[ !@b4د>4 C(@m YH G9,Pȡ#$07D;yxG1`P" 6+&Sg8Сh%JPF #pCBdA0Ee8JY(@>{~eY8VdA h@.Y"ūi믠> Xuu{9R`*]gyL~+`ȈWB;½J9B&_g~'Z=Qf8g_7&̾h!W(P+t/c(Ƙa"x]EhŦ/KK)BoXI;@ hKvx%h%@ۃ&(Mx4481Ђqhc$!hCq"P(A 'Ȅ< \B&lq@д=eP;#4,B+21 `a@ 'lC7TsЁ7C:CAB;C=C%+)C@ DA?DC@<2B=*(@7;@(EC8JD5GMQL>URLg9I(^ͺװc˞M۸sͻ߯'i*M+_μН /Nسkν//}r#W|>t'g?J'n27Ɂ} H E8ņ܂:xہw j!ȡt#j5x6!Xt'.y;cp&p`Vw8Xls"0$*ہ6lxa4~$g $ws(GJ:„_8 @$ʛ!m(fiiE,&"r*In)%c!B`AobL+l@B&O@ PRŪ: fЯ#s(-?!!kV4 <:<+\(Mrˀ$C2$Y v`!1h`x#X6if%yatۢDoe}Z/$Rġ9яF`< H8d X'V$q5K(<Ɂ,n}0A> ՜SER&m`L) & A^ zDF+1ӼU~4^lK*StdëQMV ` 剆uV q$Qm 5#PX!W0ƺLMTΒVI"UqEM9]5pJ~8l-`l倎y"53;2l}Kz=Ldn7^M:W{[*PXvMz 0F~[M8Z4! N Gtl I;gSIn|^|7ͱ;9Kюv I74wN[XϺַ{}(DzB9vh7**q|X01vC0z;q bdEaWpc@*02y[sg_y]yї)9EqmxAw  gOwcH@a+q?|0 .}L#>X ?F~a0b gm_;P9AT Y.~#({dg A`@pG` e׀x? pbWP yr E` E``tx@~D7~'P~XBv0` h7 p _70 ? 3 } I0:0 =7PS t0lxޗp Q@tP qx`] H `q@\`wEp pp0 qZh ?w)Ht`_P 0`0@ 70p B a8`3@5@ p0P  ʰtP!| O怊 ] |y0 İ@ `P ŀ@ h + @  P 7|ՌFyg2CP  . 8 .  R0x7@ zp0` t v GH xQP}|G\,y M3 ``Χ NDY/ t3pJ50 :@ .b9!a`@RЀ.Ȕ&487I ·Mpwy@ 0xMp70VXZȅo9  7/ bY09` t `?0/`JhwP =9 {tP Q{G(޹ 7 ɞE0Gՙ٤NʟAh PVz0 Y (q.` : .`:P ɰ Hr p # 1xw' M`wְӠ P`E0 Q@ iSXN:QZ 7 ` p 305@70/mG:.z0xڦxp 5 e  .S × Y1vN%W'E`KPE lE w  :ؠ۲~ZHi@9Pۀ ؕJ@wfjvfw〖(; a0*S}wHwWpx7 0 !6{X` h/p S@4̺  wg)"kc(k%UuI` qviBZ+FkVu!gJ$$ tB0}pL62u!Y+ic@QE: # u rA$407DVtҴ5UP^/3{ %{)kP"$Ng,H^bT;20t m-' rb<)`s &@{G+ E;$08f$<C*%3u9 `/<z V,!‡t2p{=<fU& 2pEOX`=VB,< AN5s+7(%D\Ċ{@ %v@OI p%!vAp=K2# b[0*PºNbQ3,3PpjhtFeǯ9`%{$O s`0EWtC@`"8ҒR p03,͔ Rt5XeX ˱̼XB p't`p Jz xuIH+Txr@pQnIo8ўdsy,aQ``IG(-4v;<@`;a7$E& F *|> P0h7BpC nxeH Jp?ꈐ(fW _B  A +``'A`}g0@}PAТP p@ "`!i'Ŧ+u+L"@DLp ``PP%`> 0p" 3`P j B Pp =@ ͐   tjPe Px 0>>~C05P ` z-` bgtZ ˉ_I z9p}1g < @ ^  ڳƷp.$'A1](~ K? wJq@ -  7, 0 :hPJ7 h7 ?1ǔ"@K}K ݎؚPdm.԰.ϸuy79eĸLwCۖ8rEdG⻃(ҋwN"wLCl pK1"f4 b59# N+8INZUYnWaŎ%[٫49e[qΥ[]yԛT9n%\aĉ/Vcȑ%O\ٮ`l;gСE&رeԩUfmskKϦ]§a۷k,uqɕ/gsѥO^uٵo|o%ˆVy՗o֌{jǗ_<|Gߌ+Q$1@TpAtA#pB +B 3p5oDK4D׃R\ϽhsqFkDo[teqDMGI4H$TrI&tI(rJ*J, rHmK0]\/K F5i1>JtEG9N]p5O@t#PDsQ&I\ԓ4N9#4\@N=oTRI$6CUSW-uDW_U5`5nU?] =H}t „hΜ ^M3ӌ1Y40ITFD4 (FJx<9\%>r Ya^|whx[8hV$ '*j`G,(Gѣ ( %p $7RpG߸9R@PceJpSNu!ys;0\MV0fFYQFi ʁ>I@#XفPa;XTw el5Ͻfh@Ut5heh(@pM$ C9b+wJ0[P$Dg#hY DVà#3 O=p&Qx8 /|v0젆lz*lPUY #HeGPZtX+`xE,5b`t,|*P v@Ma @`3Ԡ G@Fd$#%-HˣCA3lSF>4H-\8qxJTR`X {]E4@X@tDJG4Âdf/pj0 00JxЇN"p07USDe+]T0sp*Dd xh`4!(OXIl, P6ɖ8y1X 'HP^M2p@ }p'\N9v_}>bɦ/ w#N@2%#i@y+*'%+H3f!'vD10z ']Ktlo!B -4ۭyA@.r\H@n,aN7h^r\   z0f`3]'|zh;Z1! cX<^AX0^1)[~ hJG] K8FAcw~2 <) iX<` V#c @<d8*6x8#x7<3WH5l6{{0*oȉI;@ A`?p{w%p%8A'0N4@1؂qpd :"pc<\h(`*J(U%rM@=A,B- Tc[e`>ƓPk?<2A=*%A9CC+HD7GMSL=KMXSF*TW9ZYb[Jb]SfaThaMeb[jcSXfZkf[pfRni[mjdrjVGlmsl\snbvpczsc]tnyukyf{zsl{o{kY}}sPPqazAsK|/_Su|y"B|-bbc|V}@YJK6bn~'a c7MEͤ'GtWdf1Vѭ~ YqͮjGoU时ºͬ6y߷ȿvûOĸܛĹijĭŰoȺȷɠʉʾ˹лP°͹xξμλcìåzԺs֛pĈ˚ۼ͍k̶Ϗԩԛռ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˕۷pʝKݻx˷߿ lᢗ.aZ̸ǐ#KL˘3k̹Ϡ!'>L'9I(^ͺװc˞M۸sͻ߯']*M+_μН /Nسkν//}Kr#W|>t'g?J'n27Ɂ}Ɵt!` v~on]>MXM" A|AHw!R""l;Vr]tjf# $o2w8Xlr$!$*$5`ԱtQa3}$W #wr8G2DOBIBi$_4YVhXJcfJI7$;`ƇZj8$ *\x먵)6'Y;$Z#nמ),*|-Zj.EH d$x"#,ЮtQoI"B lO@$W̻ /#&ē&`#\q񒀡g$5A5LovBAyHƼ$r"x '"̨ygЩ`仔t< (c"v$K 2$m`AcLȁ5|As{ 4 OlJB]xM\p?lc *0»iklPĽB* !{w(I@HMtrEHm$,_AKNi /č"F^ &xBVu(!A(!710 $?ٯp`#?m*[",7fq.S6p/JGǫ7 mm@<`7@N2~P4AR<'Oe@&AU"}x:PD-Jpsށц+tԧ#xB# :j=Pxcp!06OxD" V6i d" Z  ,Ё/ "RFIhځ^eCISA `MGmХg݊xƫSĠ5f1@3 Mz46鈍cR1ѩJ#ʍKnU bӞ'PծB $~JLAҥniF86JHn NJ3F>dE;6Aܫ<e63}K 6ֆ^QV.~!Bl| BXNfeӑ* kO?;\ #ئ!4`jD0̈tW P &,RD]3x,0Z52/dfAP_^o vuB(qUqO@vK5۽PI~TzX DBµN@m0m20ͦ/$Gp5 tݖHQp'0.{7I@D\#~F=i6r.řQ c˻卹wZmC0HZv[FvU5 _͔$f+U^je[):"!([S9^;-m-|sTY4&Ĥ)ؙHۭV5gi)@Ċ Xg-5Kl!^PѡgcaSP(5V"3_it1[V:ˬW3b>ʶNkYԇ#zhRȎo 9ٴ/%lh[V]jgw}~noINDrc뎷սmw$-AA~]o{7:~0l%U63אw=r\!'bxyn9uA=@ЇNHOz/A;Zs"1;nYP0! `c G<svqģ؆>P 9Sۦ('=x7Ovݢv[ F-Taw qqG= $@?c\q~ b g>s}D(N12t KP H? `MGP xp Dp 0Ps@w,xi0؂ǂ|W[@}q x qn7D"O 2 ` >`APP^`^PA P=  ـ=PW2=`40-GmuxQ|/\ l [`Q  p  [Q@ aׁo`0 !Ek%7sP^@  P P 6 ` A Q7P204P ` @  `s@Pz ;wr xvx Ġ0 `P @հ~0 X  @ qzuٷ.׋(bB` -` (` -` R0ڈh6P y` Pr@u&@w 8 (wpv[x LɁPM, q'. s2`J4 ` 900 -J9pIP0R-`G$k jl|'L`vpհx0 {L`#䰒Aؒ90ɘW9  6. ٙ4HHi -Ǎ[a0u0ڈB zP Q`zgmn' iD 睲uy8*f~f @@yЙj X\-ڍـ -P9@ Ƞ 8q `  vvgp LPkwvՠҀ @PD Q@ uw>9کib`` 2 46 .X7*-y bztw` 4d -S X0@u0N8{}'Dp6 @D jDv  :נڂ} 08p XJ0uPuPuĊۦ !0sS0xz|v3vt 0svl˗0 !bq|qP0`9wP60  fh h+@r+t;T Еo ' X4 e6hi']E^*"+s*V[!2rA%|L!!BgQEHg{ !3Pk): # u L+L"A:bLFLYC "03{ "{{? h0ITR<a| SN&۲d& RR<(@r$+[[ r`|0@7/#5P? FƄeQ/#\U"17:bAcXzp6'?ֳ@pTmbS,pbC2/Fy]:w[/24!p @ a QZA@%tY12&Puu+$gE`^`0[c<%`w`[ Pz6|$qOQ"1@ DSd3d-KL !D&ZKYWUĝ <[r p` 7yg]9[< hLp@pI|,znA }(΢#O$r.@be+vb1hZD_Le0 0@ +p n0pl6 `I6sΠ6lPy}u=0P: pPPд` `e3 ? PP P@ !@q C:Ycdk `` `</p 2Pp `Z A0 @`ՠ =0 mG rqhPb P; ?-tt*_@F)M @ @ p-m \=<$]p]bڧPp%`q  rp P  :q6΍i XS``4)  P ^`pD: 7Gn3-pa@ک,-< {вX`fyPЪlJp8^ 2@fV*-fzmO,  p  pn1N@F MPנopѹwpa9 Џ 6wW90@ g+ -pWfkW70upPR_ރ kNL;@ mP0 ^(ϋ ~y'p 4` ĀytP0 ]x෦0f %=?X }/m@ NM J ` {&_P]qw)1@0m0/o _s+@ >P~20Ðj`[s000u jhѯ ``t} 0Nإ`= hMzW `9,@ ۠O 0ZP 3gNyڴPܵġsX!1f^XÌ9ZuMŊCY$J1eΤYM9uOA%ZԨIZ.eSQNZUY[z2\9N_%[YiծU[qΥ[j`uQl:_&֭]ĉ/floc0 O\e!oٳcUDP{ϧ_}pK.:SpAt*:B뤃; 3pCCZnP8LNĥ22:ȒeQHtR*RI/TAM78F%;S,/:=[ͳ h TkxP''#ITx&'3 xCJhň L]]w\r5\tgᅖeelF]Ve7`v)a`kg>TCoo ,6]K6dSи%, h@ d@`>1͈-0"ڀ>" '`a Ocf ` y zf6` b`4.NdL8>hW|q7r e&:Hf0F yvT LGk A `U9)IRT@`s O^.` ĈX(!Sdw}gfյ~Z~&C,#B^ @)" JO$`@bzm @) x0~= XrXbrBp_r>^OC$b4 BUxA=:% g,`@vohHT#T "Xz(R:/HP09(t"§Q V$Pҷ>Qd%IJ#~չƬչ ;Ub'Q/ z3Ĉ2D Uw8 N&+^a /\W$'AwÑiAyC;| ;q4Rz)H+Mm}k\:1~ > +X F< Y || ⠇!cXn>`,d,Y(@VAj @B  u /Bw^wV,k*h1>c(c^8a1\N@6,6KHrK 5L+rTCAQ w}sC\+v;a,B#݊7ǸƟt4z At# yB |!& EA/"z~w- =+&v" b8wy@=&3%L%Z=\%bFpɡ2<g}땬wȃ {8`cHNc7By/X#'~ G2=pe18cm.%<];hPY;q> @ vP>hXX'X 4=p"I;-@Lp{"H('<ԋ \B&l N;Se3:K?<2A=*%A9CC+HD7GMSL=KMXSF*TW9ZYb[Jb]SfaThaMeb[jcTXfZkf[pfRni[mjdrjVGlmsl\snbvpczsc]tnyukyf{zsl{o{kY}}sPPqazAsK|/_S|uy"B|-bbc|V}@YJK6bn~'a c7MEͤ'GtWdf1Vѭ~ YqͮjGoU时ºͬ6ľy߷ȿvµûOĸܛĹijĭŰoȺȷɠʉʾ˹лP°͹xξμλcìåzԺs֛pĈ˚ۼ͍k̶Ϗԩԛռ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˵۷pʝKݻx˷߿ lᢘ0eZ̸ǐ#KL˘3k̹Ϡ!'>LgI*^ͺװc˞M۸sͻ߯)a*M'+_μН /Nسkν//}r#W|>t'g?J'n2GɁ} X E8ņ܂:xہw j!w (zDam%F!݉`#Vr]t񣋔d%$d@BFw8\Xlr%%!$*$%5`FԱtaa3}$W #wr$GI:DPFIFi%_4YVъhXNcfZI8"jUF$̪)`x먤i;6'xK+,6$%edr{*[kZj.E>X d%x"#,ЮtQoM"B lO$W̻ /"&Ĕ&`#\qx@BHOLRC dP%f!q dK .*rB*B&lw F[Ip3H6!Blo!"!Lib -Pf|H%DJ D L<~;6qD H~ zPp4!H[X b%>MԒp`[%P`&Jte"w G 0B"= Hj)%n`܃0 JJt˔ XU8D,`8d_j ꘶ne<)bRquϼǯ'8d 7>I!82+);-VHJ?i  8j?TN nIJF:l2SO8& ?w @h)U3 qLph$@9 (y؛8Joؐ2z ! )L{#+m P%™. Bn iok<ۃDP]]x1 L]?`!k Hg+!cFL_$ P˛I2Z-r2X]3x-ж52/d@APaf zB O>/Z% 2T_h®I󷱺W*Z F`*j:E *m N H[ dp3ЁRbykZ4#;pDCJ@l$5^/CpE h!k&DW4-/kM i5s  ^7JiDJX2]I^@o?8Z%+J/DZ:RXQj$PJ85"*Yy.B XjŪʹyt=Mu Pl8L~!QT$:QmMg0 HOҗ;Pԟr<asc9û@5qj#a=#(@N[$E7p Xq8r 1w|%r7E|5yrA؆-Vaw q qG= $@?c\q~ b p>q}L0P12t@VǟX ? pVWP xPqD 9`sw4xr8XG`}g[} x m䷄LX "X 2 ` >`APP^`^PA P= =PX2=`406WmvxQ0}8\0 u [`Qp ( [QP jW0p`0 M%7sP^@  P ` 6 p A Q7P204` ` `  sPP{0 Dw܇swx@ Š@ `` װ~@ x  P  0 zw{76y2RXBp -0 (p - p R0h6` y` 8P`suH xQ|p~x0$& | QD8I :"0  .l@PP)!{( . s (-f< @:@ !0ɧw)| \v`p @W Lv Q359O(!İ l`P I@8P`s P>0.PJ\wp = )`z G|IvLP 6xw԰I `}L }[>.2P8f @Hy@r X(e-Zې -P9` ʰ '8q @q΀w\ q| /@w`\p @ @ DP @ waHj)!p 6 p 2@8P h20v 2.0J_ʇ-p@J:p{ʀ-]Wt L`x|QL@wsD@ˀI`@ <S -W!s 0ЀM eZ׀耥e7Xy uڍʠv* @a 0wssrwuy@ +wtWw|F;} P(! )wXxB"@`9wP70Q ѫ@q Ҡ:%r"w+%Y۷BX 8P1p ' aT$U+Djrf^"mr4?*~9IsA+|@L6rt!W+hrb?PAJb01%@$307|$Udϴ5|Pȋ3{ #Ļyk)+P!Me,ǣH]_0F;10d m-&0 Rr<(@r $HKG; E9/ 5p?d4s-]p]کP%`q@  lsp  :qP6Ѝi X0[``49w 0 ` `` J(3^ ? t0oh5}QWp&  ĕ)0 4;Rf`a PgX nnPh߷*` @0@unN@F MPpqNѾxpa= P ?W90P+ 6)n^`N.{jz - \p_0 lNU:@5: pq n+^! ~y7p 4p znuXj0 ͛7@f "o=BX } ?mP ص` | o;W@&.1P0m0/p s +P u=~20ĐjhsԠ0u p!@K|[ ~ט@ cmm ƞ W.ޯu w u@ZXM;4UN7)D9R.BuU#5A @47H:PLt x&yR[Ι2D.T *o8+ >8i@(gH`J'.7F|Wq+Yoh0:D&eV¹` 9mxG.h^ꀆwl ^J7d i04@^1>Va}5BwX^8O*8 2  E\kp0O,!<-qH -QliPa4U hOp@dd#6 H悟s*C]8EJ ?X^ ." `F]GJ3Jd@.C H'ԉ| d%VC^p]$yMlQZ T 90`"c B_(Q\f1l0Ɉ.@0ECsN- P#4?R`u@-)6L K<Ș"9MTfN ہcH'Zt]peAw"1)p *sF2Q~ t@/TЃ H@f DQ` z!]eҕU{=UK0feC[t+=na]01@*8qe0K;DZыOX"xq+PP:)_]ZJȯ?ГZ9T1q; GW@SRt0J`.]S %5ӥnu#iJ:ɭ\9=[,_thm{'Bi -I׺ou1ؑMX6d_^TY^ f`V &K .n:|a xM\b:8JxJ1*XǍovʈC@&r|d$'YKF9~d(GYSr|e83re0ỶѲeAvsf8-e = x%g@ZnsZށzCGvp¢zct;hy,ә& b he3{.G93hXZֳLт, V8>a*8vB`%h88qVű+" YpEI PeX"p@ Enu}o|VE u2ځ P8!̨Ʋ0|B > N0lbvqF-"Ў(Pf8A o\TpvY0(@F87!.q'[8%0& 6J"@_E^s]TTNCpEp3!XO\KFI zc zH^ T XCeHMzQbwq" ;L%$4 _B%**y}I|{}ePy^/dz8 ̐G,d,!2 dP@F}"TE|@l{v(hXX'X =p"F;-vH!( t!쿇Y'J0UpxbLP @$LB%@=f`ӻ :4*|B2/,pb0.3C%LC5sЁ5|C8AcB9C;%+'C>C?,2=CADB,DC?<2A=*%A9CC+HD7GMSL=KMXSF*TW9ZYb[Jb]SfaThaMeb[jcSXfZkf[pfRni[mjdrjVGlmsl\snbvpczsc]tnyukyf{zsl{o{kY}}sPPqazAsK|/_Su|y"B|-bbc|V}@YJK6bn~'a c7MEͤ'GtWdf1Vѭ~ YqͮjGoU时ºͬ6ľy߷ȿvµûOĸܛĹijĭŰoȺȷɠʉʾ˹лP°͹xξμλcìåzԺs֛pĈ˚ۼ͍k̶Ϗԩԛռ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]՜۷pʝKݻx˷߿ lᢘ0eZ̸ǐ#KL˘3k̹Ϡ!'>LI*^ͺװc˞M۸sͻ߯)a*M'+_μН /Nسkν//}Ks#W|>t'g?J'n2GɁ} X E8ņ܂:xہw j!ȡt#j5xFXt'.ZuA:cp$d@Vw8Xlr!$*ہ5`ІԱtaa3}$W #wr(GJ:D_H ?$ʛ|ĆWfiiF,&"ar:Ini%c;`%V%t0#OX@hd!+DERi" JRRFhjZR郕A@P` @FAIv$"Ā?DENrE|A"b›HL `*8R$dhd$5A5PˆovBAy>HF$r "x g"ܨjzgѩpdt@SR(`M $l'",yb&XLdcAk(xCmB%|< ぽPFBB\> E&oZe%@. }m{maN`A]l%\RG} '{# :IΓ~dTRWkZH.=` m4.zS6oP8C(!TBoP b`@~ε.$S{*-?!k4QU'< dc`DA݊$f`J7IVSOiadQRuC4$` } 6eVkǸ%Nb.15==I/!WzM A–i)mjUTI TO~GXX:/IX,ywn=Ⱥui˔z2UaPIch@&I`yɳQU yLj>{UHQij٫77_mW<:. Bp i֏mTۃDP] ^x1 $]?p!k P+!dNl_$# 뛬Q4z-N"!3DY ^3-@ ]52/dAPaj zB$o*qmUO@x5՜U`Q)zXJ TH@V MfTpJuBjd㈛3ӚQЁ#.R}g6z 4E H#Fwx3"an{7QWoaퟄhZ I omH.fcQL#”]%?hjE\):)!*A!W@o~۸DúՎ:נT0Y6>WPQ=JF+ \Hc]KVn y \PnMegI%茚Қ ;QTH߲pLZauʚD_5ve"irjzH9Оob[jF6'n{9-mp~}r,[η]o%0H2[OO"qPMOIs ( |=Un%/^t$hut|H/>'.Oҗ;PԧuL=CXGd:> |P#H;!yE1_"8,`c 0B+wYxO^!|,y;6l{ N;^';!Xx] A8>N|cS<1E\\'cD9'O~0\E@=VA,`A=tc?}n$`@eW`Z7> WgP xPqD 9psw6s:xg p}w[} x %ׄN#3%Y 2 ` >`AP`^`^`A P=  =Ph2=`406gmvxQ@}8'\0 v [`Q p ( [QP kw0p0 O8XQ%7s`^@  ` ` 6  A a7P204` p `  sP!`{0 D݇swx@ Š@ `` װ~@ x  P  0 {{W8gr*Bp -0 (p -0p R0x6` yp X``su6H x Q|q~xP&( 0| ad:H<"0  .l@`RI1{( 0. s (-f> @;@ A 9Pʧy9| \v`p `W LvЂ a579"İ l``@I`8 (P`s `>P.PJ]p =@)pz W|ixLP 8wНI p}L0}[ٞ@)!g 4-p8  -Iۀq@pTivS @ap + zR ( w w LpuvԐ @pD@ QP wH!AZ89Dz 6 ؐ 2@8P h20 v 2.@J`-p@J:ڀ{ʀ-^gtwYxLpx|Q0L@wsD@ːI`@ <S -g!s @O f[鐥fGZy vʰw* Pa 0 Їtssww@ -wugw|FK} P(n(yXk.e f.pp Soѫ@q p;%yr+(YjYgIz viFR], `Vu!6gK$Ʒ$Is,|PL6t!Y+ibAP2'B0^/K ;M2uMRA]LFM]W%B\?sRB۽Z˻B?0 hIT<e| L&2 O`.e-ȃ$ OB+۽ !|d|p^C1R`Fă+0dR3\u" 17bEXr{!q?'?ٳ@TmbW,p@c Dr/PF+a#:zr\3\6̷8,! P  Qda%quA]143*  uE36Ng\g|á%w`b PW{:,Qh~LrArp0QD /pEF:4 d#-%Sտ\ ! E&0[|YPġ,Uegs营 pʀ ;z0wgIF\qIoQn A y\ry,ba_`I>'-+V[:x[g ^A 1  .O QP@h0 `e3 ? !Z]@ !pAh'Ĩ+u+L!04ƣp0`y p+P 0(1  P ( pz@ 4 p s 8 L 6W hPg P; ?z-x`u*z_] P @P p-]֌=<@-]p]rڨ Q%`q@  lsp  :qp6ύy X0]p`4)gh0€{h@Q Mעd: @gMN6-pa@ڭ,p-@|H|@@X`fy`@lJ8n 2@f_J-G{O,  @ nP* |wʑpa< p ?wg90`+ 6In^`M>{zz - ]`_~0 kNV;@} mP@ ζ$oj!<@w  <<~o@pP Wgj ܾɍQ~t z8`p},e k; ? 0]`*@] Q {_P]q7%_r1@0m0/p ϶s +P t=~2@ĐjgsԠ0u nhA P Pv 0N>ئP] kM{>i?l ~ uܠ @倡/P+С#7n-$-A/rNdXYą 0"E{eHq"LNDK1eΤYM9uOA%JI.eSQNZՕ@ӖEŎ%[Yi[qΥEtU_eKaĉջ%O\laǙ5o/Es͡3'j%ԩUfkرeϦ]mܹu53DBqɕ/g~ܙjѫ5_>uҵc]3ٓW&S"'g{ϧ_}$;TpAln:iB 3T\:^PL0ɤ'AqE[tEcqFkFsqG{DpH"B㊬.eW|qƉLBe1ayQT1řfvp%'L`ps>!C>3O/jTE:g``US4\h( @L"1b%#,7dJqw0Xq_֦I:!f$`_2+U]0ÜQ6< D QH u@C8<|xO6h|aCl4A@KYK@ԧ+QC$"䗡U$!/P81f7x d02!/(F8EB)ReИxxEPRe@N! MRx_ )0: X%x!fK]ґSB'g@1F-:P.2"=p9 9#(@{:zR(C$ 3 lt-d@Mfko.`ekZ)LWJ*X-v; 7 Vh UZXr6ҧV,@((o4mm/4X"JmQfJw=:щE[h%]D7)Rtj[fW\H^u[4n42+OUְX6šXȡi]ŗ]XH"/ !k ǎ'qWb H^I1T8xBia x@r(@3& w}B+;q,B# /dxƝ=t0z 1| yR |% DA/"z~, *'1w" b8y@1~%TC%ZE=]$bE;Do͡28g}듬w̃ 8bdGNܡ_?By/WCz'~ ?r=pf#u2KH2 mx fs*"ȼh[&ZoxJ#@ @?pcw%p%@'(M381rpdHLAq{"P('<ԓ@ lB'|B N;cf3J2s> DAD%CB?<2A=*%A9CC+HD7GMSL=KMXSF*TW9ZYb[Jb]SfaThaMeb[jcSXfZkf[pfRni[mjdrjVGlmsl\snbvpczsc]tnyukyf{zsl{o{kY}}sPPqazAsK|/_Su|y"B|-bbc|V}@YJK6bn~'a c7MEͤ'GtWdf1Vѭ~ YqͮjGoU时ºͬ6ľy߷ȿvµûOĸܛĹijĭŰoȺȷɠʉʾ˹лP°͹xξμλcìåzԺs֛pĈ˚ۼ͍k̶Ϗԩԛռ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˵۷pʝKݻx˷߿ lᢙ2iZ̸ǐ#KL˘3k̹Ϡ!'>Lg9J,^ͺװc˞M۸sͻ߯+e*Mg+_μН /Nسkν//}r#W|>t'g?J'n2WɁ}Ɵt!` v~on]>MXU2G AQHw!Z""l;fr^xjf# $o2w8Xlsd%! %*c%5`رxQ3~$W #ws8G>DOBIBBi_%`8YViXRcfjI7j%;`ƇZjX % j\x먵):'Y;k%Z#nמ),*|-Zj.Eh dD%x"#,xQQ"B lP@$%X̻ o"&ĕA&`#\qx@HPPRC dPC%f!q eKB .*rB*Bw FkIp3I::!BjRڸa"!@HU d@!lυXCtPw&Ph`IMx $EDĶ:Ơi`` #&xi5H+BbD]!:R`^lF%`AbG~ # JI,eXRlUgZD.=` n8q#.i6 P6C*!XbpPM b`@~ŧ~TE$X p\0m^& g Inܐxp6qx O3H*3U t /N[1= X255"OG,G*tQՒTC"hal$rD@m s#NW DdAX`XФ`Le[=&`#T ;" mܸV,6P>yU%"a\&Y_;7Ɇ$]**1J?A)܁0pYiT %1Y $%XY`oӨ,QicC N=+$/(h&43EY[y+@U`ge7$L'ʄdzHU (AAnPXPs05"0fZ qm(M֜B}RI zPUvp"xn.``2F iA0 }@!@diiYڶ*@RC'~m f:ޢ^NhnT?a ^=,`"!ZMy 76QePR# L n:J oMsFUc]^@XdXRG͛f@ |z"e.y#49d`ݥb͆ \eݼ}M hs$滲mud#uWf U++ W5jn-q64 9l^cbRQdsjlGVJ%AH(hk,<- "rl6<гC~2Ji,DM '.gMkZ{yk^qi~-4:q^ }Jc9ٱ"j[6=}n{ɶ+mp讏M-n,[w]o%0H2[OxG"qЧͶ$qJ8 -ranN-w ryocŅ?HOҗ;Pz3QȺ;jsb9;nZP0A ac GP 9Ungy]>yƯH|!)W -Xaw q  qG= $@?]q~ o>t}L0GR13t V_lM` ? >`X2>`4@5WnpvyR0} 7]@ t' \aRq 8 \R` iW0p`0 Ml"GtP_@  P p 60p B0 Q7`2@4p ` `  sPP{@ Cwwsvy@ ƠP ap P x  `  @ yw{76yW'C  -@ 8 -  S0h6p z`08PPsu&@ 8((8ʇv\yM#I``§M4;Y. t2`K40 9@P -R97APQP@S-pǓ$srt|§Mpw0yP $H|Mp+0IX8I_Y @ 6. Y4PP 5Gcbu@C0 w{p Rzuy0`vG E0g@zf~g @HzPr Y (d- Z۠ -P 9`  78r0@q΀v] p| 00wp]p @ @ E` P  waH ! 6 ؀ 2@8` h20v 2.0K_ʇ-@ZJp{ʐ-\Wtv9xMPx|R MPxsEPˀYp@ <€T -W !t 0ЀM dY׀耥d7X uڍʠv* @q @wrsqwvy@ +wsGw|F;} P(G(wX;oU g.p Toѫ@q `;fF 6W"YZX eIzqviA@Zh+6"Ve-R,9h|3Rô-+)I%"X$Fbb?P 5R0`^/*@$307}$#tʹ5 %\=-ɻ?[P!Mf,ȣH^`@F:10t m-Pf.f-ȃ$0PKH y~=0K $Q^C1:RPFf0R1s\e#,{#04 ̻%s21p=;eL&@ 1`EPXP2FA,[ @d5l 7(e8à` %!v@C<  {\U'EJ1C `O0*pv epQB@wFPj6dF:,X 8`%!{QiL"S b EVte-"P!E&[՛Y\Ĥ\ cWs瀥 pʀ > z0ge9Dx\q@pI<  }{n0(΢#O$r.bf+b1`i]D!`Ἳl@ 0 +p o0p|)60J6`t@а6m8u> 0P; @ m @PPG`=}P mnPm@ !1 c:Zdpkl `` `</p 2`ې j0 BP @` @ >@ njĠPs |@6 "pG!PTN!ж@ P` b uA>$^]ګP %`r@  \sp 0:r`6ҝi Y0[`` 4 i0 @ ߀ b` J(3n @sPph ⪝QXp-(   08|@ Ypg zP@mKp<~ 2g^:-}{O,  p ~P* Nzpb?- P0 >W9@P+ 5)n_pP.{jz - [ѐ`^@ nNT;@ ?nPP ζ.(O z7p 04 z^uXj0 ݛ7@g  % =Bh ~ ?n` 0ضp } o[q'n0 pwl@0)p '+P 9 gp=G [W ? 0!@K}k ɞי@ d} ɾ q ~~ qu@ZX,vP+Νn7n--qNdhYą 8"E}eHq"LNTK1eΤYM9uOA%JRI.eSQNZՕ`ӖEŎ%[Yi[qΥe\tU_eKaĉջ%O\laǙ5o/r˝+7R%ԩUfkرeϦ]mܹu53uҵc]3ٓW&s")g{ϧ_}$;TpAln:iB 3T<]:%^PœL2Ѥ)AqE[tEcqFkFsqG{DpH"B㊬.eW|qƉLBe3ayYV9řfvp%(L` ps>"c>3O/jTE:g`Us4\h( @ӗL" 9c-#,7dKqw0Xq_֦I;!f$`4+Y]8Üa 7<  QH vHC8$a/P81f7x d@:E! 00F8B)ReИxxE`Rf@N1 MRx` )@ ; %x!fK]ґSB'g@1-:PS/2"=p9 9#0@{:zR(C$ 3 l x-d@Mfko.`ekZ)LWJ*X-v; G Vh UZXr6ҷ W,`((o4mm/4X"JmQfJw=:щE[h]D7)Rtj[fW\H^u[4n42+OUְX6šXȡi]ŗ]XH"/ 1k# ǖE'W H^1V8BiQ x`s(@3& w}B+v;ށ -"Ђ# /dxƝ-t0 1| b %(DA0"z~, *B'!vB c@wy@1~m&TC%Z=]$bE;Doˡ38g}듬wȣ 8ddGN<ڡ_GBy3Wcz'~ ?2=fCu2 HFdal6%:m+`PZq> @ vP>hY`'` 4:>x#؄HC-#@#Mq{"X('<ԋ \B&l N;cf3J?<2A<*%A9DC+HD6GMKLXSF*TW9ZYb[Jb]SfaThaMeb[jcTXfZkf[pfRniZmjdrjVGlmsl\snbvpbzsc]tnyukyf|zrm{p{kX}}sPPqazAs1K|_!S|u,yB|bb*c|V}@YJK6bn~'` c7MEͤ'GtWdf0Vѭ~ YqͮjGoU时ºͬ6y߷ȿvûOĸܛĹijĭŰoȺȷɠʉʾ˹лPǰ͹xξμλcñìڥzԺs֛pĈ˚ۼ͍k̶Ϗԩԛջ۵ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˕۷pʝKݻx˷߿ lᢗ.aZ̸ǐ#KL˘3k̹Ϡ!'>L'9I(^ͺװc˞M۸sͻ߯']*M+_μН /Nسkν//}Kr#W|>t'g?J'n27Ɂ} H E8ņ܂:xہw j!w (zDam%6!݉`#Vr]t񣋓d$$d@BFw8\Xlr$! $*$6`FԱtaa3}$g #wr$GI2DPFIFi$_8YVъhXJcfJI8"jU6$̪)`x먤i;:'xK+,6$edr{*[kZj.E>H d$x"#,ЮtQoI"B lP$W̻ /#&ē&`#\q񒐡g$6A6LovBAy>HƼ$r"x '"hfzgЩ`仔t< ("*6 2($m`AcLȁ6|As{ 4 PlHJB]xN\p?h` *0»ikl`ĽB* !{>(I@HNtrEHm$,_A;~N /SˤF^ fB@u(!A(!710 $?ٯp`#?mS,7"q.S6p/Aǫ…7 lmH<`7@O~P8ARK'Oe@&AUBjx:PD-Jpsށц+tB xB# :C!rcSL H$20X3 n.TH,@ t )\s('ѕ.S<4t`WPuT>FX{Px25cںWA1kb8d:pg |Q{פ P[2V('B vd@ss?I@rG*P'3PK]%F)(ӄ;p ,88 A g< |%`vlHWÿ́Ԫmƭ HM›.F XƲ=H5 (lXPs"(fUK Uܽ^Ȣ*%A/&MK5wѲ k!,`+` "0`9wP60z p qЀ;%R!}% WX8o ' \T$U+Dirbu^lov4?*|3rA(| L6"t!U+hBb=P=*B01%@$2 |$Ut͔5x0 /3{ !ޛyk)O!Me,ŃH]_F;10T m-& RR<(@r $`H{KG+ E7/ 6P? Fs+,$R/c\U"17bAX{p s?֣@TmbS,pcC/F|]#:w2\3\6̷8,!` 0 Q Q^A%uAY12* uE/u`^6`TplgliPw`ap Pz:|$aPѸ"CM4 /0EGP:$ d-!C!D&ZxYLġ|Y_q(u1WT װÛ~@KЀ,' @   ( O$s.pbe+b1f]@`0 0 +p n0p\4 ɐJ4080 K@> DЇXu}  .P ` p @` = @P`GP =|@ @P P@ !qhĥs+e+L!05ጰp0`y p+@ 0)  0 `z 5 ` ° g@sahPbc P: ? -tu* _@G-= @ 0 -m O4 3H% 5p]` 1B.9@l0X`Π kZcy 4]=q< {h@Q -0 &I(#N =|0oph5}aWp)~  * ďـ0 2;Mf`a AbX nnp h@߲*@ @ @@ ~P*P VԾMʉpa= ` :W90@ + 1ـ`Zfk w7pu`ϐ_ pNP:@1* u l[վq ~y'p 5P ðyuT*0 m@I9~o y7``!eP k:P ?@ 0]@ٳ@ z oɛ 7,P` Vl{0) '+ 9f; Ҁ0pu nh! y}  0 nؤ= m {:X X P j0 ېpS /A̕kO;yhWgD)dKp@ 4@TpAtA#g= 3pC;УOtPB32OR&r;4 ݐ )!;Hռy32:XeSoTRmTTMe/R5dTW_]/CYgVAo5]Q`EⓣHN/WJ~0'QR$g(CTe#.pV;^|w_~]+yfYO`C}fe:/+8c*.O`JX4ceAŔeS[b wg{gJR*" ht Ahe>" (" k! @Qi,: @PnP `` uᴅp7h;sZp/a1L!etx@'x(LpNf!>3}lN2Ĕ. 5 \_+ >(l@(`Jf!#6idJ9tP$ 4FWg+Y Dʀg:A!X$,#P c%(o]LQ6 ࠘E<Ğ:bphTP'r@,*V OxE,fQdSclS N] "X&Q -x\@ 8.Q6joje,#%0@!~!6D eH%lq?'ۜMyJTC\Tj+T+/`{09֑,5RW`Č/`0" TLED b 1ce,THG:(  -g7L /":,qCpq ^ PzYf^IuT|*j4J̈,Cex3~6d9u`wg_p$bF)>UjVӥ8k%]zw\ޡO4&Yks SwkH l 4_VW.b;$\mw> RUT{H!E3[-n1W#毖T%DĠ#/&-WnZםIbب1.!6o!Ƕ>.r$;fF3Q2'&0%eX[p8d]lv򰵲M̰d!䨀Z>iCvump{ZzG>a+ܰZ?! T2OAȷ8Q +| ,"U(2Ba<"8@[#'yɳk {x"M^0'p eLL> ! ~&1tV n0LQY,+j{r(2T&'{mf;C|YhľY?qY3`2No@hEfA/$dP8HY$g|=?贏Y؄8VdA g8J/K9̈́i,<>ßEfEA' 0G_ӧs"*xEqzwL`gk:ؾK_{J?&1`mq_?ͣ>@ wxk3zx3Pyxe0c`W?y0&8c}sc0Ó4#a3?PXSe(?k];] D>,6[Ī f8CCK+DNDODQER3rRLEU\5;EV|EXEYEZE[E\E]E^E_E` FaFb,Fc@<2A<*%A9CC*HD6GMKLXSF*TW9ZYb[Jb]SfaThaMeb[jcSXfZkf[pfRniZmjdrjVGlmsl\snbvpczsc]tnyukyf{zs{kX}}sPPqazAs1K|_!Su|,yB|Ȕbb*c|V@YJK6bn~'` c7ME'GtWdf0Vѭ~ YqͮjGoU时ͬ6ýy߾ȿvµOĸܛĹijĭſżŰƵoȺȷɠʉ˹P;xξμczİs֛֯pȈ˚۽͍k̶Ϗԩԛջ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˕۷pʝKݻx˷߿ lᢙ2iZ̸ǐ#KL˘3k̹Ϡ!'>L'H&^ͺװc˞M۸sͻ߯%e*Mg+_μН /Nسkν//}Kr#W|>t'g?J'n2'Ɂ} 8 E8ņ܂:xہw j!ȡt#j5x&XHt'.ȚuA9cp$d@Vw8Xlr!0d$)ہ5`Աtaa2}$W #wr(GJ6D_( A$ʛ!m(fiiE,&"arIn$c:`%V$t C#OX@id!+DEJi" JJbFhjzbej+l rH҅]0`A>B\AaH+`0BK;A LRŪ6 Zo#<I 0xA ,"›`Ɓ2xBA/ Ȩ7,I4G;Ip $5  ?ȄFvQ!!z-q*3EY]2. ^520dPcf zB Ȁ&q SOxeL}ȕQ)zZ$K TH?V MdـJusj$(U2ӘR A#,7J}i&&<x 4EJ0H #Fyh"ap71!u.0D0IZMz{>Gyy$MeNA:zU-Lщ6 2y'H`P'֭vT4ƥD)z@͇buIV2z^PBAZ3m2S]y*788KJ$ATEX:D/f׾53 x'B34<5l&Drʶg.HD,mQ[NCrO{K뎷]vR禷q>h h : p4|&''n"| Wёp$8Dms&?ySN|C,o9ycsS*}%`;>􄠣xFr?>ƹԧN[XϺַg5bw @Q_C@qxc숇-!=G9Z }(r6o1yg_yA?zћ|=1SIxB!J(D =AQA! ~tqܣ)4"*<(](/U )s*"9q ` 1Ѕx'vڐ`v0@0v ؀`0v  ~0PpP tCw0 xww0@|?'~'P~VxsY"vP g<` ^<  fx @7٠DPX174 ?Gn wxpP}A\  [_P p  [P0 tW M GU،ߡXs0P>40 1P 1  ` >@ `s@- @ 1 ` >PȐ HG5 W tPtPw 0 @ X [@ _Հް @x_ʸ~8D$Ш" (@ 8 `aIЎa7p6PB@8 ?6@ gp" x1PБ@}z~x/3 | AEٙI G"0 -m@P]{(x - s (,gpI @:@ x‘9}PWM`vx0 /|M`6T()l  3- )4i]I`)ZYsP>-PJfg@ 7Ў){7 |Н' ɞE GřPZ$)!w 4,`6 ,ɇـq _v^ 0`@ *P zQ p!̀\ {G}7 @w`\P E@ P S:"@ < P ` 14`3-k7,y {7`,p@J*|Ȁ,gGt9 MyA}PMPetEPɀ߰Y ` = Rp -wۙ*!s` 0ڀZ` od萦oG3@ $3۲Ƞ80!  w}Wt|wxy 6hx~w@} (l(l S"0p8wP 7 Ъ  5gB)"k( ն;k p 0 k!$ %+i, Vu!gJ$k=8!SȴYk*Q>EQI+*04U+.:  u Һ?$207|$TVtӴ5uP^/3{ &k.ы.P!4Nf,H]aT900d m-& br<(@r $ @2۱[G E<.80g4<C+%3u9 P3,z V L" qH' G?1أP`UmbX+pc0D.T+_#:x\FI K"` aP Qm şt p \`'E#K2 a^0)¿ ORQ7,3PjhFȕǵpp6`%{|AiLe,3b0/&EXtS@P!8ҢRp07SdEXe[,˳Tvns搦 p` H'  JЁ q@pQnIo8џTr z,aA``IG'-3fK<;`;a6#i$ J,lȠ= @p0pQ <0B l8czxsΠ3m૏@dG ^Ј0P;O @0y!hG`@2 A P `@ !Qai'Ŧ+u+L!0F` `` `=Í.p' 1P@ Z < @` lMΐ ( Wi ?7 <P6 p"G!P_Lp!pp- p0  -m P$ 3L%H@ %`q  sp $: q03i X`hi`0`4@ Ӊg  xapD:IG$m&5nԿ-p``ܾ,GR<| ЅXpgyPpmJ R> 1g@o*- |P+  p  nN@G LPװp^μqp`N  HW80@*prHx砆^p_{, { , fGpPIIa N_:@] 3nP )B=w  ==~@`0 W`wJ 09 3G0gg ?=!?"h }`*/n0 N- e ~ @| ׽OaP] r"C?Qa00n0.p $sP* '=ڀ1z=t f >P/ȗ!@K|; ؙ@ c  NN$(PR&q .dC%NXEm3-9ö%Dr9xڐ78t]y)47ϝfjcZ[ELik)è w]{ p3I*XYiծe[qΥ[.܃_:Xar$cȑ%O<9a̙5oܹo`-KiԩUf-gرeϦMtmq[ǯq'^m+'אXIѥO^uٵowŏ'_u7{ϧi՟?OTo9 H*B 3pC;CCqDK4DSTL/cqFkqƅڻ@pzlpG"O\%\2q2M$)J,rK.K0sL24L'|rH#tM8ѽ8sSAqIrI\[petQH#tRJ ̯RL3ő':E6Sqq\35PA@50:te;V\GM0W^uW\Va3Fc,6emvXcTjM6 Af"ֿKO\|OiMy1lO%@PAUAEEZVxavkwY7i^{k>eDd y{'a`k;ygQeLW\``}hVziMQ*{"hفt0 jpg(kH{ @>(#`"n7P@uCj9r^)h> SW}u["d4fF:Ef0C zg>ஃU g yYd)H\]3HTTQ@`w ]2`  c(CFH `*@FP􁝛-]p[pk P`DtyUx. 1cnp'.txꐆ>C JkQp T/ | n84F(Y-ic$c͘ I>b, '2,cXG{)piHR#4/f#&G9N>.HPT=J3!,9#V$Lb.@팳e-mHbk5U[aF?9fT$+0?YW <  P+yA'|P%4q\t-O3E 5 90@ "Z$ B,#`5%a*L!L%Ⱥ1# HddRIMq0H>P3@xoTg(E0PE U ?T@TSjJh, ɜ \y>l!:/BF9fthHG:6N;L+t=iPoҸG1*OD]jXǺӣ;AzuюvNu8Awnq-];TT]09 !G-kp[ , V@>a)8vB`%l@8oqȣVŽ+" Y` Pf" x@ȱEs wM~r?܁A E{ P1aP8ʘƾ |B /N0@ a,"犃(Pex r]^9`vY0D(BF?Oρ.t;͍%( ԯȂaH=q HyЇ^m = qȂЀ1^{ | K]A|,gH @>! YΓ#f}컙~\p" P;<%#,6r_ '>b|Uc >8+@<@ؾx'>8'@eWPe;%pcXc0)w0#3K3W86 ES7Jnpp IAAP@hSvp%p%(¸'0M540:1qhc!x. [(تIHUx4bL>B;C<½06+?ePK5Ջ 5AC3F @`a hA

@<2A<*%A9CC*HD6GMKLXSF*TW9ZYb[Jb]SfaThaNeb[jcTXfZkf[pfRniZmjdrjVGlmsl\snbvpczsc]tnyukyf{zszk|kX}}sPPqazAs1K|_!S|u,yB|bb*c|V@YJK6bn~'` c7ME'GtWdf0Vѭ~ YqͮjGoU时ͬ6ýy߾ȿvµOĸܛĹijĭſżŰƵoȺȷɠʉ˹P;xξμczİs֛֯pȈ˚۽͍k̶Ϗԩԛջ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˕۷pʝKݻx˷߿ lᢙ2iZ̸ǐ#KL˘3k̹Ϡ!'>L'H&^ͺװc˞M۸sͻ߯%e*Mg+_μН /Nسkν//}Kr#W|>t'g?J'n2'Ɂ߃#(]l-H!~~BhG6"kl-~@! a\]ځdl<GB$!2zgÝh%& NHF;Jbn(I`A1k\Gr60|^ |̉d#L%oá'I`V╔Vj jx`,iN9~*ᡪJ#JI34~F**j:L9$v*I☜fmYeZej,l rH҅]1`A9>\aH,`0BЦ K?A LĨ6 Zo#< 1x ,"B`Ɓ3x9/ /j| 4E;InH92!BjFZ!!Lp`C$P@&It@akcBwF 86 F8Z*pHdAO1Ţ mCF p@'>jЩ!lp\0 JI.t) XU8D,`7er_ }G99Ls!8-Cuδ'0Η#7.oI! @nHb#[k&$Ml TO~ U0X270IS$SwfP=rNB1G8vJDbn PF`,`7y4U(ܨ4)8| @<!o6nҦ~I"54X9R05-G"..I<F5P[ 1EhD9I/ofڨD F0K:PH]k첥$K XW@v l3`Bl 5B`A@/@ P$.5Z 2)_` =d.:\!On=kF`* j8ᶸ 7m`rިNH`Rr3JbtS8";hCI92-4^/CpoH X!4e&DW4./f7&عZHA/oH0ofpcIbL!jFU h+ 90&%Og~(ВE/H׼xT2BOg1A F XGZ9lv QY^@Pv2NeCbǞ/!Q3&Jqw^z;΀Z'eI 0X˚R^bYڰMn{B}vrqOmtV v7A{ gHg;7p?AŽd|!B5ц&_vʧ镫d#v1Kv8>wO];PԧN[] Dyx:9t`7*(0{T/1v#9;aadxEQVlC@( G)g>W嗇tKy\WDalpA w a=WOwC@A*p?{ ] @xC x< O!G4r|a1ClR1S X.nUzC 1P0h7P]Wh> `ZGP xq EP =Psx8xv<ȇ}W[~q x AnPX \ 2 pp >YI @y% 0  .mPPVa{(x p. s(-gB @:@ xy|ЗM`vՀx0 (|M`/䐓M<9e  4. 5yVIY)SYsP>.PJ`g@ 8`)zLj |P{y{' IE ǞEyH*z~gPPpyu X iw-P  -P9@ Ƞ 8q`  wPw MPxwvՠҐ PPE P0 iJȄAIڪWb` ` 2P70 H20Pv2.0J w` 5Ыd -R X0vND|'EPB PE kEp v Ю)נB~I07p 8J0֐v`u`v J֪$ۧ ꀁ0RP:}pw@gw wy'  {!rr'b0p9wP7 Ѣ qq @:q.F b6pclBPc{TBg` kI P aPviAZd+}VU-B,b9Ri8RĔYei)O"W乊b\` `` `=/p 2P@ Z < P` dݏ)( Pi :7 <6 "`G!PYL!pp- p0  P-m pP$ 3%L%M@ @ P%`q  sp  :q4܍i XЬa`@5@ Gi0{i@Q .&J(#> Lyߠ;sCOẗ́fF:Ef0C gȮU tgwYd)H^\3HTBSQ@u ]2` D2HϜN$` ҉EuAH*xȂWgbH3&.jl[BefyZHU +"[V'wBqsn}{PEM^oUKQv5ykD)/t^m C|/zd p=<3*Y 'xB+Vq.l=@3q+btD%/@1oHd#I.r'f4dL!D 1 +gq3d߱M8Lfkfsf8ǹEcs|gAyC;| ;qb)I+ 6S}mlg[۵YbPX h70'0NM#h=-y p7#aCd! PPt@ 4 gc@B@a9v<x=qt;1߶\oO>F; 'CӐāCpB] |X™Ȃ ̐E@TC!FD`nȽuc[w6bdEQoV؜ 5ywpKP77äIw" )(A0"{-A.B'v" b@yy.:u%L({w=W~!W+`x, yr d|7k~.+>WdSvQt׽Bxj @[ @ ,~ѐ>x'>3'@eWP`;%pcXc0)w0#PF3W5< AK1"np I!AAhKvp%p%'0M5491qhc@<2A<*%A9CC*HD6GMKLXSF*TW9ZYb[Jb]SfaThaMeb[jcSXfZkf[pfRniZmjdrjVGlmsl\snbvpczsc]tnyukyf{zszk|kX}}sPPqazAs1K|_!Su|,yB|bb*c|V@YJK6bn~'` c7ME'GtWdf0Vѭ~ YqͮjGoU时ͬ6ýy߾ȿvµOĸܛĹijĭſżŰƵoȺȷɠʉ˹P;xξμczİs֛֯pȈ˚۽͍k̶Ϗԩԛջ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˕۷pʝKݻx˷߿ lᢙ2iZ̸ǐ#KL˘3k̹Ϡ!'>L'H&^ͺװc˞M۸sͻ߯%e*Mg+_μН /Nسkν//}Kr#W|>t'g?J'n2'Ɂ} 8 E8ņ܂:xہw j!ȡt#j5x&XHt'.ȚuA:cp$d@Vw8Xlr!0d$*ہ6`Աtaa3}$g #wr(GJ6D_( ?$ʛ!m(fiiE,&"arIn$c;`%V$t0C#OX@id!+DEJi" JJbFhjzbej,l rH҅]1`A>B\AaH,`0BK?A LRŪ6 Zo#< 1x ,"›`Ɓ3xBA/ Ȩ7,I4G;Ip $6  ?ȄFvQ!! C/*XL䈾y$6oP7C$!LBoP b`@~ßΕ*.>s&-?!kV4^;( 2I\k-[@d`S6^sz~]re/*lԸD_Z/3U(20xjt PbGP xr EP E `tx@x~Dp7~ݰ'P~XBv P g<P ^<  hx A8 DPX285 BGn@wxpP}D\ [_Pp  [P0 vWM GWss0P>50 2P 2  ` >@ `sP. @ 2 P >PȐ KG5 W tqwx à0 _@ pհ~0 X ) 0  @ 7|ŌDYg"B@ - ( - Q0h<0 py` P t xv GH xAPP}|~x0x4 | A$Fٙ)HH%0  .mPP^ {(x 𕉐. s (-gJ @;@ x‘I}PwM`vx0 0xM`7V8Zȅm  4. )5y^Ia)[Y tP>.PJhW@ 8) {W wН ' ɞE ްGřPʟAgPXpy ~ Xq-P * -P9@ Ƞ 8qP # 1xww M wvՠҐ P Ep P0 iSXьPZ(SJ < P ` 2 5p04 .m7*-y z8-ppPJ*0|Ȁ-iGTr9 M yQ}PMPetEPpY` = Rp -gksp 0ڐ[` qf瀦qG4@ "ۭ1Ȑ 80!   wt~xy 7xxP}X} p(l(jk.5p9wP 7 Q ᬺr qР:.{"6iPk۸VX80p 0 m $ %+iBk'oU_m~4@kJ@ SYk*S>EAI+*24%[$[q0 _/+ ;M2sMRAeLG M[SX%\>RBl r? iIdb<O| L&e& bb<(@r $@"{G E;/8f$<C+%3u9 P1,z V ,!‡t2p{=;eV& 1pEOWP>FB, , @Ou5r+7(EF|čq0 %v0QI%!vq]1$3; 'ܻ uU2 u6Ng\x,zPw`sp P|KlQiLc,3b0EWtD@P!8ҢRp05,͓RdUXe˲Xb̳p't倦 p` LzPhs9H.RXr@pQnIo8ўTry,ba``IG'-5f; Nq $oiDaWp :N  : ţL0P F;_gp` AtX ~dppM÷* @ @@  ~P*p w#iNp qP   t^{s0q J`lgl@Ǣ7Ȁv` w  , RH v,na0@"/  ~k1 ~y'p 5@ P z/vhj0P ଡ଼@]I z7p`}1fp k;p ?p 0] 0ڲ0Ʒp$W@!]  W~{0úP(0 '+p 9@g 0v \ia @퉝 0Nw!0 |0|>Z[Qɶ&NrɆm3xA! Y;qʍnvUyʝlQFwNajK\QuJ)q׵7!R`N)L&MZUYnWaŎ%[YX%ez[qΥ[]yWirFM[aĉ/fx_ȑ%O\.,pcСE&]Z˩Ufrg?]m܆QwjخKN&/gsѥO^uٵowl' hկg}zf̦͟4fv}o@O?K@A#pB +B 3pC;CCqD-+pE[tE[[kGeHY%$3$L"aI(rJ*J,rK.K0Dr${L4T[?_15 $\ĥ\n[&ANDUtQFutR'rsMQ$939)m'=PQ > ]&cgVHoUG]c;W6_-c{e?3=u64dF.ֻqfԾ\u/$Qg(V, S Pqx` 6`ՌVMxw]x0aU3~/cv[??w&;~fUvId{UY >% Eلzh6Dž @ nf@`P1e 7yx+چl @e,: @v 嘹` {?uc>ztK7GLX bfDaQDaf>A 8}&H@:P MxEl̅?3D.@% j+ >4%`m@(`Id)#,D~:&P d{TgP Aڎg:A!X"ib\&;^e̘I (:"TO (;0UԋRNEGp@dpj`E0g LF-})H tLAX$,6^\Fp0˄(@)P$.@CD<# ̖83Am@$l?+bJXR2V\Z]apˀq^&HBq#r.0n‘&/Щx1xSjN̅@W(R>PӐTq PD 2 CNSFbT||3PA& ! |7 (3 U<&qMsv^IUa0ܐ>g]?T>:E 0 G (@evf i3GP4 Y8XK]'  0gp7 X1:,yrq +6S]UІVвT4F/TlͧVx]cNbFLC.fb~3ie\VCb}L *PUmu{EMuMʓʕ$ ڑEqi˕fk͋#Xٞi}o]\.|ɵ-ªGmWɬgS{u'$F-8,(W#&qzڄg?^e ƹ %Xdz Љݥ"V۳` B""?y?~ M[&$eGwc&3,{<7`7Yss|{sg@ZД)}3A'Zыft=B`k&GgZӛt]iУj`MW!B'Hӫfu]jPK=y`; ':;1kc#׵ǭ]'`$bC~ump&֑GBa+ܰZ;! S6PAȷ8Q + ,J(0m3Aa<"P9@[#'y2nȔ {p"=^0F(p eLK> ! vE'1tVb mV p 0CxrA xr(2׈ 0y~vo/7;Q,"# d=ysz xvDdA0L%e8HY$h|=hY8VdA h@J/K9i8E> KDPvoCTA2OA~_ESp,`3t}1nOkC A+ͻ>,@L wpc3zp4Pype8cXW ?y0%8c}sc084#xb;A@4q?@#P[:@A̋ v=`WX'X"t=p#\C-v8!XAWB\p"P(8(<C;C»?eP3=s; 5ACc3Fl `ah`A@<2B=*(@7;@(EC8JD5GMQL>URLg9I(^ͺװc˞M۸sͻ߯'e*Mg+_μН /Nسkν//}r#W|>t'g?J'n27Ɂ߃#(]l-H!~~BhG6"kl-ہAHw R\]ځll;X%!2zgÝh%& NHJ<֠8NRhu#\ %0߁ȁ$r"!t$%`Mx b$/^饔lpNix**ꈓH 8:kzz9IkNBh9&gU#ЩCVI鸕f l$|"ࣣ*toI"B pN0$WA /"&Ó&h#|P…NHRC lP$!q `e[ &*o:*Bt|nRA=78 M"~p@,  C~' d@&QY|u:P>w-Jdo jށ+xzڐЧ#xBU <Шi=Pxp!)6Np?9"8 I# $) Z Ja5fԐ IhNG$PHꈇDC0*J@2`j:rC4pw 0(qHȢ  !{:h2ب%``Rк!l6% ,6H>yT!`\&I_;1xɆp:RM >7P 4!#I#j$A7 nD'% ,ax[6*JnT@P>1{UQg^ K 7!]aV} &KuXYM_+=~Lt$ /뚄 Ќa` Ye( *9a Ę(98:4&kPZ!6K`"@adӕfYajp l@ga6%)3^@Q"Z'b[`L=-Ł%ϳ8KyQXֱhofS<f `z "tM% Lw$fP-!)R.3GDn/ "# L3Pn@<2iDຕ`E6KF1f@$2 Cnw[,eavE j3`z)IV #3`^\ˊJbJ=2%N0fJM,Y,ix͊E% S 4%qZ 3`!@{U&gPm%]Z6 Fpp!B߱7 JƸ5o} NƤ, Cn),Av&tζ)Te-n{Y"NwMz[~[8Z!ɾgH ^ptL  ;rFB.r'Srg呂R"|G p :W~gtGy\CampAw aWOwC@Q*p?{ } @xC x< O!G4 s|a1lR1S X.nUzc 1P0hGP]Wx> pZWP xq DP <`sx8xv<ȇ}g[~q x !oP~u P g6p ^60 >2` s H 9 <6@Rs0kpwׇ` Ps@ pw_\8 _p`[vD` pp 0 QX(g%7sP^@  P 0 6 p A Q7P2040 ` @  tP{ GwC \p tx à0 _@ հ~0 X ! 0  P ~{5w<ٓvI(@ 9 p`aH`a<`8PBЌ8 9'8P a7p~ $9w@w["x L)`ƧM:铔Y'. s2`I4  9@ -PW9wPVP0QP-p%,7ͧ|i|\v`P G Lv Q9ل;iɓg"@ m`PpI8PXPs P>.PI`w@ <`)zl@ P ԩL@ :wI }L`}[FzgIw 4-`8 -Yڀq0됀WvV 0`@ + PzQ ( wPwP 7w`\P D@ @ LĈzi"@ 6 P ` 2 46 .e7*-y0qjwp 4d  -R X0vpND|'DPB@D kpDp v 찮)נB~08p (I0֐v_u_vЕԊ"˧ Ч0R0:}pw?gwwy' 0 {!Rr` !@p9wP7 !{ aq  ;a.F b6p! 4a[qp 0 eA$U+չ|rVE-2,R9i7RTYeCi)L"UĹb;P[Iںc00%K2oI A^UYFLVC "PҋǕ3{ !d{)? i0Id"<H|N&be& b"<(Pr?+뫾c + %QW% 13?bL l$259 P,, w#Ul%'t2qpD;=:eO&`S*ppcCR/T`+ZP:u\@,C\E<@ %qv@M<p p \Z'EJ-# ap1)€RQ@}FP0fs64F5Ǫ[p8`%a{wQiLqBAr0K DSd#e},#!D&`[YeŬ !q03v9w_ րĤWP XI`7@ LWM (̢#Ov$r.bfc+c1iZTq`L 0000 +d0Јu6  H@6sΐ6m@hu<0P ;N a`@`mf00|P@PPf L{0;_QY!0?m,` ``@@$`=/p 2PP Z A @`  <0 -֐s6 "@G!PYK!`- @ 0 0-PP4 3#K%-AP 0` 9B!.9`mXΐ l n 6Mq,{i@Q >؞T q:CWvڤ 2 g@e:-q{O*  p  nqN@F KPPp|`G0 BWW90P'+Рjbgl'7vnQpP@ȾBaW wNY:@ %nP0 n4ɀ= w 0==0~; 4@ P @z,P ZmJ pT~z @z8p`-1fp  :p ? ]ز7p׸05_aq1 pn/Pp0 Cs+ =20zpt00v y!@ K| K .ؙPc@M`7ڮnu w u܍#w8&9w̓w.yYtp.ɄØDxm׸Dk,Q Γ&Q"ZQI.eSQNZUYNWaŎ%[Yiծe 4f[ +T]yo_p&\aiC$X%O\eoďAiԩUO10B  -8j cf g  @  v P7.@/Zy\8_vq#xM6JؗQT@QYFrgp)gBU>T7Xd$y!Y 3D. %@+ >% ƨj@(`n`p96%dvr~+O]W=C&CDe0@&%*K3(ᆫ p]@B=7! p!,>נ0@*F#@c ,3BC?$&QKP?GWڅR@(q~+ ļ@eAHAE3`xEJpLZE b/ DZr|@ [1Qd'Dͫ乆%<['/ z,3θC3`̍[ wh)O&a]Ǵ`0dXK P8&ř˓$g97 o !L!|0 1P1 F|8JJ0 j ١*3gx 3pyU z*:@T\Ly4gMmzSȡC'gPQ,<.20Ҍ`; 1C0> 7$E* 8 P V9;]hvS`[^S&o  8qzX&V:ôus 陗I(PoƦ%- g4Ŵc0`@.21Pe·NXVqbl*$LgXQSV5Mc%>":t<4t&=ʰnwۧ =.y~;^<97XӲ|4-feYAVp'D'̐c:S&L~WIwLE`poSB -6OHqA\X(fˌf4bD!Dm|1Vq7:G|d$'YKfr,sSr|e,gYjlDe0Yc&sGeش %rbf8YssbzC !jBIYЃ&t|XGx8v@p9ѼKm\XгumD Y|t Sh#݄,L J>@qG1 e3V0D q|EP5H  :cp@ [[Wr ][aPĮЋ^Ei8[ !@b4د>4 C(@m YH G9,Pȡ#$07D;yxG1`P" 6+&Sg8Сh%JPF #pCBdA0Ee8JY(@>{~eY8VdA h@.Y"ūi믠> Xuu{9R`*]gyL~+`ȈWB;½J9B&_g~'Z=Qf8g_7&̾h!W(P+t/c(Ƙa"x]EhŦ/KK)BoXI;@ hKvx%h%@ۃ&(Mx4481Ђqhc$!hCq"P(A 'Ȅ< \B&lq@д=eP;#4,B+21 `a@ 'lC7TsЁ7C:CAB;C=C%+)C@ DA?DC@<2B=*(@7;@(EC8JD5GMQL>URLg9I(^ͺװc˞M۸sͻ߯'i*M+_μН /Nسkν//}r#W|>t'g?J'n27Ɂ} H E8ņ܂:xہw j!ȡt#j5x6!Xt'.y;cp&p`Vw8Xls"0$*ہ6lxa4~$g $ws(GJ:„_8 @$ʛ!m(fiiE,&"r*In)%c!B`AobL+l@B&O@ PRŪ: fЯ#s(-?!!kV4 <:<+\(Mrˀ$C2$Y v`!1h`x#X6if%yatۢDoe}Z/$Rġ9яF`< H8d X'V$q5K(<Ɂ,n}0A> ՜SER&m`L) & A^ zDF+1ӼU~4^lK*StdëQMV ` 剆uV q$Qm 5#PX!W0ƺLMTΒVI"UqEM9]5pJ~8l-`l倎y"53;2l}Kz=Ldn7^M:W{[*PXvMz 0F~[M8Z4! N Gtl I;gSIn|^|7ͱ;9Kюv I74wN[XϺַ{}(DzB9vh7**q|X01vC0z;q bdEaWpc@*02y[sg_y]yї)9EqmxAw  gOwcH@a+q?|0 .}L#>X ?F~a0b gm_;P9AT Y.~#({dg A`@pG` e׀x? pbWP yr E` E``tx@~D7~'P~XBv0` h7 p _70 ? 3 } I0:0 =7PS t0lxޗp Q@tP qx`] H `q@\`wEp pp0 qZh ?w)Ht`_P 0`0@ 70p B a8`3@5@ p0P  ʰtP!| O怊 ] |y0 İ@ `P ŀ@ h + @  P 7|ՌFyg2CP  . 8 .  R0x7@ zp0` t v GH xQP}|G\,y M3 ``Χ NDY/ t3pJ50 :@ .b9!a`@RЀ.Ȕ&487I ·Mpwy@ 0xMp70VXZȅo9  7/ bY09` t `?0/`JhwP =9 {tP Q{G(޹ 7 ɞE0Gՙ٤NʟAh PVz0 Y (q.` : .`:P ɰ Hr p # 1xw' M`wְӠ P`E0 Q@ iSXN:QZ 7 ` p 305@70/mG:.z0xڦxp 5 e  .S × Y1vN%W'E`KPE lE w  :ؠ۲~ZHi@9Pۀ ؕJ@wfjvfw〖(; a0*S}wHwWpx7 0 !6{X` h/p S@4̺  wg)"kc(k%UuI` qviBZ+FkVu!gJ$$ tB0}pL62u!Y+ic@QE: # u rA$407DVtҴ5UP^/3{ %{)kP"$Ng,H^bT;20t m-' rb<)`s &@{G+ E;$08f$<C*%3u9 `/<z V,!‡t2p{=<fU& 2pEOX`=VB,< AN5s+7(%D\Ċ{@ %v@OI p%!vAp=K2# b[0*PºNbQ3,3PpjhtFeǯ9`%{$O s`0EWtC@`"8ҒR p03,͔ Rt5XeX ˱̼XB p't`p Jz xuIH+Txr@pQnIo8ўdsy,aQ``IG(-4v;<@`;a7$E& F *|> P0h7BpC nxeH Jp?ꈐ(fW _B  A +``'A`}g0@}PAТP p@ "`!i'Ŧ+u+L"@DLp ``PP%`> 0p" 3`P j B Pp =@ ͐   tjPe Px 0>>~C05P ` z-` bgtZ ˉ_I z9p}1g < @ ^  ڳƷp.$'A1](~ K? wJq@ -  7, 0 :hPJ7 h7 ?1ǔ"@K}K ݎؚPdm.԰.ϸuy79eĸLwCۖ8rEdG⻃(ҋwN"wLCl pK1"f4 b59# N+8INZUYnWaŎ%[٫49e[qΥ[]yԛT9n%\aĉ/Vcȑ%O\ٮ`l;gСE&رeԩUfmskKϦ]§a۷k,uqɕ/gsѥO^uٵo|o%ˆVy՗o֌{jǗ_<|Gߌ+Q$1@TpAtA#pB +B 3p5oDK4D׃R\ϽhsqFkDo[teqDMGI4H$TrI&tI(rJ*J, rHmK0]\/K F5i1>JtEG9N]p5O@t#PDsQ&I\ԓ4N9#4\@N=oTRI$6CUSW-uDW_U5`5nU?] =H}t „hΜ ^M3ӌ1Y40ITFD4 (FJx<9\%>r Ya^|whx[8hV$ '*j`G,(Gѣ ( %p $7RpG߸9R@PceJpSNu!ys;0\MV0fFYQFi ʁ>I@#XفPa;XTw el5Ͻfh@Ut5heh(@pM$ C9b+wJ0[P$Dg#hY DVà#3 O=p&Qx8 /|v0젆lz*lPUY #HeGPZtX+`xE,5b`t,|*P v@Ma @`3Ԡ G@Fd$#%-HˣCA3lSF>4H-\8qxJTR`X {]E4@X@tDJG4Âdf/pj0 00JxЇN"p07USDe+]T0sp*Dd xh`4!(OXIl, P6ɖ8y1X 'HP^M2p@ }p'\N9v_}>bɦ/ w#N@2%#i@y+*'%+H3f!'vD10z ']Ktlo!B -4ۭyA@.r\H@n,aN7h^r\   z0f`3]'|zh;Z1! cX<^AX0^1)[~ hJG] K8FAcw~2 <) iX<` V#c @<d8*6x8#x7<3WH5l6{{0*oȉI;@ A`?p{w%p%8A'0N4@1؂qpd :"pc<\h(`*J(U%rM@=A,B- Tc[e`>ƓPk?<2A=*%A9CC+HD7GMSL=KMXSF*TW9ZYb[Jb]SfaThaMeb[jcSXfZkf[pfRni[mjdrjVGlmsl\snbvpczsc]tnyukyf{zsl{o{kY}}sPPqazAsK|/_Su|y"B|-bbc|V}@YJK6bn~'a c7MEͤ'GtWdf1Vѭ~ YqͮjGoU时ºͬ6y߷ȿvûOĸܛĹijĭŰoȺȷɠʉʾ˹лP°͹xξμλcìåzԺs֛pĈ˚ۼ͍k̶Ϗԩԛռ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˕۷pʝKݻx˷߿ lᢗ.aZ̸ǐ#KL˘3k̹Ϡ!'>L'9I(^ͺװc˞M۸sͻ߯']*M+_μН /Nسkν//}Kr#W|>t'g?J'n27Ɂ}Ɵt!` v~on]>MXM" A|AHw!R""l;Vr]tjf# $o2w8Xlr$!$*$5`ԱtQa3}$W #wr8G2DOBIBi$_4YVhXJcfJI7$;`ƇZj8$ *\x먵)6'Y;$Z#nמ),*|-Zj.EH d$x"#,ЮtQoI"B lO@$W̻ /#&ē&`#\q񒀡g$5A5LovBAyHƼ$r"x '"̨ygЩ`仔t< (c"v$K 2$m`AcLȁ5|As{ 4 OlJB]xM\p?lc *0»iklPĽB* !{w(I@HMtrEHm$,_AKNi /č"F^ &xBVu(!A(!710 $?ٯp`#?m*[",7fq.S6p/JGǫ7 mm@<`7@N2~P4AR<'Oe@&AU"}x:PD-Jpsށц+tԧ#xB# :j=Pxcp!06OxD" V6i d" Z  ,Ё/ "RFIhځ^eCISA `MGmХg݊xƫSĠ5f1@3 Mz46鈍cR1ѩJ#ʍKnU bӞ'PծB $~JLAҥniF86JHn NJ3F>dE;6Aܫ<e63}K 6ֆ^QV.~!Bl| BXNfeӑ* kO?;\ #ئ!4`jD0̈tW P &,RD]3x,0Z52/dfAP_^o vuB(qUqO@vK5۽PI~TzX DBµN@m0m20ͦ/$Gp5 tݖHQp'0.{7I@D\#~F=i6r.řQ c˻卹wZmC0HZv[FvU5 _͔$f+U^je[):"!([S9^;-m-|sTY4&Ĥ)ؙHۭV5gi)@Ċ Xg-5Kl!^PѡgcaSP(5V"3_it1[V:ˬW3b>ʶNkYԇ#zhRȎo 9ٴ/%lh[V]jgw}~noINDrc뎷սmw$-AA~]o{7:~0l%U63אw=r\!'bxyn9uA=@ЇNHOz/A;Zs"1;nYP0! `c G<svqģ؆>P 9Sۦ('=x7Ovݢv[ F-Taw qqG= $@?c\q~ b g>s}D(N12t KP H? `MGP xp Dp 0Ps@w,xi0؂ǂ|W[@}q x qn7D"O 2 ` >`APP^`^PA P=  ـ=PW2=`40-GmuxQ|/\ l [`Q  p  [Q@ aׁo`0 !Ek%7sP^@  P P 6 ` A Q7P204P ` @  `s@Pz ;wr xvx Ġ0 `P @հ~0 X  @ qzuٷ.׋(bB` -` (` -` R0ڈh6P y` Pr@u&@w 8 (wpv[x LɁPM, q'. s2`J4 ` 900 -J9pIP0R-`G$k jl|'L`vpհx0 {L`#䰒Aؒ90ɘW9  6. ٙ4HHi -Ǎ[a0u0ڈB zP Q`zgmn' iD 睲uy8*f~f @@yЙj X\-ڍـ -P9@ Ƞ 8q `  vvgp LPkwvՠҀ @PD Q@ uw>9کib`` 2 46 .X7*-y bztw` 4d -S X0@u0N8{}'Dp6 @D jDv  :נڂ} 08p XJ0uPuPuĊۦ !0sS0xz|v3vt 0svl˗0 !bq|qP0`9wP60  fh h+@r+t;T Еo ' X4 e6hi']E^*"+s*V[!2rA%|L!!BgQEHg{ !3Pk): # u L+L"A:bLFLYC "03{ "{{? h0ITR<a| SN&۲d& RR<(@r$+[[ r`|0@7/#5P? FƄeQ/#\U"17:bAcXzp6'?ֳ@pTmbS,pbC2/Fy]:w[/24!p @ a QZA@%tY12&Puu+$gE`^`0[c<%`w`[ Pz6|$qOQ"1@ DSd3d-KL !D&ZKYWUĝ <[r p` 7yg]9[< hLp@pI|,znA }(΢#O$r.@be+vb1hZD_Le0 0@ +p n0pl6 `I6sΠ6lPy}u=0P: pPPд` `e3 ? PP P@ !@q C:Ycdk `` `</p 2Pp `Z A0 @`ՠ =0 mG rqhPb P; ?-tt*_@F)M @ @ p-m \=<$]p]bڧPp%`q  rp P  :q6΍i XS``4)  P ^`pD: 7Gn3-pa@ک,-< {вX`fyPЪlJp8^ 2@fV*-fzmO,  p  pn1N@F MPנopѹwpa9 Џ 6wW90@ g+ -pWfkW70upPR_ރ kNL;@ mP0 ^(ϋ ~y'p 4` ĀytP0 ]x෦0f %=?X }/m@ NM J ` {&_P]qw)1@0m0/o _s+@ >P~20Ðj`[s000u jhѯ ``t} 0Nإ`= hMzW `9,@ ۠O 0ZP 3gNyڴPܵġsX!1f^XÌ9ZuMŊCY$J1eΤYM9uOA%ZԨIZ.eSQNZUY[z2\9N_%[YiծU[qΥ[j`uQl:_&֭]ĉ/floc0 O\e!oٳcUDP{ϧ_}pK.:SpAt*:B뤃; 3pCCZnP8LNĥ22:ȒeQHtR*RI/TAM78F%;S,/:=[ͳ h TkxP''#ITx&'3 xCJhň L]]w\r5\tgᅖeelF]Ve7`v)a`kg>TCoo ,6]K6dSи%, h@ d@`>1͈-0"ڀ>" '`a Ocf ` y zf6` b`4.NdL8>hW|q7r e&:Hf0F yvT LGk A `U9)IRT@`s O^.` ĈX(!Sdw}gfյ~Z~&C,#B^ @)" JO$`@bzm @) x0~= XrXbrBp_r>^OC$b4 BUxA=:% g,`@vohHT#T "Xz(R:/HP09(t"§Q V$Pҷ>Qd%IJ#~չƬչ ;Ub'Q/ z3Ĉ2D Uw8 N&+^a /\W$'AwÑiAyC;| ;q4Rz)H+Mm}k\:1~ > +X F< Y || ⠇!cXn>`,d,Y(@VAj @B  u /Bw^wV,k*h1>c(c^8a1\N@6,6KHrK 5L+rTCAQ w}sC\+v;a,B#݊7ǸƟt4z At# yB |!& EA/"z~w- =+&v" b8wy@=&3%L%Z=\%bFpɡ2<g}땬wȃ {8`cHNc7By/X#'~ G2=pe18cm.%<];hPY;q> @ vP>hXX'X 4=p"I;-@Lp{"H('<ԋ \B&l N;Se3:K?<2A=*%A9CC+HD7GMSL=KMXSF*TW9ZYb[Jb]SfaThaMeb[jcTXfZkf[pfRni[mjdrjVGlmsl\snbvpczsc]tnyukyf{zsl{o{kY}}sPPqazAsK|/_S|uy"B|-bbc|V}@YJK6bn~'a c7MEͤ'GtWdf1Vѭ~ YqͮjGoU时ºͬ6ľy߷ȿvµûOĸܛĹijĭŰoȺȷɠʉʾ˹лP°͹xξμλcìåzԺs֛pĈ˚ۼ͍k̶Ϗԩԛռ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˵۷pʝKݻx˷߿ lᢘ0eZ̸ǐ#KL˘3k̹Ϡ!'>LgI*^ͺװc˞M۸sͻ߯)a*M'+_μН /Nسkν//}r#W|>t'g?J'n2GɁ} X E8ņ܂:xہw j!w (zDam%F!݉`#Vr]t񣋔d%$d@BFw8\Xlr%%!$*$%5`FԱtaa3}$W #wr$GI:DPFIFi%_4YVъhXNcfZI8"jUF$̪)`x먤i;6'xK+,6$%edr{*[kZj.E>X d%x"#,ЮtQoM"B lO$W̻ /"&Ĕ&`#\qx@BHOLRC dP%f!q dK .*rB*B&lw F[Ip3H6!Blo!"!Lib -Pf|H%DJ D L<~;6qD H~ zPp4!H[X b%>MԒp`[%P`&Jte"w G 0B"= Hj)%n`܃0 JJt˔ XU8D,`8d_j ꘶ne<)bRquϼǯ'8d 7>I!82+);-VHJ?i  8j?TN nIJF:l2SO8& ?w @h)U3 qLph$@9 (y؛8Joؐ2z ! )L{#+m P%™. Bn iok<ۃDP]]x1 L]?`!k Hg+!cFL_$ P˛I2Z-r2X]3x-ж52/d@APaf zB O>/Z% 2T_h®I󷱺W*Z F`*j:E *m N H[ dp3ЁRbykZ4#;pDCJ@l$5^/CpE h!k&DW4-/kM i5s  ^7JiDJX2]I^@o?8Z%+J/DZ:RXQj$PJ85"*Yy.B XjŪʹyt=Mu Pl8L~!QT$:QmMg0 HOҗ;Pԟr<asc9û@5qj#a=#(@N[$E7p Xq8r 1w|%r7E|5yrA؆-Vaw q qG= $@?c\q~ b p>q}L0P12t@VǟX ? pVWP xPqD 9`sw4xr8XG`}g[} x m䷄LX "X 2 ` >`APP^`^PA P= =PX2=`406WmvxQ0}8\0 u [`Qp ( [QP jW0p`0 M%7sP^@  P ` 6 p A Q7P204` ` `  sPP{0 Dw܇swx@ Š@ `` װ~@ x  P  0 zw{76y2RXBp -0 (p - p R0h6` y` 8P`suH xQ|p~x0$& | QD8I :"0  .l@PP)!{( . s (-f< @:@ !0ɧw)| \v`p @W Lv Q359O(!İ l`P I@8P`s P>0.PJ\wp = )`z G|IvLP 6xw԰I `}L }[>.2P8f @Hy@r X(e-Zې -P9` ʰ '8q @q΀w\ q| /@w`\p @ @ DP @ waHj)!p 6 p 2@8P h20v 2.0J_ʇ-p@J:p{ʀ-]Wt L`x|QL@wsD@ˀI`@ <S -W!s 0ЀM eZ׀耥e7Xy uڍʠv* @a 0wssrwuy@ +wtWw|F;} P(! )wXxB"@`9wP70Q ѫ@q Ҡ:%r"w+%Y۷BX 8P1p ' aT$U+Djrf^"mr4?*~9IsA+|@L6rt!W+hrb?PAJb01%@$307|$Udϴ5|Pȋ3{ #Ļyk)+P!Me,ǣH]_0F;10d m-&0 Rr<(@r $HKG; E9/ 5p?d4s-]p]کP%`q@  lsp  :qP6Ѝi X0[``49w 0 ` `` J(3^ ? t0oh5}QWp&  ĕ)0 4;Rf`a PgX nnPh߷*` @0@unN@F MPpqNѾxpa= P ?W90P+ 6)n^`N.{jz - \p_0 lNU:@5: pq n+^! ~y7p 4p znuXj0 ͛7@f "o=BX } ?mP ص` | o;W@&.1P0m0/p s +P u=~20ĐjhsԠ0u p!@K|[ ~ט@ cmm ƞ W.ޯu w u@ZXM;4UN7)D9R.BuU#5A @47H:PLt x&yR[Ι2D.T *o8+ >8i@(gH`J'.7F|Wq+Yoh0:D&eV¹` 9mxG.h^ꀆwl ^J7d i04@^1>Va}5BwX^8O*8 2  E\kp0O,!<-qH -QliPa4U hOp@dd#6 H悟s*C]8EJ ?X^ ." `F]GJ3Jd@.C H'ԉ| d%VC^p]$yMlQZ T 90`"c B_(Q\f1l0Ɉ.@0ECsN- P#4?R`u@-)6L K<Ș"9MTfN ہcH'Zt]peAw"1)p *sF2Q~ t@/TЃ H@f DQ` z!]eҕU{=UK0feC[t+=na]01@*8qe0K;DZыOX"xq+PP:)_]ZJȯ?ГZ9T1q; GW@SRt0J`.]S %5ӥnu#iJ:ɭ\9=[,_thm{'Bi -I׺ou1ؑMX6d_^TY^ f`V &K .n:|a xM\b:8JxJ1*XǍovʈC@&r|d$'YKF9~d(GYSr|e83re0ỶѲeAvsf8-e = x%g@ZnsZށzCGvp¢zct;hy,ә& b he3{.G93hXZֳLт, V8>a*8vB`%h88qVű+" YpEI PeX"p@ Enu}o|VE u2ځ P8!̨Ʋ0|B > N0lbvqF-"Ў(Pf8A o\TpvY0(@F87!.q'[8%0& 6J"@_E^s]TTNCpEp3!XO\KFI zc zH^ T XCeHMzQbwq" ;L%$4 _B%**y}I|{}ePy^/dz8 ̐G,d,!2 dP@F}"TE|@l{v(hXX'X =p"F;-vH!( t!쿇Y'J0UpxbLP @$LB%@=f`ӻ :4*|B2/,pb0.3C%LC5sЁ5|C8AcB9C;%+'C>C?,2=CADB,DC> F&&K:(I(E% PJUKQ0202``9D pX2C/a`<!4a{-<m `Rfla30Df`8P UbPkVeXIfMM*iD!ASCIIScreenshotբ՛iTXtXML:com.adobe.xmp 937 Screenshot 545 D@IDATxx7jPri uww~-[έu-J Z܃;$yOevflvfΙ3g~yrdD۽o}w[59u0e\@@@"]RJ;@@@JAj!   PbRḲ   @ H-Ϙ;D@@JAjyT4@@(s   @ H-1"  _ ?c@@(1%QP@@@ g"  %F <*  ~C@@@GEC@@@/[o;Ee;9UBvRbyiPm\ሯ=g'd/~LI9N3΂T+KJݤÚҹޥ92  M *999;**Vvokf~2ۺɩ#g/ᅤ)wMf NG(;w%mV\QNU NX޿:,Rҷ#a4h  K]~̰ݻə/p~YtL]zˇ్nm^ %  @ 0'5B|IpPWhmgAR8~ $@@Z9E-LA!AMrJj^IKOϳ1Rjټe[re%>>.aj9WAmY4;/jbSٹo,:Zmiw~%[i[u^ccZ%Qn!UBB=I+2vziV_/v@@-p`R_ <ܛڈnRխgfll)wԪYݶ;;[iG-w H2el~ff|2g"Q}7ϖ^sPcNNٚHޞ]2zsT+m_FwMz1Yc|0${u3NKltνܷZƛs7|9O{g @@-P$=kmsvҢy\};?lY{ԱLM{6n(w?ڷ"ٟ>c,Y«:kI}zz NZZL3g7j/]f1.`|\׮]Ki͞3_U.y-=q4_ܧݾlo߱KjT*EVJx|6@=`H%KV^C۫.tQo=v4 z=V|7񌁞k%zm^Aj]=%idi\h]}B{dzΟ7}Ę*e˙ߕJjF{=mU=l  Y H0.˯c像ufbbc2]~|#"UTѣ|ķ2wկoϐnjqҩ}̐{ehۆ5{rC-@usgj+"}Y3sv+UXA:oWQ)N}\A X3/ =̐E{c{8ZFdv R53T&4~=zϓ}Q?ۼf$=ckj4L(+'vM[`%[7gE{_4jkiV${nfV<;&QT5XLy,l  Y '5f|8"ȷ@unѿwzmϞlU ;7l_yG<*լA+=<%ўμ_`7i]Nza4oȔT6cwNtXq^)P=Ԫ橞9?lƬuyTXBb8ٟn~Os 8Zy><5uFo#oL:J^Q*i(9˶K7  @Bj?;Y.HͧN::4 ye=O{Jo=ɩq JժUd{O9+U:IN \|9@N9zyΟ+϶n,jZ5THmMY֞Q'6Zt ҮYrA/S岣~1Ǫ-d׾r W{s}ٹ  C A67 F۩G }iRG0qwkjO'ElEEdp>t0[%yjTg[7'Եou;#3gkfdf|ќW]H{K]Muv>jZfN=:tңF:Z3L8ݬI^&g  @(bCqkL4UM-7P'W 0S.G^=KjUJԯWk?;\* y ߡ]kرW~^tHsuT| '"SpCXdjk򉶊_Y Ii8LSJnBB}v\-9Mrx٦ 'd!`GmHm^ n?uket~eޕv]ڹ}ZzOf  E%P,A -x? {O?YY˫7]Alj~$骲bz~]xy)*cuDAs:t(]=jVW> Y8}}黯o揦aKخ1C5GvS7m$`nڼMVu]w3x݆;vK:׽3D/.WhW|npBHa $lL7XW1v1$ dkt*)elJm1=Sm3m/lk3oGͻQS?H${<ּ\\uf  A( U{F$?UluOpȲ+ϾyyjҤ4kH shWfG{N|\}]!sGڶi.,9jN>tھ.!/ɪLHxNhٺ'Oe/>th+[}WsU4 8_jUs,'KQAސ2q垾bHeb+^M-8ncfqGs^q%]_%3־/67?U ˙;i0 UM3}cszg{>6@@(*b R^y]9&lW{o7#M0ʫ}g."Ն5֏~Ux\? o/Ue?Kiݪ4lh~O65M?+K3߅6 Nִi׸;@NϸsϿV*T( P,Zfk.Gȍ\( :ء^];Uoge{\?3n L`R{K'~E&|ޤZontOme{AuX;\{ jǔ7 N_+Mӎ!C{u>~tik޲O2y7  @4HM48I?2٭7kG~ZS͒g_x]~噧towu%_NjT T^p }S~'JjUdAjttѮuJ7|o7'#~OF:o~y?TujʲkD9i3;[Ҹa=V6C]CmJh{J}[<"ˇʄOIJGI dk7hfOUڰkchՆo!QԩQTZ7}, V'|VŒ4HM9 =4oW j[I  @FW\YבMjv݆\Nj3̶ ;nL8 Ey{Dž PJ~{c/f#򛞞{8(7Yv-ŵWGð Z.4%^;w{y67@vEuc͜Qߤxיvg5i$շlA+6~nދWꜯ\}= PV  E) UoTcMařM$:5P3;7n">>rEWStGqmӺwmͷbO37H7[E ?g?#s4@v$ l@ 熢F  E-0u f=^d9rt^NjzG{? iP?gEW;X\76W!?,]ȳOWᕧ՞ewajU'<ݞ;oع 8Ϙbp7cx~֯h_c.w^#.Zl7mjX^Q47tͯշ֭%Ur9:ėPs-@@ B*ugjzנL+i*,/<)]s|^sgՇ2:&w:æ RG@_rߵKG;=XuNا#6}Tžoy 3}|/{wr'ӃR@E_SU| ~Dl1W))։ E56}͌Kp u  yƫsO/HڋڥS\V-UvݙZ}< ;C91ў`\G} άw>̯:4hz4;xIĿ){{"pQ%'X-C]\@@( y5W],pEӮפ[U0HMhkݿ&,Cb-^Ƕ0ל2u7;Pu%uC:e@@@ B%HUK.:[~|JJi,Դi *8Xa_GY 'Yw=?i4 5ةE&rW &Huԇ  K؂IJe[ǟ}wW IHB-⍷?(Ыd V[Nd3Ouz_2{ }f{:ud*V uj}L][޺.xoY@@@jcNG\j%0<T]ѸmұC[IH~2&L(=H9{mFs@@(@v7Y3&L귥}ol||'z74s_XtfuZ   PE?3Ю 4 Ɣ-3guk^}9xT-r\elÛ7o>zd{cpdp6   bIuW/fҖ6mw*+ȘsE[ln;wi܇O~+.=?q    Fjru}PB.$/l怞{鞬Tyns̽=_嘣{;ӳl赗,]!Z^)7   PaM^xd˖mE}!|rRӼ.Z*g_p]899Eƌihf u2,wbbYڥg?І88iJ"cEK   Jbl2 49_ދ\~7O P䍛xkZi$6`з 򛕕7   @(&H՛=Oҩ}(;da +U?[9HHK}]Aݏ[TΙo@@@PIG/6.^(wٲesw\U9秭is[{~9pra֭˧!O?Et7M滭:s[yTtO<뾂kg[.]R֮ UkRڴn)   woFN>n¤fM~H   dK2c\7U\bc@@@(=swke@@@p}g?&m&\7=! &X}Ȑmiv[ddtkRk;E{.A5d^~j/.eX]5.+]2e yҸz=Gziw xVkzW1mʔa5mܭ|1eۑnvkYMLl=pO2A?lڕlpZQTd~D{[~bp oNS]L;m   Q =MOGUVt,2:*J;`zCCy_ 4eρCyZ(iilwo(\ֽlvz\}Mۮ xnL2=쳁^GS9Vn2C7^MȣgִTAqx)olM M줗\Orki#s/]TֹkoA2\WI1yNoו 9t!D>  ":V{//ov˔s_[+Y&3CU)1>z 5^~;4a4flz桹ԡWb) [SlΟTSM3ImϩOһ>${M@Tv˻7Q䒷aWܤm9AM[*q4'(֣âu3 @@( f8kT4ԲMi?{ψ͞EsS$lz{.gNThOj͊k\tDj Mm77u!s0u~:9H1cR|{P_m~jo,sM{4Òw׷mse5 r涚  D0}YYI.>ULOSd!ՀM{ aN[pV ҅L9n9Ƶ֡a?^grrbN]OL3Wk9WsY5P<ȾgN}zLzO2bIK7fqf'K3oVfggӞ::V׾msz*`@@("F5M]H՞Yg;L?hWWGos,uHU-ia3UHש[   @iZOj ($,{h0cA349&bu_˝=@ڃ$ 5Xu qV{^ua'ij=$@@@ E^!Th`$]d3WNm^ߧ zhrQ@@@,P}8ۅ)>m@@@+Pݏ%׆#  X 5\@@@ Aj`r@@@B,@bp.   X 5 9   ! H 18C@@,@؆@@@ !   H lC   @RC @@@ !@@@ !r   Rې   bs9@@@mA@@Aj   @`6   X 5\@@@ Aj`r@@@B,@bp.   X 5 9   ! H 18C@@,@؆@@@ !   H lC   @RC @@@ !@@@ !r   Rې   bs9@@@mA@@Aj   @`6   X 5\@@@ Aj`r@@@B,@bp.   X 5 9   ! H 18C@@,@؆@@@ !   H lC   @RC @@@ !@@@ !r   Rې   bs9@@@mA@@Aj   @`6   X 5\@@@ Aj`r@@@B,@bp.   X 5 9   ! H 18C@@,@؆@@@ !   H lC   @RC @@@ !@@@ !r   Rې   bs9@@@mA@@Aj   @`6   X 6+$1c?>Ҡ~]n,[J&L"7n={J8si<_qRLg @@@ 6H]f'gҺu#R0Y}`N݈1Aס̝PpZ=jׄYtL8Ef͞/kmUFdffʾ}= I}   wqdgg`sΜ9вZGIN:7## k}_F|ݏS:滳e6y䟩3}䜳NAbcsn+o}w_E>ټȐ'YNÆK/Qǟzٕo>/]:wϙ\'> 'غus56Hvi/<.]:wg  HrJ޽O>2~xܹswmԨ=W(ɩ؂T텼Gd:0颟@i6O~ 7ӏ?d;w <=O^[ņ n[N $%!O A3Hr{:hxzZ)#  @)(LZT}6wzj~/Bܰss-7:U7}һ^֑~}{J.9=cU\9~HzSlճ{kkrxV &7u!  NKooi PKOq-ȅ}ү)w O0sO/X@n ˋ׽D{N5k޻n 9iNCnjonۦ;LsM]|ixN Fʕdسʸ假xϝ7JV=l   @pUCKkOXw =*ռ³~Ŋ䚫..;w⥞tKγnש]u\"=kD2.Ԥq<SGZzzN|#  */Piޏ;Kqfwczo7/uH7r׹s:ׯhOlO/?&s/<#  E)J"I܊%HݼyW[Zjᵯ;SiC=oŕ|3A{}@@@܁6FWc1KZ\kugٲ5kݱC[]j JeSOrw;3+;A@@W@R (n}z^>#kh2ëӴqC8i+/_γ2ml^tWޠNGsl7ʔIpM=+WN`@@@KX^ASNmR%˖ξz}7ik73+y}ή+g^IZucxn.NٷWByc -_)#+pwt'    ғ+_sp]=&ĈR'reȮfx.䞣Z;th*ujyuw?TY:ɾ];y-^ࠋ|ri¦8SMЮY\i԰W;   @i(TSf$IzV ޡ!  @|ttHί~,_[*=iii4e<;^9z)XȺ0e.   @ L G&3MΖ@{0_ArGPG@@(~+Tapy@@"P h}I%KgVE@@$H_!EGe{@@@ |B@@@p H C@@@ H"  ,@Omڔ]Cd"=e]NFF }yr̔UI8  E/Wm kC1 cge檬Ib 9fiXSR2”UJ\99(0EܽJ~<ǖStЫ{'3;Kl}Dok֫ e߾Rr")o\sår΄SBʮZFq9./_JU"U͇   rIjșw<+ٸ?WdP^x[\Ѡܹ3Ygdtv]\Ӱ\:mT\P\t(MA)lv vVV3!!!ߺ5mSW\||<=fZ]O-Sd؉|*-Ȁ'IBh  @8ԕX`Y{l޷ۆ tl]Mp(@J!S,levItTJ#?%Mɛʒ]eef2Nr-ݽ9T*u'===`;#;˻ڝۃ(}3\N;#w[vE{K;vn'[6͖ۺz\yz`}xJj|50+Ͻ{;/-`vuh}ȇ(ٱ}{eϞŏxao=z@@ r"'yğ$_"bz^=JR5Cs5i/=dϊ.pZ,[V.weEز,Eؾ˖Y15ZHo]?זioy_}?ooc˕..^. ],M5z?IM%̾rJrֹ˹(oXI^~-kz=AL![$u֒dX쑧$wyvT'򺋽W?C_~W/\js/:]Ι5Kޝ"&ߍIe˖nGwΟFBknzgaċ-_䲤Q2 Wn߱G>j3tAz:o?wZ4VG+'xs|7soIb;J9s onˑrU[Oa l޴sœGY@@ 5:.99$.:OcSW26ygzSږ+dj;-/痎sR$*&Zb˗1**6[+-}({K^p׭0_=VF5iڴ f hu-dޜ+=lݺCn{<%%,r4Sjռ&Y's1l@~y6Hx>#3͖+o6m[ ڹ3ɏ"ssӼS^>K5c\%>3󬧠A9@@-}/jxZ;MŜ[JZ'֜9abmfzeL`doVcu1.e~ҺV# lf;jisp+!w˫/ޔ^bt,N@کK{+=Ty~{Eդ+jIM.]ΰӳdK M/c;{-Śj֪9C\5uCqz(_3AI{ɉ}eο,Osuzo7h՝ }AydMVLAKR޾wﶞ?pP9SmU?@IDATޕb{5}OJ˭okowȰWJnlﶮܧ_O;Zzn@(  P"'UWՏt+1Y!iT s:+fd12~|YOPTϩQZ?SwN-??u:4%9L뤊rV ]dʎ5aVs(@Pc<^~J]a~q:V{oaw?pK:Wj>u,^n8K7o 5j\;vrkϤYU5鵻pԨUϞ={lф2rף3i\d6kl(YU=]0۴h۴y[Fbϧn+A@hRo].2zl!LjbO}-Pn燢ebrCIFPQ4(YY$+=C*J<|9fKS6ξf-:J.* 8-} ޱgϤv((bc 4F-{C,\t@9V}m{XG7Oﮮyڬ]fu-Wx߆pdu'󁵇VSSIӆlJ?|;=m9%`߇M^ƼFۿdrʰs֏p-[5ko.sKgL#+;V uk7+/-7z yYr|v~W qf&w=9Ðs~ZUT:=kC+jIKO<HE3<8g|fR3^؃+۱Ffnj>)WVkǾC55gkeȍ?KۯMO娎7pSC^f$'@zvk:WWu=Mt%}˝vh0~ ?Qj?Dw>m;i]n3t֞P'7Y=+/yCg`UBNjӮzz̚tuMmYnڶT}>k45=jj:6#ŋ;`֑b7fA$ ;kw^P]h+.sR5l,!#>;1n^s  "Fy(m+OXt@c6K_5яޫ/=35,yU|,|.JSs.3BUnub?.׶^G|vEt%Xk:?Pf\byVjb^w]vK:lܸaT\/0qoy㮓m@@8gƫm\rkn#6H-,t]Mٙ9Q1+8-5|a`o~}UG}$@@/Rs,29lZ=~QJ#lҨh)jq5Æ],6DB@@9K]wf1CsMc\FJB@@ H\bRZ)1    J@@@! LLΪh0uF,,4\@@BXE Y?#Z  @iɜkvw,}ѱܓjzmޥ枸@@(9! RCk.LT ~ho   ^AKP   j%>:3&@@@ t*ƀ 3P= U]*4G@@@R/0a" RqڨX9Z7x$}|zTKOD@@H[G&ՏƄJQNvok^vvdffJzz,K$_m)S$=+CCnpRD@@@B-C|UԖkK||ؘщMGj#4HOVVddd؀UI4)k+   @ 81jPQUW8i}SG)]yC   @4Vӏ~v0㷠zN4x40eMM    8_-Hu.4v뷿c|vaʺc@@@ o k@@@@D 5L@@@08@@@p H 'A;@@@I7   >ϳ%   @ FO@@@ |RY@@@ R#'   >,h    @@y@@xԈ   Aj< Z  DAj@@@G 5|-A@@"^ 5   #@>ς   /@?@@@ H gAK@@@ H   @ϳ%   @ FO@@@ |RY@@@ R#'   >,h    @@y@@xԈ   Aj< Z  DAj@@@G 5|-A@@"^ 5   #@>ς   /@?@@@ H gAK@@@ H   @ϳ%   @ FO@@@ |RY@@@ R#'   >nJjYvܕ,YYY^GEEySyC   @JJҰa=)_\*>XSTrrrZ6}-g^74i@jժ!111zؓ:<(L+W.0[FF-Vs(   ^ʿk56m*Æ w}WN9ШQOYСs km4vX]zu>v_̚5~wg}&_Wm   djAPpm6_̔yُvIk=:t7::Zthk馛n/_%K<:ud٬Y3ϱ &N ZTMz-m1!c{\rhxׯ_of?Fmm&ڎ{NjԨA/7  x 8jWjIP5Hg֭v!I&yTqsU{(@O^y^NwtFu[lqvmp9;OLL|IםtokyrI{smu^m@@(HZTb Ru_|aNSWO>.l7n0? (/_n׹N]D9+VjXV-Ͼnmޫ=Оwyvq'vÍCv*ړ@iG}]d)7   +P- ;|GޫI.[۰aC-9.>3?ȒD? šu^sJ^!]I'3kI8Pv Pu']X{5pa۞5p'!  y 8{ji P'U.\9u^uWh0{˘1csO:\q[l):uŊ3f@\}fÌo.?,Z3lY+`;++št=\X_CB@@pUg/U|kO0'Ugj9u;@=S"I$`]mW˺&+kcN<`{1tj!wu]μW[ǜ|]8I^[jsԩv^NJJ ,zaN|#  @U}{R+ftl*UlPw4##u}d[[S8iAͫ՞ZWt':W{I   @I(p_77vkSKm .LRSSe…XN$!!!W:@@@D\qjȌ ,8c嬙ee]^fV6h}M-Y1yGp@A}: >p{=k}.=zT>]ϤJ*:\(@ P(@'7Κg(@ P(@Ljf-[Ȕ)Sl'L ݻw:ș3goծ)))(:6lMfPQNm]=f.S(@ Pp8'3%+_U_mu֬ ZaV_W.ڰߖݲU]ͯ8WRR"@ŻTSC&Cʯsިv3@zY=x@F]C P(@ Ac9>*'N;yzI9R\>\L:MWpq)a(~!CZ-To[{ ɓWOll۶ɢct#nȪf&L&;Ś56RtKsϵ ]*V}WӲigQLQBb+ۊP/ (@ PCPkpv"d"ePݻcg$&&I?իUns Vk= /ƝG6k߮..%V` x N\*]ZRvJ}mGn.I2v:k:vlWzGO'觻{ߛ֭ -Ç/^6n<݀/?v`|5KpjUZl?j4Ɗ-h u|u=k3@0I P(gy(Y(@ PǤϻ/d>CiҤ<Y^=4h@|}}3_l_2zh3CtI3GĘwzg8 V={V{z///8%ۤ(@ P($ R ɃeRرc|r̈́:uJf̘!5jԐf͚)y籌;VZxbYr[tڵy流nCvk֬۬_֭ jfl~QFn ImG [ˡC|Ҿ}{Yz;ĉ%::Z;l꫺www p}||$>>^맟~Zk*Yqr]wp%E P(hhOClnڴI 2,`J*! 2g؆VRRUE?0.]Z<<NJ۶mɓ'K@@C駟2w-[4`+Gݼy XyϪ>|X^zI-48"|y"F0mh9n86\+jB P(PxI-<ϊWZ YR+OmR]x{-vҠڎL5KٳgOO. ư"@E7`G-B;1I}'ƍksrIiժW\9 >׮]A16Z*T{o>1f4jzP(@ 9*)V)K+C.CVZY1F* YOOO݌ lٲԩ#AAA:6 .~p(E:2&L m۶Ƙ ]y߯jժRȑ#rz,SdQ^ݺu5 E P(P(ċ@;gA"?~\gݱcV'&AO,!!!߿f'хc9QajN406t^fOnݚ/_5¥J~-ZHwq ݐQnVquuӧO:2Ve`ŋk06"׊* p,(@ PGcR ϳR@gEjMdtʼy?`o͚5_ke iDkmR+DЇ͝;W'-XQ`"d7eV`E RJ\XƬXFܴ.zQp(­E0cTO.=/ P(@#d˸ΚҾ]2>[%m־̟V][!67F{-j0i~?uk?cK&{Bۮ}kYF6~Me(@ P( fl!ڪC2nε+:O)@Ƈ%myRڟzT۾ {jeP_dt-֣(@ P{yF P(@ PFAj60L P(@ P7^A7)@ P(@ P QQ:AM~[yH3$ۺ )f܄pf(@ Pf׵q}]°ȅ8){ZlMmq㿗>v?w8;$..)O'쳍2j<˃(@ P( RS3S[5޳Oa}❗3f͗9sɩS1RVMǦ+L[Ӥv`>rL.NێB  4*x{JjE{̙D5kyswɽmS[4n\QOc| 8}%9ݫ2p`S cGݻ\9yfR^:f+g3T 5ߟYv6@ P(@ 0[ԏ='6Z7m3wd8ϿGi&k3ʒe50}M i47oRLXקg Ƅ")SF"i~H"HFu$""RΘc5>+ɔ?fJrr|sud)piP8;Cڶa9 e QuC<"}m9z,L*T('ck ^o'j]^_~ 1Nm)ʙ%= ,,NP`iBUxkPm[LCK':Kp2:Q׭_UUݾ=~N~mVmٲ8p|R%op~R(@ P O RĖA+Wם~]>;J2wY,IZ^D 0EVV ݻ)m[Ɏ&6S<=<ޖA?"1nAׇ>+#W~}:ArwO{Ӻuaee ͦ0 c|Ňm':z4t c릿F.=CBc,1F>+;gY1n7ڵa6@ P(@p~߶08QR^y4mP_*gU{LK8ľ4tl4cdQ o0)ի[[ωtq7avm[u$I>Gǜn3݌˂MF<.A6Ō9Q/f h({2&~Z~N*URE(&ҩ.ו_e2g~Ap.}Su߾ 6ҵkNzub$.߳'Zv<4o1c'EC؏1wm6T)7ٺ OOi_gNJJ32Y|}5ڭ[WP(@ 81رpʗ_KV@hi/w'n;Y?XuӧUܹs9Us}(dK]֛B6] 3"S`ʮȆpҥlu!55M^] ?zl\kv9}W r|<T3x^.ws.V+ 6%=O)@ P[T#/sth^&̺t)8/ %}Y0F4?T7en>|R'(:^lXqY4U7-i]778N&LV={fja(@ P  RLWǤ==F\\JW%3-u,kbb[u-<(@ P@`Ztefj E5W-C P(@KAm~R(@ Pn Q.Y"##[f-\ 9s&+r@YO>n(@ P, 5)fw2f3 pOzxΝ;u_kcF)#F,t Ę?QgϪ͛sEo>pBL(@ P6IQp/W}M'QAF/[̼k/=z)q#FYcbb;q2vX^㶦]\\vٶ݌իWu^=*7N4X؄ 9rDwMuV'ʞ={ɓҼys tm2i$Aw;luqmח@&Zjra?Sa(@ PE]}PL!3*FT" YхuڵpB7[`tq}؇`p =zж se i7 2Zr:ӧOC0y 7Ϻ3֭[KX(hb<.D ǣ3Q{ScaÆ0#El|Z8Lq}ן|h"sQx=&**JT,(@ P80Z2H 0@>S[Ժ9tݻڵKJk;Ç 2={kVA ݀Q2|-Zo߾֡WDvfٲe5(sݵkjA9 2N"kXWdU#<~x͜b?sƍz 2VPmXTd/ Dy 'j;}WRJK/Vne kA￯hɒ%|z/y5kO P(P{+r@VX˺Q+ˮYYY)|A,K+@:uHPPv=_dkDMR7nN:gmcD1YNf CzwjVaq( /h_#ҥK,0.P#P `tuss?X?e>FOtGAkdQEEARvm}YX+n,(@ P80H-OXd]D7]t E @Ȫ}ݶȂ1 A,2J̟?_vd]4X5j^5k1#n۶^Lbϊ1$br$kFzHe+3gg}۷k{v0n=QE["k0w׍ggfu (@ P( RS=d0vA-tF7o- f)&UT+Cq!hѢ cICP AfEЊ` ^zZh`rkH(/615DplÆ Z1;+^fb&Lhq(^{1]ƸY"VɎtbS6lܪg[DDDʸ ˪Y;wc?euL0[B>-X*hbr_=+rzy%f5y_%>>A-!6LV% [͵0@+*xIBB-$SS/x.[C##/:ǧ?fHJ^ڕ.r P]u/)!!GtGiy&*キFu; QU[M(@ Py`'j.=i#y};ohe(G<=<]zCyw2;=s}uZuь#E}2Gޒ6[ :]E)U[~~-d~B\~AƌKHҷwJd"#:lX{رO'He$ v/]ږ۴ȸ6jTA\\5'OC㏻IYԩxYv5m)۶77gyFޢEv{ʨQw6(@ P@^3rW9D񿛛k#hЙac6+7x*:Fʗ,+Tol& ޕ!.ҰA]ilҰxɼ1/$bP\l1~~zUJQEA=%%}9..I*Y+RBg?ozVǏr1߳R^9 to}f[yfM\(@ P@2FRynfؼ%D>;^xOwu|NR32{16cعv2c< ݛe+֚YEg_kÏn oM浙sZjH 15hD'PQR{K_GX d;vDM &KMKN1?44||_R5S؆"feˎjN[ЅN&u2h566I/>O9#"(@ P@Iڵ_Y6oI3G͛HU ~zt6Ѻo5?rOJ*d2gb>x?LKWݫi]x_\3-[65cTBظ1L|IǗ]&;wΝ]j@b#_EYXF0IІخYs\uuvvt2e-agÇyڵ%$$D,Yr+n P(@-L(GhJ?S[j]x{-vҠڎ@n;HϞ=g}lTTTL(Ɖ"@E@Ek-Z}'Eӧ'΁l'20L"+V_|;v={Ⱦ}|z<~Z1vС#<~xiٲʌɓ'51O (@ P 0HuK]DeU+C.CVZYɴ "[5N]z1 PQN: Ȏ{Rre͠{. 2(ڵW7},T, /h߉'6q?vP(@ 8Tz (,&Ι3Go+"Ǐי{wء֭[:(ׯnȶ_*T]1ȑ#1+0z=ݺuk~Z3 *UJsn81*>1 Y+I=E+VT؇Ȕb**#Ë,͛7Kll5JY@qݻ[I P(  RA2(p-t"Bf 0ʼy4HScV1( fݺuuEeK"5hE&]r16W^i$>>^19ѵ E>l>O,e(@ P ߂9ZA:-*ޗy@ ䷀5>4"h2W܎r躹_:)@ PPqK(@ P(P\'(@ P( R(@ P(@ WGEE묪薋FF^0R7(@ P8ٻ@w~{iٲ5=w+Νtˉd^%rcwFǎŚwV(@ P`z3 3g͓}]_UnҮMK)_\x%dz/y f~M+X/17k:."k5U#|A&LؔcX(@ P7C)-)̒Diټٻ_֯+ݻ)W,cF&/ )eİJ@9z,\>>r\Ξ֭[f_%Cߖ8F UMOOҲn&ٲm_i}zmcVLyQ?(5o94׊INI2wnu*Fx$dJ7/6m$'OӺ4=-}ʥ@q:sFԑ_GW _&}MFKe$>Z'.%%?ʈQg_K :M-Y)aaRrE)#Irx899lXyH׫:%...'!7nvHɒSFټejy,YZ7m[";w?&8٬ݙԯ:cS >V~ouܪ *J18r z~c%];IX@pI3Ibh;C!>yJ9y:x?9s@L|dMd؇L5wT ف10&nzۭ0pɒ옑+(@ P4ϲjEpLj~jfjkȶ]gʏO'OBUkA66/˓COn˝:I$qYbK/-2{,was]*q(@ P( Rg%x% KIZ%2yiF+ϘcwF ϕ7cj^Ȣ6,(@ P(H0vu.@6]ʗP(@ PF pٍy(@ P(@ P RJ (\+22wyW{IJu;7Jxf P(P<λ.fw 2fAe_:;wŋ729r1B| f޿yMu zsY5ؼyUg#{@ P( RדQ@?мunA wfl2%:%J;o3Dg8UVdذa2n8yQ׿mAhեnݺ=zT>s ɰ+(@ P/ߔ-R@;&˗/LSdƌRF i֬ϼXƎ+RjUۻrwŲrJtR׵kWJW/ [f ׿n:Yp-ׯ4jV'""B,X M6ێl@;**J bf >@V^2yd>/eÆ ҪU+]&M{j! :uhYfW޽tEСCzϰñ=z]%尰0 uVʞ={ɓҼys fc\\\믿jW-ZH߾}mms(@ PIv+֤M@i&SȌ" *UHBB[]XgϞmˠ8y%ҥKkfm6AЈ@駟2w-[4]"[^=qss+!lٲ]l'ݝ۵k'>C L02_re~ Eu`۾ j5uTA&8* q~Fw~(@ PȽ37) !O?Ԗ).L2һwoٵkvt>|;ҳgOYn"pD6*Ê #-1;1ޮ5sxAmQXcRd#PFcXGhoٽ{-PF}n۶m^\"\}QXjժe؅񽯼TTI^z xy%((HQFkvءׄOi[udAQ5 ۊ1*T.Vv_vID)gUpNLƄXNNOd$Qn[̙3"P8TtE@ݚؿvZ=ΌV ϟYa* `tF1sΚ8]Է cr*ÇkzH(@ P@ݎGR Ӊʹyٲ(i0ZAjڵZb^ ibR%`l)AF{k:qD MW^Vu?Zj5nԶ3L҄,-&JdN}XQ\&!@EVc@qt7Fb(5tQp/YDA52 6Ա_LզMmAot%F@zk /΋ׁltǎsYXYbN.P(@ Zdf.Y]?Qg`i.}Uۭ6k_OnV\(NX5Kߘ0^K3'/~L4kAZFYQ|Egu+Fkj.ֵXce_mYV`-B n \{)@ PM˿sU7HT%r\7(@ܶɈ%Lʔ]M6a2#y }Uc 3y-x)?Y[j1ymQ(@ 0H7:t悀gEfVLB P(p Rߐ-PPa(@ P l(@ P(k&(@ P(PP R JR(@ P@暌P(@ P@A 0H-(YK P(@ P(Aeds (@ P(@ PeڰA YC>=l(@ Pr%P,jUz)°2(@ P(@(A*@==Te(@ P( bV\I||Ȩw>Qe(@ P(@/PlԒ%LR oP(@ P,'""03ң۝ŕM P(@ Pm&5.>:A@x1(@ P@ R#NswwO@8 x(@ PEXv6/_Y*sg(@ P(PezmFuiؠ,Y, (@ Pc ͯ(@ PK؎Iu(@ P(@0H(@ PFA< ^(@ P(@ 0Hw(@ PFA< ^(@ P(@ 0Hw(@ PFA< ^(@ P(@ 0Hw(@ PFA< ^(@ P(@ 0Hw(@ PFA< ^(@ P(@ 0Hw(@ PFA< ^(@ P(@ 0Hw(@ PFA< ^(@ P(@ 0Hw(@ PFA< ^(@ P(@ 8|ZdI>% P(@ PN[9|zS(@ P@a>HuvvOOO),Q?(@ PIb*V( F P(@ PϤ^ǽP P(@ P(d R R(@ P( RQ(@ P(d R R(@ P( RQ(@ P(d R R(@ P( RQ(@ P(d R R(@ P( RQ(@ P(d R R(@ P( RQ(@ P(d R R(@ P( RQ(@ P(d R R(@ P( RQ(@ P(d R R(@ P((QBҊ(@ Pb?Ā]E_(@ P(@ P ZrqdF5(@ P(pAEw1^j_S\\%'''m~;n9?.gŋ]ՆgnQ(@ P@ /2P-{j]aVAfV۬?sS7\(@ P(@)} '(@ PEA< ^(@ P(@ T~ (@ P(@ Pa:̣P(@ PT~(@ P(@ Pa:̣P(@ PT~(@ P(@ Pa:̣P(@ PT~(@ P(@ Pa:̣P(@ PT~(@ P(@ Pa:̣P(@ PT~(@ P(@ Pa:̣P(@ PT~(@ P(@ Pa:̣P(@ PT~(@ P(@ Pa:̣P(@ PT~(@ P(@ PaZi&UIENDB`vitalik-django-ninja-0b67d47/docs/docs/img/body-schema-doc2.png000066400000000000000000001551651515660254400242600ustar00rootroot00000000000000PNG  IHDR94ւnHiCCPICC Profile(c``I,(aa``+) rwRR` `\\TQk .ȬߖtX{KOaG\)@%000% v-Rt=N7I g -4$Ć <.>> F&&K:(I(E% PJUKQ0202``9D pX2C/a`<!4a{-<m `Rfla30Df`8P UbPkVeXIfMM*iD9ASCIIScreenshotXiTXtXML:com.adobe.xmp 1081 Screenshot 666 E@IDATxxE{ tPқ"RlD; ,(~ *M+ҥ{ :o9K.!#ݖ&y"##.Kw9@b.&LZIE@@@./C@@@!@#ug@@@/@#b.@@@!@#ug@@@/@#b.@@@!@#ug@@@/@#b.@@@!@#ug@@@/@#b.@@@!@#ug@@@/@#b.@@@!@#ug@@@/@#b.@@@!@#ug@@@/@#b.@@@!@#ug@@@/@#b.@@@!/s{ذAm)RwR֭$3f͑]vKTqRy=Z%h2;?񏶽_ҧO]g@@@.lzL.;׌eBXX rmJ%KW=Ww{{l&w՗9{Y@@@@djp>mp ¥߰I>kYn2A    HUcrDGeӦ^ys{^G^fZ   @ [RreټysOZFrK&qiYz_X"#$cx {lٴyDGG<ɓ~թ!ՔJۮ+Ǐ5k7ȌsEdsɉ'/ &]nǰ   ֭nXxqOy5j-]*gϞ52FaZ~bݻ_̞0.iyoyćuvq/I]A~۵{|,o_^])Z{~14a{;2RKK'_۫4W˻sa߾6O1c߇oK+b@@@D dϞ]/UԮ][O.7pCehC+Ve$tU ^ cG=_WZf h@i/e=Wmpñzu-b@.i[wHw?N n3+{?C~ uM31a@@@D $& Ua8.vg H~ \Wߡ$VۥV*X@չCTϙ~ej =&f#WN0WgH/5-9u[ݞVMY   @p:C[i*W%* t׎@{$*긌=N}<Ìljg*^dɜYɣmi';ʋ=!gΜk6WNuyS.+[t='ҥw=^z)tރ#{62mL]o/GLص{_]nߺh@rl1]_;6;vJZlKɸ&˒e+u@@@uBeXA@@@\)d /:E֭d[K8XdYxQmip^},*:[/-[m}_3ۅ˚% [Q~K]PI    Ukɑ&Mt|vϽh#"<\4WW|OuE[YmULwףbŲq^@>. YH;@@@[v'o}i]/кﶘ˺)ӳv#jZ \R-${(ҁdmw~)?0]^4Hp)ٳڽW 'VMhٲe7S6f˖5!śG@@@@K5h?UXPZHOxڌJ\'g;    49 D$@@@@  9evV|ֿeU$(1JIdSZ.@@@bIԽK͔)WZ(8H$AB@@@+.*V}!,E@@R@9N&Jj#ܭ(ՙ   ^$ r^b@@@B GR(s@@@981'@@@@ ȑʩ,G±cQ2rs2ɱ;wN_"7m    W ɦMTpׅ8ϩ29}.Vug# Vѳ'e2fvHIZEe-` #7=mY]9玖-,7k9qd˞]/?"XZ1w\ɒ5s6l/-7RYGnsׯ$r吜EB@@H:uwǺ z|z:iЭD#;q䮓jM^䬕t,ZK^ܝ_VRb/ Ǽ9mnƾ nKjb6_f cwJ6m}amc/I e 'ov4JzX"#=c~TziC~狹vSg,W3f }pc#Ge scR Mem?JpPmq-l7իɗ1?rRnSRY{|7JHB8=\:F4ƯzQո9E?g>_HLӁHs t*0Ȝ޼<ϧSZ3zVwiMⳏr%%Jo ct gڍul!_(:G3.ə312n.:Ln8ga߳m@Y=lAk7y _ )h5ѭ+v9 K>iJ`+4i G_4%ky]|8y7r!?oXz~>}5d)s&ٶuO嵞/Ȃy;vIrlƹE ؟'st_u P 2B[D6nl`xIu@@$@w`j dJ٬o[+f5sp(n. 7&1zlVVLt, 5_ju2}mvmqG-1H=w?>4yn,N@T]d4484(Ф -cm6⾻MW?|,?|#b1twFD_:i|y۵&=߾/ħ&S~MQv羇>q>#;W,ѕ^_}*֗K< }۾%BE5z|=-Ei CO3yw|2/J,/-ښ{I'rՊutSKQ6`^@@@hadtF}9Idd9lbYlg gc4gݞXl]\&^{TYLY,CnB[sn_9~d{}%M4~ת%9f &;{fĢA&}t2a͢Ft|ׅMծ2ڪnrhF hWm=Rt3y{Xy;v4zZ||+ ݿg^рeK N~mutMz۪,y }YӥsVJ:y}rKR&o;{e_Kk:' EM21{|ە7_etѝdƴti !w:NV_𝀍n:o%KtƓwT?~?5Gis]b N`Hhߤ~x(BDS*n>i\3 C7> hp$_9qv@@@ RLh!o2j<$,kp]h}^6K~&cY^ 6^ᴽ%{DFiWv喟v̖$3 94<{nHoӦmtR2uQM/v:NW(i X? RDQrBt&_`6i !ę'mZχML[_jEKJ_+xck,X6۔Zo)|ty|lܸEF8:yD9)qo0 rh O7ϰr٥M 3jgͳӧRҲ#+'lD@@!@`頠aiS'^]챳'm3,=El$Μi2cjˣEcNy8Mv2D<8&>DVLsy;ֹlk͖z~$ NcOڮkwδmDtRNٮ=xjTQ{iA:kHx|=ph|g:0emw_;D )й|exaUN*[:z}8tvk:FɯfׂV:E{K RB 0Ǜ$?( MV6]eNV"f@QLqZq<\ [Ydn2uҟ'_crh*U$4g3h 7_4_9"!  #rJ cfҾg%cD:l+cq `oՇ@6,Br'IBˮwn|3kIUԧ1]όhR5{9/ߤ]kdžl`nAɣJZ>p;iܘIvZ8a?0A.O/luJ @7miDMתk~,&IMx mo/-'tG[˙gxѠQ_3hoAuR{7Kz:;dL7UZ7kgiD[[2a0at8   pH>84Z~\]uPkȪO8uO63j“CVJxSieuیqI).TQT>&L i10mYp. (e3ªecib}'Y9s5M3d0Ƨ\ K>mgԈ@_c]?>SF5c3^D?:%kT8ts#KV}ϡڊw7O|z+C8Tg28ڧS6]nd,r+EÑR@>ݹknɞ=ݮ NzӦKk6>[&   \_~.dʔ>m+ Y7l" ؘu+d n$<)ObEz1/CLkfr   H}>te=13>ӭԨq sƻ,?vVEї~ӝdϞ9yh Eϣwڀi]w͗BnvH?nϽ.~{Lco~)nZwL8\&{6m]뭗LdժuR`~*ۼ!M=(bf9fԈ6ے![5Y3~zevǙ>}=yѿm{BWF|"  _@[L`CLד/˗/)h 5~y=v l߃48^zk&mݡH.4fdC%?1:9s&2ytm򉈝;i8~ށJ]6C~m|6"!1ujWf,Qw& [n")'Ϸ*qhiY]]4i;v9y?7o`_QՇM%s>'ֻr劢|c_ЦMK[?'?   "-T4/͛=-u07ϥ.lܸ{hv(>}?ׯߛ1/\cm$ҧeKIti-Qi;tz6ɛ7jjߤߙX|1sӥ39S:f [M.7iN(X]v ?xU'"D_DqRzwҦQzNV7^A4㐐@@@/.f܍/[lj/Ƀ)my0""Ϣρ}u;ٖZ>C.ȡ8AߛLţ]<46bW3o>emڣM7۾c7,^֨XڕE,;{-' 8+lBuaX nӯ*/O*ǟ4C!s r8R|"  ?lpJV2u <3i%ݗYXaE?/ub'<_o7=tR p^+v;OUd}p9,`~4i3!b܅ެE{}d⍀9fZ^8\{\|ML[F`ٙ_[m^Ig<-mbki_x2a6/n8oΡ23h}ߞŊϒ:GGan~Q_r%imV,۾3v'98ܛ={6LJMavaq5`4pDtNcM [Jb%Xv4}62?枟bGir~F]1UŬOVwyJr*PѶѠĈcX"):8t Q[s~T0D:m~jla   8ρZJG3osn]we'|F#fBמfpz"h7_YKN)au9yv3l}guOWdd[uOeֵɋAqQiKFk wrb:>i͝;颟'OjSK9ghCə+Ε/6!:bNN޳GN8e( iz;0\9bZΙ3{xdg   2:%T[}~^˶jBHlBϙkjz5`~Qȗ7}y **Jr@ϵgΜ5aK cW_nz[6<#:!ƎQ}! m&I(YRehgO tq/   @ L':-^R/;XW\I/tPJ]5E@@@ Pڒ_h|g H#Zr\"   Q#=$1e7x%%!  2@_2du92    p9.U@@@JBgФsܿ1A\   kKzf@@@@ u+\WG@@@ ' ;@@@@ rݢ    A8i؁   $@#uE@@@8rI@@@%t+   )@#Nv    @( E]@@@@ NqҰ@@@BI G(-   q 䈓    J9BnQW@@@S d6lwźQ'D;w.>6    @ Gtttthlܰ,];|(o{jX5c?RF@@@.*A߫_/E$f̄̕@@@@D()oT[~<]&*M7 Xʗ KLnPۖ6]X}\Z^SX&CN8)ԓV70O1埙seRj%itW]r[ֻo}(7ZE֬Z/۷?zSn.c(sg/yrټmm%iҤ9.0u"֒1'ٳgwIYeطdRN5й /?b˭P&[e3]߽k7AL֗n"C ̺& *Z<ģr$}S9sݿjZ26|,[#jԺ͞)ڥfEŧߘD%SywTk۪#ɜ[&=^|k~9v4J\Rpɓ7T__F(&-Z7nOj+QKW{6)Y 7 <ЦԮwL5QڲxC@@@ B%j?e_o=c5(ů-f\.wδhȞ#_~g7-tС21r߃ͥiݠhBdúMR\)M[k|=mAE I{ϿlJӴq[lͶ)O<#UŦ[v[TaMyUnw1:qԪ[@!cO@@@5j [oQK~1}y a일gEdh:g>5fF=}˒%wU}ɓr-E&1SDDߦ ʩS6 |?~^6t}Xt\'Ffb1NjԤiZ+_J:Y(g7   @ȵpt<^ M/^2O9zlSw[ϛ/7®{S.7L5oz`Yl>吏IH/%iC[,_v-BBW ٦6 c|Γ{-UF8ƴD!UIE~<7{%"Mh8'   @*ɖz4EtR8u@MBgg:܄C>@@@@Gr.3gcu\SR$   \!ْ#Vj""!   @ @@@pr8|"   @H G@@@@ H   !-@#oG@@@G #'   A}T@@@    9BQy@@@pr8|"   @H G@@@@ H   !-@#oG@@@G #'   A}T@@@    9BQy@@@pr8|"   @H D\ڻnr\w+ WlG@@@QDpG%{LV/P"ж72؎   -vW-8r^     0sH9\ \^F@@@@Bc A r$$A@@@+CP @@@@` $    U qU99   K G$)@@@A@@@@ X*r@@@"qh. ԓ"\.aOrUAI@@@ ЈU$DN>)!6mZRzi)[>:]%9  G+[2g|-EEM*-9"  @0sٳgm }jԠ@@(%p~7 rRΥ &L8xi8 +uĩK;@@BVbCQT"p5~G rd{'NkquIUt-^,Ex(^R!   "]%EƤO>w"ڰA͛X\G>$Uݪg?kq׮-. ,sp  WR@xח)fL#-Z&zs>+HJs/=ey!ߏF j˧#*OH>!pֹC-E˲dժ^OlRRdq'[ܶm2fu r$ۊ`!zå-44C%*ʴ&=6oɛmf>?%Dž  ݞZ~"u\cKiΟϳ~p@@HvŊk.Ex{\dL0_^[ZIS۵kJNI$S rXt0HmcCl$k,rۭ7JmLcǟ E&ZrEeڴR|i!jPY|nL~==c|LO\rs̞WժKVde2j8[Fr? y9!4bį2iʟvoE 6iZ6T\id{)V]?m&3gΖLYYv1y>vgb4xSDv߅0O|pt[n#a&@DNqW$ 5qȑ#̖.5"#EtѸpyun08k q74_"kΜ ` @@ ^޴N.7l\9sH*H3fSm7IܹrmZzpVZTƙ[[o*=(2|w>GMpuuvSd՚uRrMmk,[> g]\$_<edODk'ͣǢY }LOpqBɴpi#$l15sd"˶k@֚:p:~Nq<(? wC3Hi֬vR0@HQO/5@@}^xjƌ52e}`rٶ},2'}~9{BK9I4y)]ON+ΗOEt[]%Q`ذagI>}+y.sv_׮]ʅ0_eڠYҸɃӡ2e_N8\ch@{Uб.9omP1M̥_s] }n:hCu}'鴻W>ԯxVN)nd zѤzhPC_%m?NC[w6nmb3pzI?̠r~8=OtScgLEmoW@c$$L\R7,jegG?D G{18t9U1:n @@\L`O G5j 4p@~f|}OimEᛚcGzZkAX 6I] ~_rj?mriiͺ Nri}I[f+f9ӂ\9ՠO뗽Edy~z'OLAn7Zb& hY6÷m]~9I[hҺNGQ:}S7^~5o/УGiڴ fhPIN";z=!BC?8tMG"~$_ bh6Unt?UypsT2ͬ4iN2pR^ ە$!;y]L|Fk4ի[öЖI6foWi(;[ҥ+)si^I뚨-(ޱ[j Ȓ@bݏ,  G] ݺJ/o 碣T:Coe3ݢ̓-uߎ}\^o55_vot ǿҶM+` N51! 1]?ՆtY<ᔣm~u{$"b2Ӱ29M'MjfmѤS=Y_ҚBФe ~UРƓO>i_)%!גgr!"xi3-ku3&h;`O^lSƎ4C4]X[ϛс3x}9: : 3qs3ͮt)i30`w#t撋yE'y@_35=jAPbum-ec3>i@GIM_gv!]]fĔB%.EHx/d3"i Y%i"sR拚,OhtUInA'.v~fm ohZ}(*PFƈh[zNC)n5vT7+ݟfZ\m*9o66 &3i-W^c*bfa@@'P};X'#  >#1SԾ3$c|t U 9j}sr?W^`F̜`\P0  !(ЬiCW|iƷ;qKfL⮋ Jy!=hʻI{Em   @J ȑR$ׁ   @* ȑ|@@BUq$M4t\=wt~GF9Rs!  @PtFrJ2}R@GP)  jɸx[x R4  \ADgKl޼\F&Of_W< N{&H*E@zG *(D""ҥ)*ER[;r$ oϳo @<ڋC'wSGou'ǭ~   $~f"`)S<\_]R;nr){;XnNVs?@@HGOtIX")/]$AX@>Or ȑ  xX99*`NZ^XY@E lh*srB#e;@@HzCKP`tHmy./09B@@ )Z 6Nh)DGo 37A@@@-@f s}@@@%9n 37A@@@-@f s}@@@%9n 37A@@@-A]2   $@BbIYcmV6~h tb:@@@RGo:S4a"AAWHLل<,e@@@@L̇$$FAeFY$tcJB*NLY9|#   @'Ll!Yzr8mpB+AA7   d$x&ו#   nr!@@@|I /uE@@@9Ґ   $@×Z"   [ni@@@@_ KE]@@@@A4d    / ֢    V [2@@@@rRkQW@@@p+@-     K9|+    ᖆ @@@%Z@@@ pKC   A_j-   nr!@@@|I /uE@@@9Ґ   $@×Z"   [ni@@@@_ KE]@@@@A4WƦni@@@RAפ7Ξ='υ%&111rҥ    DPN8~X/Z1s:~Ğw#>='sǮݘ3c-Mf !/>3X:!w}^~ܸ~t ː   @R D#FbNZ5Oْ]OWo]s%hPFek7€ARRYYdL3AJ-!v{uqm@@@T З '}*Ϟ>_gCեi272iwʫߒ KXc\ԩ_S&O&N;}?{jTm-{vuKH@`U$Zo5`p.t5uZUeŲҤE:l*rE  o+ΞʕRe^zkOƎP6%Z6S=6HlYI^W]$;'OYDR ?]MPPDFFJiO>)a޺5]92b1wKRAmԭ69|ʕC'qӎ;G˒VHz>)ЙO̵qɓK4+  @@@ٷ}y3#?L@-^TV._-iL `|h,ϐ^f__u=g/巟CGm`>/ѣoo-e th dޜ/Us~iSfTSٗwl,]ܾZ͛YuMwɸѓmC} zeT緣^Ǐ.\(ɒ5ݳ_h}O=*Q&hX̕}{+-(9y┽   O9K)? ˑ3n0:6ѧO=?Q^ziip{[?-?d_u_|6wԼG@icdA++L0:  Clb\xUQ=4mۺC_csJ54Xp55;Z6I"Ly~#>"MO a:/Ǥ>1LْҲMT|l0"*y^+UUw5zNemd 8R:5=WLjڠV 0A%Ѥ   )p /7Оo Z",@HN ͖=2GNoa-ݡ/YdG k#|tٻKm}Aaẇzv *qYɞ#c~ר]2ѡ6:B)VHN:#[W]eG'4u$GtKvM/':ugC{mJJuli~KOM>*t^EtRC\4imM_Mf#i@ȑ ]P~Cd.!Ae0 f@@@no rJ;b?~K3dE_3!*/W|Nƣ]yۃfPG-Z7SW|%0`IHHَ̙3:9KU–9<4\hh{/")(8߮C5ҧOgi`H{Rܭ|ZĦL)fȬ̳<ص顲8+=4;mG-JZ? FufkN#kZ] #kV9VH\   p :ƫ߾v5jU+`{\@hMClO E0{MȎ˵΍@3':{jw_wTUf C^3f)`^ꋼNʰI'/Ք9s&nkO מΑ8R<9l/ >hslD3EJέ섦ZowC{*\@ҤM#[L:f$3 ฻Xgi>I:OE0_N5׉^5tU'   |"'חX]%5i3j':N$n2Np97$<,v؄y隞plkǰ%JǮmY^O<$!fxIQdZ`v;1j'Ѥգg'۬VrԬ} ͻWӬJf.G>6[7=lRKƢm;l2U˛ Z˂   )W/444F_ /߮Jn_z+IdN'+_\\]Sk#""K-nW,DGdΞ]UFIsW@ʍN&1Gvdj|ڣAi;F7zM7H ]On;<οb^&]UUWQIH:QfdT@@@  @@@@r\Qa@@@K G\*C@@@ sMF@@@@ .qp @@@|N Wjs.5ml}\+զ   x`)_nص-^$ٞ'xn$?n   {klDŽwF I@O Wp@@@A@>O9t @@@_ 9}"A/GL @@@P| L@@@@r'D>   Ah&*    O|@@@ >LT@@@     9|$   '@#>!@@@@'Rlnd/e}!$   x&b>ʌ03!F@@@HA?5>T@@@<HA… Z{    3).Ѿ]+8?4E@@@R\@|(111rt8@@@|F 9 zsILCPQ@@@L 9coJL=l@@@P};w.UVH    Rlرrg2qߊ"υ   .)6%wyT6@@@@ % *)x6@@@^ Q?ҺU339zLJ*!NI7ͨOlYKdyҡ}kYjc֛ bE ˟J{ $B@@9\ȻuhVc]H=q3Shi׶ llA}ބ9V$/_ֻ%l󙧟&˙3 ;)R7'[   9\'Y8z\咓<7>cf}&`#M \(MO9앓'OɅ C +@@@M p'Oʆ؜tiʢ3$00Ha,yyѮܢ0>2SO;FfLP%Ut\2 e)2}\)qg1櫒#{v,-OxQ΄t>.Օuzj{#ʦM[\n?p}2œjβ-[4!wd`{lh/O=o,6ɠ_2ϑJBBeȡ6#ҦUs1{QcI{ڲZ;Z=Lʕ-cQl͖}٧I,s星,+1=N ?ҥKgvf&؋   p0KS_I~_/-_is""#BxJ\9K}Μ9C6H႒%K&{s%sfyGW Ai Ӄ!88XbL ???ѹ$4 68V phCW}yp.RHayݞ:m1rig~O>fx_odHnZh r CWJ*i/gϞ'>+5kTwR%tuL> g7Ur!u6stNÇ1"LD2hwy7J.:\EP2K2'/:EXhdΜ%㕗Y^~eMbN,    Г#FӉG5Ixc;= SY~:N*vv2yϟCOڵmehs)b$6RѣҢYciӺy,@ |8qҖID"i&k,ѤmCWBK/Xnk0&Oܢ=s挴oRejUZ5'%KG*U*/ϛ7/Vɯo0zOcjР =ګZ QxQswF$4"  _hhhh&ok\u6;$s*>kٝ+ks(ۼ~wExa3m#x$ Fԩlɱc'DufkơGJ}}6 DDFH^^cޟ ̏^T3Yny/xoH@@@+osNFucd^ޒtDUNu5иURvΊ=űd@RN¹o[wD@~Kuў%s>_ܿцNe%!  9nvɧ9zYZw]>UlVa, yNإzR2   /@0>R|<   @ =%i@@@@.@ÅufҦUs$kGxf,*%I]B 8WKIk})<z\tդH^\@@%.խKGAi׶tKNfۥd/dԈǍG&iӦ1K`M:If䡺wfir,{I8hO\˵gKredf"ˮY = @@@$@å1nj(~'Oʆ8stXȻޔX_)i|}v?q̛-쀾@}I:DEE Ԫ6/@IDAT(Q\dϖUbbD.\Hiժѣl]灞+e?7?7%EL#?qBra _~RZҦus{];JÆd͚e̹XR%ߵjU+>#G2AC51zd=h u^Zϼ(%i}>|Dl&&Ls;{=2{NRv^z'ŊzȥK첷;=,: X"ZDFj.ˬZ>tLiղdΜIv+]O34 }tֵpBgΜ&8ߒ|I|   +p77ڗs+#rgv7[֬%ϑe^{MԩӲbz@>X˗cDC! p<| ɑ=;vܼHt9{fܵ5-:C_5Mvﱁk8ow^سw|gfzҤImsT\A׿kYyKdE"|""#ohvaaazsn !  Axhĝ%""R5h.{Ug߰pA+ړCS_=.xQ{Swy3?,N8)unʎwOi/K6潍dXڗx1skώJ~v.c \4L4ko^8VMYt-?ҭݾL)ʙPYxr΍?~fkO1f-n۵6Cz7AF|7mkۼy;}W(|Hڴ*65Y|   $Uq̚5Qq14sUg.\(3s{$ X[7#iؠIQ;{T #5NR qoC)4b9'"=,RJ%=4Hhz$8Ҿlso|w߫Wlo$ d/*9U${6@3dR~=Wl4z#Mm "Q762!1BLhz$&iM+]|I̹E@@n'PoNij2ANI̙͜PLf]cÆ?nZ)cFY|+[F*/+?X[qNA;?lW,)YN{O?f_cWj!+jV3CEa6fuvXy;WLjQ{-o&?c5_{3d0OLpw'mٳwK*qvzv^W,:gd4ǏӧHI31Eq:N0yg&s/xwuFMW<;۹G>:ȴM(QCRL@Js-"c>[4S #[T\і@>6 JT}ۖvX]-!!  -@#n7bh]rH6_ӯ^:j:x|rAФO?iv\5K1.q: Qsn.XH+ zsnh|^# E1@9?$@@@ro3%.ggL}ono3lyV@@@ xo @@@@'gkUU>J*!N٦^;NZث̺&.G@@@rB.vJ'Ybj'I5fյwnZv ȯub@@@`Kۄ=+sqBGKggSJ7/0@u(yrŊ{ߔ %U   7U.cNUN<)6as+"N-*%SC o,]Bڴj.>fˎ3N#3g͋+ceRb:4i   /0\%#+ WbWh'w6;<"YlqfK ,@C?f7o*Zv}7ژ>s-ۚu7*;tjzhrS΄}LJ.)RlٺM6   "@#-ѿҦus)RDDDa$IjUEWO^=2zxq)ɓ'ed̘9W~7ȗ71YU_6ncQmϑժݦǕ8ލ>N`hzz< К&KT.]qչ:OGԩ'q ;   -pD@IQPA3Ah{fv-pv[{94jXOJ-7^ҨQ}y}[rR4kHBBBdƬ}z^mU-RDm~   7 Г#xARB9[j#7_gp޾}u=7y]   ^%@Oxc_j'߮X)7['F   (@#V!CB@@@`wC@@@ ГuffO?9rrN}leIV{?"oB y3qW,Kks!@@@nAn]:ڽ.AU*vzZ9qH,m-=ht ؒ%%KxBv:w 9sʕP"ȡy%k,y2x0\ e@@@HAгgmrbKNl\(M\!ҧ.o\2lDt5ǎ.{뮝]Z@;9jtx!{7^Z5IPP\n_0cKITT ddHAmKz ɠ_TRIHH9+:¹7?i\Hw)Vwe5{Z3)W.#ƌ>:q⤴i՞31~&Ya\?uxnz5+'is?_(#GysI…DUk<   $RG]w3ž}l/Gk& M2e??cK|V3?ƞvw{wS4@ic:bӤI-AAa)W73֩efHѡ+Jt\1+JppnlD*V[T M@Eӎ;meXl~,j:|D~eynhvrWRҺe~[޹3vw|    T9̖-˛GΟ?o{;t۞q7ǧr^A7<\ӬYDDڶnahP"c;mɾl^TzUCFF&iTPg?2ѧ&x׹hv[n{ސ޵c}({9di~:N/(9r|c5!I4.]dc42c@@@$ b ws3<$%q%31&:)88~Vx ɕ+|bsxNn':dDSHH3TQ'Sw)27gfǻ=nGvhWK|'h@DSewBNJB@@@ )#aaEeO$KLWqf_ZˬJ?L vC;4DԱH4n(+LCkjִەG6IҧO',畜9rHvxҢ7O[!١4:φ04j(Z;b|x |/{Z)l{W|qlÞχ|hJce/9C| ֮!;=`$ofR׋x/@@@@(put49yɓ>cȅ֭lO򦷂sC16i$>m5(zNͥbŻ?:om''ռ,`bCXmgu=#ڶ 8 BsMG1k `Y칳e6G,Y;d?&|mϧϯMlV!2K=a^NBN     ўu<}}՗0ÎI2ⓚݹḦ1wێNܭ<+g=s>}F:v~1:wǙ3q k$aa]U\;AΝΟqʐco]]nh&JI#Elu+$:E@@~/WOJ[7Fm: ^; fpH$}Vv T FGG':i:tU޽gOu.1;s$6?wh׀K"nKQ@@@`Nx-lJ;$?\aӿ>5wB &]   @J ȑ =+L3ɓO>JQ@@@H*Ie@@@@ yr$?wG@@@$HqAZ_ Jq@@@Xj1J:P@@@@ 9~[99h޼yK    / 1=94.DO    @ rlܴY._^= GD@@@䈌KO*H+#   m "%AAA%ҳw۠yD@@@HA9ۖ׵0   &)2QpA|, @@@nCz]jת.QQѲS<    F 9>ls|R wF@@@&;w!!   %"丽E@@@ @@@H9RD3    @    "rf!@@@@'!   @rD|Ż}"   $;O9:vm/ (   /\'EwF իH)@@@7wv}wwJuW^<0Q@@@nq   S@@@@{rxO[P@@@@ x   #@{ڂ    9x~n[If擁   )_g_dϞU.],lmv[o%KѢF@@@Lth%wU6ә3Ҹv;m#2nɐ!T|r;w˾eWI,r]-[nOpRfU9q┬2Yf? +_#f/W=5+l#v9kTPVΝ;o/_zr_'O%KWoWKp{ƍKRw|O^@@@nC r#ǜ Aݞ &pرA={a'k'l^ɒm/ ~r1YcH#7!O"d)2}l{}.)ǎ_~]g?Fr.eJ&ʕ?H~8w>L_lj''   n>/ If1OG=3 @,\ pheˬm{o{>ٲuϔ) hPf1yUOpLxhDӜ9l x>zߚwlj'cdႩ'wN{hr/,3iݪm@@@Azrhڤ*{>u6 2b[MJ ^yˮ'EӦ M릒*U|Æuԕ#[7#'Ȟ:4k fa;w_b9ɛ7=^L  z~D. W[ra)z`o   4=姯eyv mOhӋmh 3@G >}:ɑ=3Uўt H箏L/c`&:uj/4iRK`` tJng#~z=???+R=6O.s.6zȁܚ/@@@n}5:Z;v\k 'yoBZLYB~WټO޵2lycmk}dN2_CS<$ߕ:]{qveKv-[J[@ƌb{y߮Xd_=G@@@ pH>s72ԯWN 1] 5VtP ,Z𩄞9+M7m@tGPc %yn뤢7'LYeE߭{c J"͸Ch4{)\N>ŋf_ACB@@@vٞX:ő~w; WA%KWy+KVt֎ ;Ew^,'q){gٕS`7Vj6_t5k|XR?w嘈ϟ/{l*;\ҬԨ^%ɞl"   p[<u<3'FYts,f;ew|8zvbʺ^C8! 2e6|ꤤIe&) \fYWǼB1JeӏA3Wsn^CG|dΜ5+A:F'21e˖U2ϐS@@@2㦳CzHuG*[8~6OYr6X5rCDkE == @@@@ \!=\b'$$H:UbO<   $@_M[j"CB@@@'5F@@@8rā!@@@=f@@@  @@@@r^Qc@@@C G(B@@@ {mF@@@@ qp@@@|O 5F@@@8rā!@@@=f@@@  @@@@r^Qc@@@C G(B@@@ {mF@@@@ $ rq !    $$-?O>&r tb:@@@RGo:S4a"AAWHLل<,e@@@@L̇$$FAeFY$tcJB*NLY9|#   @'Ll!Yzr8mpB+AA7   d$x&ו#   nr!@@@|I /uE@@@9Ґ   $@×Z"   [ni@@@@_ KE]@@@@A4d    / ֢    V [2@@@@rRkQW@@@p+@-     K9|+    ᖆ @@@%Z@@@ pKC   A_j-   nr!@@@|I /uE@@@9Ґ   $@×Z"   [ni@@@@_ KE]@@@@A4d    / ֢    V [2@@@@rRkQW@@@p+@-     K9|+    ᖆ @@@%@_Sk ! 擼rK`gq =+3g,Y372"R%88(Qs9F.^(s)  x_vJOmSNu]= N\sJ\ٯ˿ŋQρC9_W]>\Zm*~~~W݌mϖw%ʘ CoxKxɞ3TYEn.}EZz|sD@@Qﱁj#Re._G{wv[^C ~܉f>X4kgu$}rj9qtT6m"&khΌ#MtLH=rTflv(!}r~O?eƼNf/X;nh{hҶhQgS}}ɕ'M֖F4l K-S msvN0 V_4_ˍ~wԨ]5Ŷ@@|^`yw gٻ Rh‘i_1wW%{v퓊GHZU_~ǚC:vAzUt G*\7tȅN¢kLiMƿ- &Գ'~f~*R@&|eЃ"!  (PXd\/}o6Lhв/1X65G ;ZdD/2YgrU44V{n[NTUG;%hm&HE{_vSp43Ts@:z!8ʦo)_vnO=P32F7(#Gk_"M-M!_jX $GN;&۩X%q\Qzh!1:ajQ؉c[ʱ,Wۃ@@!I]5EFF:@0Ok.(x1u.2fK yLlRO Wə+)tLRٜ|)NJDД4i8u9sg}2E4C8NФO<9Y){ݚ 6pQ?K/zo0]W{x%_uNFMۻ83Sa{*$ZoZ|ɒ5K,kHV*J;Y2~}vg1sy~>>?y9tZ4kCKeMpD 3lE?4G&wm Kzّb%b6;S,\8d 58ر}ݗ@>ԯ9jփ   @W%Ť{&Onrb; n#OZ`ϯ6^iV@"Q|i;EQ*&&ujbLg`M3rʯ$ KЗv}!`RsJ1%/<zaz65bKj0E&rkZLg7//W2P4걇MZpsEԪsv3cEBOksKjԼNMig^[C-Nq"xVI:Hs\nb@@HO@cu(JlŅ˃-ɗs#Hܹ?|ptI@8A%CgС#+MB n }LO2~dG;fu:7p{}YjX'NdCi39XoM:d佻i#ݱk[|_m })_Ϭl8khE0?Ef؀$oXR)#~UHa2i=EꙈ5thLߞLOÞ/.M}t:ŻIvpp簎  d@nsE5ϤEߓ}ӏ䉟Y*4'"wƪ]w7'J@9Z_gQm L6q\Qe7l pwsA}C_#RLWhdS6ufG?Z4!S.Jl+T;zɣq 6EOZml)СRÓI)ilЙQi\qDRkC7Ibbx7yK= ff2kd9hrNp1N8ME?@@@ `R6ŶfEZnyYҮcA}'b&p;+(***Q󃼗R-FL[|oy^OĄDb:,zNYzI /U“d<=uNZC_wH3g˺wg;*&   piGi˚2 >.M .֖kߑ:a5'OFs3<ѥ'LC2b(iݢ }uA?ʫGc.kVsLW[Zt:z@@@ hcgS^gdMYzy}:llnV;w)O%_-}v( DC#Ov vlk1d@,k\+/zU~g{\ }KjԼN !9y=M}u8 D@@<vla-ʖ[Pr5Œ͛JU$44\;5\Bn1լ]#zB[.sh|%)W=tY5r v\կn.W(~%ԭ-~4WֻYX {^JdOoWIyߊu@@@M`^S-V0ϓ'ݷ-Rjv=1!Q_"# 3=I46nn~1{$&& ǔI3{nj9#۴nj]wyɖv]ǎ(s}:Xh} GZ= H^ɑ7,$˄{j =J)[JZX/_ɛGvl    -3[4S1b qqoȵ+i?wߜ i {ucQ#DG>,N>&]8{GOemҴyc<cޞh9|v0R htO]2yAʠ~M=Үc)^@NNy{nDO `qԷͱ4K*E/]BNDP *}X|JQ@@@7 Jk+^^ 6Kv<Z*ѣ䓩d=X /}{Krtl߶Ӯk/&j\Gh c&ȭIw}IF$ژ>m}O6@>=sMjj/vW@9CLW_+[:hRi˻h~kw'x=@8@@@h/ Pɕ9|ulaIT\Af|e=-mױn J 2V{齞ηDGGˣdfzS8/9W8cK{vrn>)f=;LER@@@S1wRH!)ZHۗw$$$ĥ;%,)WL߿wdvΦK4 zr\NV)P0ID?G@@@y%Wю,0jÅܗ 9    zD4@@@.Dr!?sЩ4SvfKA@@@ rj1o``V'dE[fȈ!drKڞqq27d̺4ư   pE B'dy4jR_ ,۶fɐ#}ǥտBI7e_184 2pHo)F@@6FM:8zt0iߠ4j\_zv $+%J?xqbg!}4>@@@Iģۜ<-sg͗B Jm<eʕ8t{oݞV0:֔9C=YA@@@9{ؾ˶f$W\];OLyMcԺFyqs8    /Kޏ=x/{Ԇ8ʗ?L#YWˤdνvW\\Oۇu@@@ Г~s Nhɕ+^NbNHX0g.5TmFd@@@@_9%^Sj{Czt֔#%Ó':ⰾw@7qSeǶ/>@@@K GvI>˄,fhjի$;&vbW:c {KΞMv   dAw+"|΂Zwϟ2󓹶F;R[m=S&MwvD@@@/d oxV1反RMR`~if^9 |^#y;Ⱥٟ~):    zrCԙU}8&]{yAʔI3H2zH<- NJ…9CaoKLi5    AQQQAAA-KǼ%66Vш 2vw=nrޗŜVX3f9s欔+_FȗE   @6 \̮Ylȴplz nMܹJJnn"mC@@@ C dx'     Ak@@@@G>q   K A@@@re    .z@@@| #!   ry@@@Q p\    Ak@@@@G>q   K A@@@re    .z@@@| #!   ry@@@Q p\    Ak@@@@G>q   K A@@@re    .z@@@| #!   ry@@@Q p\    Ak@@@@G>q   K A@@@re    .z@@@| #!   ry@@@Q p\    Ak@@@@G, r .C@@@C9f38DbcnG@@@@ 4Q#Kz'Q3YYyx6@@@@VC49 tdIC7 G֖VCё3   #=8>LٻJUfsCz%(***鉡':<ǩ<11Q%66V< 3,N؄8甤Ť Gr;@@@BtG|%gΜ#Gpb))$ȡkC? g-zLKZ S|]̹).e@@@Ph jGGdПUiT29Noy1W@@@@ 4&18 ,ȡTMFZd2j7Ŝ}    N\Yf4̹t2}ǽ/\XG@@@+O W@@@T G>8   r$` @@@T G>8   j8IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/deprecated.png000066400000000000000000001266531515660254400233400ustar00rootroot00000000000000PNG  IHDRfQ aiCCPICC ProfileHWXS?wd(2aE)JH #Ƅ ⦖*XhUĢ HXgQpǁJPNo<<=9s"EbT{JzP2B }{%#X)Ʉ8[B ^&+ C"K 6V!ƹZJxF'9q3d@ba.xL$o qP"A ™jbg/xĜ| wk9\?[Saj8#dDf5A'ˎWRT*:EZx1<@9y@ig"(@.wd"M3#$P H #vaY1(#Rhf51ą *l$Z*x%E\ -BIN$FÉH nx,|B9p: ݄[3e/rH]ٟW;B>xC8 77C`d(Voೞ(2JqҒ=U̗yYǘ/5! v;Ś;5ccj<ipDM>Џ_N*==z=>@Hx3s\I b6_&;}Mdi߲ [~-s{uBX+|epy_BAA2Ha%p=+l0,& { hGI .k6\?= $03q@O#H,#YH."CT<+YlB#uȏ$rDn!^/=4Dq(1h2: EgtZ֢F$zv `z 1 ,S` O_>Nę8wk8O,|߄v ~? !'L!f U]Äp7^Dщwc:18J$>$H$3)OH复}.R-YlM$G32r|E~BP(x2BD R N j25ZMmޡӳכ'[Ww@}w4#+Gˤh+hi[t:ݑJϠWoLX!b,d0]}}tR*C (<#7  5S{ 絆cQF)"EFFGGD͍j&DD u~Ol$lymN8i;qqxϏ_7)aVϓ&L~8>q^$fҌIÒW&NqNQf֥I O[=eܔS.Kӛ3H2FL]?''<4i%M7^0 YiY{>l~~!OAL*Z'׈y6W"IyMyy*H+_H.*<"3gZ,)w˻gZ?_إDӔE~QZu8هJ Kd%Y6Iids¹ml-w>wȂm .Yس(jў-([SꫴZX.YQ_ח37 fR|ti2e}U\㿭vhEΊ+":d5kJ<\;im:uXʻjՆWmIZMXm~Ekkֆm*NQkkvwx3u92Un={Z]Y֫{eC WT~1cj͇+9M#yϻ9frlq%LJNh=mFSSN]mq:_"9u{٠G;rsƋ>ߎK~/_ny++\_p-Z7od)V6x{wYܫwv~⃤ >{|gc'Oz>={H?|lPА\hd4'v@Oyj|BT  5 @u^+ ;BCVՓC5:Rxyj}vh%>* }wTwM5;o5b|_Y_@< eXIfMM*>F(iNxfASCIIScreenshotn- pHYs%%IR$iTXtXML:com.adobe.xmp 1536 Screenshot 358 OuiDOT(C2@IDATx u]-!([ZTZyڤB, zmYB(yjQ(,}rgS3wfΜsϽ{9}ҙ ^M„     %EQA@@@@@@ A@@@@@@ "rI           xS$@@@@@x@@@@@@\     <     D@T. @@@@@@@@@@"P o*          (@7KB@@@@@g@@@@@ %!     @3     @ DM@@@@@ @@@@@@ "rI           xS$@@@@@x@@@@@@\     <     D@T. @@@@@@@@@@"P o*          (@7KB@@@@@g@@@@@ %!     @3     @ DM@@@@@ @@@@@@ "rI           xS$@@@@@x@@@@@@\     <     D@T. @@@@@@@@@@"P o*          (@7KB@@@@@g@@@@@ %!     @3     @ DM@@@@@ @@@@@@ "rI           xS$@@@@@rHMM=ILLP={NS=.g%>>^$&y UW]&eJ O:-,Yk9     @~ ȅ;dGk]噞 E6ɜyew?z=>Vɭ{icZ^׳@@@@/p'#Y). W~F^z%$⪙!    T nL8'NM 2| ij-sLU,o)a@@@@]\ a"0߯'dr{̊YK*:JYD@@@@rO l!h۱>?ODi    @x?~\ԟʕ+w)ŋ%ȅjIUk)I))Һe|Q\j`w8#@@@@J*z0sLi۶ʹ&!!Aڵk7ر }N EkԿ^ͤs6^G H\    Po߫ƍ'=z0swРA2p@*WIfrҴEW0mTZH^AwkC@@@[ի9q)_'yϞ='߬A%hIȐreHW^*QQQނ-[w$GK||K2LR[KKr<,ꂹoH x]b߾Ӧ_d}ri9~kYT Yu Su*Nw:tko+T=kxTҽlܴţܟ=$ki|m+m6{} YU5N0uQ7?H*1k~)>ԫ[ǟA@@@@ hxToxfU}_@Vo>jջ%, fvweg #    hν ^\DOi4ok#&~y '~|UTc_*oV fZcs߁ ԺNC98EXF@@@@ 8 h=ɍ&^$滬 -HIMNO ;UZYfL}p7X]{M h:=AAB    ApjՒkJ:n 6gΜ)m۶5 SҰɣRE~ /[sR|2h.3y|u {O~e`z7;f9x>xfs۷ʚ^Z].TQ_.z(7m,9~"GM԰Ͼ ]Ũn}=ɾe ;m)iii2d89w6ɶ?%54GZaʴn24@@@@@ O hϓԃX8a׻Ѳ쎝=;Y2Ữ jCժVicmŁvz`(@@@@+` hm^‑u_YJ2gޤ\k2|Z%gѮǞ?]ꚗ˄li pU&]yR֕r٥5Mn.Fg_HAXctb鐖&ong] |68tM݊YK*z] @@@@Ν;S\r~=Eˋfʴ2%… G,1KgЭNjƟ]֤Qܱ: `9 ;y}9ox~k]ryժ )?V+B     Od ijՋ셎'OI&:J3j_SSƏqr=QY1@nsMȓOu] i3ޒYsvݦLRt4uFצʒwW$     @ Xnz_mjyGgo9˔qY_jڻq\Rdg8%::ڶ.@6e,8(7~?XZFd,z ~_&1ӣQʅmR]h:tm^F     xQiڢs֭ڨ۴{JTP_k 7kr$_x)m4h} ݞl'-[o,~322B5׽m"C='FY6`ԱRZes@@@@ >UU5kKjTmt59dY[A^OHcm<][E9 i]vy#z_`ެ ra}3tmP^51"ˁSE^2@ګ +@@@@@` 8Dt~sQ_je(m\J0{LOR;:}re`[E ZkP,7٣JNG?؟Q0>R%..N/:x𰼵]Yr93_U?q4lmꚗc3G*ey\qy i@#)Z_"ד@@@@Ȧ ؐd\^:uZ+yArm<6i0_k̟,Y W]y:|TӺ|´RM*KqGip4h{8|H_WNp.     ..(uYp[vz/ `M=X>uw9 :YnuGw?Hƌb d' c@@@@Ȗ^\k?Vʟ]'q.;ZWav6ڏ[]f\L)cjDBhU RRRkD} t6KSf˲{ݬW@{<֫.~cFx ^aoU$rmשc+ ~@@@@@ ^3,-Q|BOs]-~W\ܬ}󩎮묅jPᱯM{W_*{c8$yX]h)]ʣ(HIMw[)gCMM$F5CXұ}k03ou t :BU':?"wnܺ6Ko8T=-8z\pAYꢺ (M?oտ8r@ֺTTp-WFz̜,]{>h.'N'OJjJjR@T|+Z$'f@@@@@/     @x l@@@@@K/&*!     ^u8[@@@@@ J     @x/@@@@@b     %@^E@@@@@/     @x l@@@@@K/&*!     ^u8[@@@@@ J     @x/@@@@@b     %@^E@@@@@/     @x l@@@@@K/&*!     ^u8[@@@@@ J     @x/@@@@@b     %@^E@@@@@/     @x l@@@@@K/&*!     ^u8[@@@@@ J     @x/@@@@@b     %_/i@@@@@ "t}.|y[8)@@@@@p ;y"     a@s      @Ѳc@@@@@B'q@FFF492     @ DEEյED[yX!N@@@@@ dD]ۼ5S     @ 泵<kve_@@@@@| XU=ly^vѠ~QF=|^s<@@@@@0ՙkraֆtQTk7e~@@@@@%`4:Fh}Yz庰 F|qh7~]^r,@@@@@0Bk4ߘ}u*p6Fޓ1P~4Z&j_d^@@@@@ DJ%2)RX _A@;,5SSS`?BM@@@@@ u*U5Qo5kB g²_Ub l('k %%E>^HD(iQ+Vʟ}     @. ;!ooHcg3D} РY30BuP(}~ ;G.=@@@@@.B)_k'Kd4/ԛ۟/%۟xlG     %zkPJWoGZUoϓg2A@@@@@P~,# ~w3o0Z     xdֆ}i7/U`t7ॻ ˻A@@@@@(0d}o}2 FW}@U@@@@@DW`@@^n50P]%%%Ɉϋ[<@@@@@rU{R (`vd`z>v2BwU     y.@~U`(/ؑ&S~@ g1'eFɕ*19 [!    X~`3 $~Sl /%-jJZ*    ?@ `)4p?T測@@@@ 63Pޚٰ)#P:    a/@- f6E | ,"   @/Џ7{+ C@@@@ lu ))~RQ @@@@ v랔xX(O.1Jkd:.@VBG  Y!   W O C#   @)! !>F@@@3 cSB(@B|    gPǦP @@@@ &M@94    @ @M"Bsh@@@@<  <6E !    y&@5@xl@Cnݗ䪫jmZJlllEs̗(w5S׿=)   ?M ;N^nZ FRD+%E DItHjș 9!ɖZ5r^aw7Q8mx|r:>.k@ɓ0/qrͤk6{■}nٛ˓=e?^-ժW5i\J,+X-Z, ̞={wmzFE XVp9Y`l$%'۪i_}N(WZxYbibvi̫#KkdMVnNU#=O:uE;@@@ w%/7-=KIy %95CJ[/+*w]u8eʗ7sĭ\_h9#.Iֺ#rMn {I}]=._ ! BߧLap2ॾr8Ϩ;vIMuo .(Y>\VTCg+He]\/2|'(u[ <$5Q[3VcձM6Q*T(o-2W}"ӦͲ5,3' wֿR}6?A&1|z;s6uW3r+'e67R"K _1|o+ZT{VT*hmjA}~r^[I~eFutQ9XIFz`Z7oBY s0mL_}uMV$P䤉S7Z/G2}Gnݛl,   .@!@xic* 0S-'#9QJպ H $|ԏmN}}n:odE7࿾Qod7AsfTk;~$K㭁\Fn.L:S}s+O<\6@5h7uSmԳW7G_~NF|5;~}=v?['Gn]{m 5tpZ9Zp;}WYwbFqAvۭ,aLہ^h+U >K8\[w>mtn2   o>> nbJF{u>8.' Χp\)5@dh=$m,cr6Y~%UVme \X@޶Won3w-ݬv]w_+5k^wӲDFucf̜,ʕ5~պy7l1Wj3M˴jc :示*1rG?g4T~ys}[ckeGɓ'Cmmg;Mԛ?mja]}P\_|1?\tхւyy]#E1&8j>|sܗZﶯ͜9GzoT_(P\mECuحUOdjcǍ:udޚS}{c^ md;Z7X_U}u=gn]3܎kk^m1e'Py$3Sa5\u3/۶**;|^Z4ƹ   ]Mk$ Z|8bNe{P`3~*ke6;zY~sfKe \X#g>c_oV .$j]%j_d(1b'lZ';5qU#sڹ=Ua ']WR9ۿ`6̟̝3ϊ.+Y -ɣ=l|/ԗƔ`7eŊM_xGW?3طq"  d-@^iB]qR=x13^ Pk]5`$W_G!y4`q Ov$ c,ޱc9|T9"i[ ҥJ(:yIo7)}|ɧ׌EW5 A_Sg#m:'LxUT:gФi#ԩ>%%E4ni. u\gbT1֩oޢzw>x,\\Bk uam| )י oVh jۊh_v)s@bG{^7U7ZjJr5.XTQI+w]ݮ ;'Lozܬg`FH꫃ S\^;3_c0L5ʂ   |\K'$+)J{'r WXw6&홻r68"KˬenϙBr.~NΪ}S(y}tyuR`A׌z#ͮ;|5=Lw[Ee=noWUw3_~*+@XΝӺG:$iM6˧FM̙wtqip{LywW,r3<$> 7G.dzĭc*T㞨I*dB@f;RIDAT@\ CriZ呛xi,\;s,BAu沚*uLܾ_^ւ(UfI'3y۷_:vb Xb24 V&ZSz5)P1g}l؛nTzj&ӗU%|YRd4wI^~թ:uֆ0޽6p蜜 /a֛RH.ߚPi?:#O<|9yFۥg>Cݦ ]paWH.$_v tֻ=%CoO~gϚg0R~J/c9[/dbHMeEu&_ ĮҾQƔ0W^@=꡶zS*S%Q}־ f7S塖w5Sٙ }zZ}堾vp 8L_Km)C@@.GAg@IDATֹ5Ŏ'qal6momo{!;L 350'cfڵk(gٙOlI_i9:f\thpB`W___o-P]QRakܦC]hak)[ww+ ə==wWz7ꅆV0,{̅/^D6-$PPM6u 9\yh7xy>os}#G̛={}s~;ğmzcy>F 7\ }~y]>}[qgWwF.\ꪫ=½gq{=i?v~q"]O>u5?u4}3nL9h>k~W_-m5!  (`qm3#j]nݢ`XlV!P1NQ2u3&DEiܴ2}k܊.MWn.NMI/P+Z:pu7o%>]vgşhn^ '\su7kln+ :+P^> z۲-6ӧhRvؑ_|q'O"rϚ@//0`;nȐw2-/;s>|&>^QY}? |׳;q]z}ƺ[c\o?=6I|$g=`K[o͝q2XrVZyI'to8< g6? k^1VZiEĽ*lvi(1W_oɽuT*cݩ|?ړw?z%E3J~Mh}%ߟmo~ +EǏ ?w.Z@@@ `hIdlML6X;yA[-7??;Z_]]ՄGrrxv =5 b'kg @op?:>&71y4cv_~}l2E]LQrv͟9c}Mic~tvN7Myg|M>Kox6XA⳾j-R׫ZxjrIIB͑jnKA(Y7t8a͑G:h(٢ qS:JhaFcӧw<%*tP ,%~?;5e=[[o%!&l}    (-ڊ@t `Oŝny8y7 IuWm7& ~s{ۯ_ ^h6eO h@o[wݵ=^zw@]#Fv5eG=* m dwo~{pW\s:t[}N}sns\sCũP=c6Yl _AkI79|P Q! &j5n;SO=1 >mm2jI%po&Njokom29 M+p9?h̎jfAko'C2_Y9c958طWoAV~y ,t='V ȫ~kI?3IIE%jYg-~7sT:nj׷_sa«>.JwםF[F_;ﲣO"гJMh/ߌ׮A3^zyCj i@@@HnoA h y3:_cٞn{!>0g~?޽l'@}pw)7w\z]kkdn`3tzwd{r=h5F,([%ag@{A5Ǎ֩se|-[b%J*6HkǼ+:= 'T j˿o_msg\=~idQ/ rjرqj/;uTdzݺuͻ[A׭mJh-WYe%_ONYj"Ck+gVK/O]]]xZwY>˨?!y4u2]PlY   м A /MYYt M}]M. W4ѳ@@?ܯ{>dCf~FL-7fϞN=D@h+y[M<aO?'ʜ5@[[!a珊(|3@@@ H IV՛ OÂƿ]sh@yG2[v/5]rŵ쵷6ĩnMQ*W@Su9Q^j_{@@@ZM@j* tjՏuYQ7rM U0+!Tߌ'~Hsq    @<6E%0ܽ>PtΊ+!I=NmPtvk @@@ZT@^* t믿~7+.\׽{fe(M@÷߰V:m `m@@@2ȀG "PEΒiԩj <(r    _ xl@:S@@@@$2\* ">F@@@h5IdcS(@@@@@Hd&M *k@@@@V @<6E$Ϯ@@@@ZM@J&p[()%еƹ_^[Ժ    @{ U2pn 2."Prj)[w/j]VB@@@@= p*xf86Ebv]zծŬ:    k._%: p1"_    t.eS,r2\6E 0     HdȕNء9w5 310F u;o[o.4S    o_2pBW__ϟ\Qal     @yaG{k׮OMMJϾU/^L˔@e\)@@@@@ a-X zgF%@`6E@@@@([?v֭ҥK\_oTkhoFպE/     @@Hy:%gp _V6:)     TV`as|u ? f-fFMȝUwܒ{S`1     @7}ztwڦNuڼP[?z L*Jk}T,P__レVx6:[(6     @V_%q[(Wjױ4x^-qFS@b@@@@@h1o}c:w|9|@ioI[vNZ.jhe}k#    dPf.r|5\ڹnݺE?am]%,vG> b@@@@@@%TsJ5St" ;{gbw.n"mŀ     @6.5-ջ ]7ޭoaO:v["6V"@Ӗ ֏&     %X _co0omkY~ iUM@aP?l;@@@@@B:8Lش-u ۚU@0̷ 8\/9      H&ƶP%&mA&?|     Z66ּ2|Ӷ.c@@@@@-k C 6O|uF@@@@@ @7?\""5F@@@@@{1     @g Y<     СHt!    tVs     Z@     @g Y<     СHt!    tVs     Z@     @g Y<     СHt!    tVs     Z@     @g Y<     СHt!    tVs     Z%-Zԡ/'     P̽vA2>!    %:/o~YW@@@@@:@m]&s8-綀1     }dp?NLٵ@зi$-K3     ii}q8m<\qJ|nhh` 73F@@@@@ M ̷]tVpʰs5&5X L6&2F@@@@hئ״m-Y*RA +&-oh*'ֿZ{AJ7E@@@@:bϏ&qlU Yjٓ     t2%͛[. Xd     PM9-{j۸Z٦p&_["    W@qj ~,ooL5"`~ [@}1G     ٳ}YBy.L,X ނ@L     @+ X@֭[ ". "X@@@@@*$2 5j>~m72)     @P{~ >Hdl     PqHoX'&7Tc@lf}3e8@@@@La 7 *Py#_= Pj={sn    7Xs%z) ( ЫWVc9    B@Xp4lP1P    HdLP?Å`SJ-X@@@@] p* p(s"f5@@@@ڌŝ˦/ X6"@\@@@@EHd%M *k@@@@V @<6E$Ϯ@@@@ZM@j* ">F@@@h5IdcS(@@@@@Hd&M *k@@@@V @<6E$Ϯ@@@@ZM@j* ">F@@@h5IdcS(@@@@@Hd&M@[H|ѧt+zM]׮](>v󯸯_omްAsA?mpH   @ K ^;شK.bGZSS잩XT@3gr/.>=w V=N7\âZ6^]<yG?3 tOqgZ   @ [0WcpB``bv!2NشgϞE]b6jakڮk<=zpݺuvV^]]]t$OǡCa޼yY6l)ǟxֽ;q;d maysO|[]u-n6snmy7v|76ٸ^]ʱ=}чs4ls;M}FG{#  --`qgWT+=b6ncI+آma$Z,%HFA{%e /FWyHŖ;wntX N{,Mr<0g/P&N=h׷oivNU0~;+rF^z+ç}xF{؂SMw_yc=h2'] ^[Y~:[{gugpӧpݻwwK- o'YgzL%.ՠ:-Y.i,z~v\]4V&*@@ `eX (MJM.WA ZʜݻtAa}7HL<«_pغk=w)'*:n.7oSI'MqW H5kuin2.<goO>ORz3fM6t ui>2]'|cc%m|e[g5ܮ;oJy]-swLݺ7S7_כn;.o#?Pb*LoBz1V;**ko3o|ƄI4uWMA  @g [@7-7fkno¡PB)$hLW+/}cFAK/2'ڊZ7sh Ju ;7rW|&{rܞ:M~'ܘ1 9U迟von;ZϟW^{=əﳛ[cٝ{yu _}1)'nIqNpxG1Ԁyo{䱧ٕkN~-eMX@nk ǟ~PH+1  C@hdy d &rXXs>i5蓵gf WJ( ߯_&]pi %T~ea"՜J2!aImoM8WZ ^=6tw{ƟjN8齨nj-kB|v9\l `3sY+nAȸ*NT3nxwMwgՖ}cwSWpOyMdg7xC7x@UIݻ0wmvܖ[lb:{ݗ_Uge8a>4A   X/}x-Ȫ1 \=8W'NlR: ^jZպF0OkGQeY 5V~MaRAM p7n\\FX^߾}}}U&Tю!\Aח4c<C~j$ }uQƎVX>6;V ޺:EYT(5jUC2-쁵 s:c=*mϊV?kqf}/tϊbϱ%k|s=Rǥ:Vϒx>ccR-էD_ϟR\wc0}A{!\%;Jod2%lSTW? A{E쵋[{Nϖ;<>l̺krf8@  R@naK4-wk~[n ̎jkj+o{NT_I]8e%PmZs%v|?`esJf(czA d`ԩբkZPYQS06˯Z}eNxՆ8ը]fpv4=e4v&6w踼O:l^vrNo2Vp[x~rBQǹ rҵawpf%}N6sfrF}SAv~Æ}^M?(0AǢ~5nrVNj~n5|IK X;n ]1~&M&OyпPWZ5QL?8K Z[;oII}cǹ -5g ݻ}>UkM*Dmq;ѵҊ+D͔\zEi j4swJ+.53E*6t[ecB> Y2 B/3xiwQ44[Gw]}Sp.>џY:aU'Ž$կ:ӧ“|?M'ScG4{nϽ{עb9o7Ch,\t-u]Ik]j@I)wJ3hwB{n'΅гNQ;& i @@\o~(Qт(X5Rl.DVO&dvdκ.eǏ UAC<,3 -Cۚ:& ǖɏp>Ӆ^. &]y9Ѓ3jP)/Gq[n9k\MI(Q6|ѧI[imϻZS2}އYeM'kͪJK(rjMƻ`uWKjN*lJgn%RJ8=ϿlL5ɡvW^i&*cO5}JyWRk6ّ͎,*jV'7ZV(Y ~PgKRǣuwp<1:N6.VV97:tc-X̽?_=huekoWOMl ";cw-WVb?QAnNA:jݧJz߽)v{+'Wk9ٿCP@(Q'_DM `nXeȊ>ANFL9}lTFt[ozMft>;3пDL+Z^{qBupGFM 5]{%R7py4_vn[O?'#-I2dJnVrw;>ɀ  P T$JIW&҂F }|_Kd 0eכ/%#.ʙ*˾|-&}K,\ǟ|^k*tD%$#RXXծG(J @*&V0Ɔ|4Q'Ȩ'_@/Vk2 [lQ|G8H0%t9fy6/jaW\}SQ+J y6֛LK)^P`"_RkoPDX?\N}BC9ϟB啳ko̻CGrJ.|9˰Y?]oF=Ld+,'BӮ>,Mo}'-DWo-uYo6=K/ {x4Ӧ͈+'~O( ~G69v56w am(MjϺx>5㜳O~OZ Kn΃}\׾РĒ:^9y-o} @@4Aߡ$҄ Iࢴ6(o S]7z2~ iW_۫ib=O1 b[pGNm{Csõ>;~ogްj6芾i5ʫo&| W|Qn%k+Z%ci/} h$;t7_Gw@InY>^8bB==Ks6Tc7iuΪi`?<-*oK9l}U#y-6@ϚoT-zBk"͈d S5ՖxK z)p6CdQUMv+9(w#rS}|mXO`we{:jj 7)j:-Yi5/(87Sϼ=Tj-K pӧp@뾩3 \+j 0`˷j9O pP }MG(yQ4#^Uo ~!+G |7_ۆb;4_?G"9*=5(ID| 09,31.Lueo3rA@4%xsLT^צs9+z/`\Ro \ޱAǭ?ύyq8!n*y$(o6DʹsjK()W(tN'tLgf7Fo\Yش~֤-!u^&x}W3w6&q@@*!@ " xenZn@SP?-o;,T?,y*G* sDIn. A MyN$kwTlTW`|yΥxoI}S[mq[Ra쿇[}[=뭑QO z0jN,}0wD[OZ֖Y w\|eT4R8m_ֶMU+^RA[6-v|~e~Հ/7u\3}2pei2JD+jmWcgݺ>gzc-/yB}ZM)'%,O;؜l@@ $2i9 LJKZֿ^Z#^3Z}}dư m $ɔ>@fl_%:s73iMG}%A@ [;&|Px,az,htW{Nڠ+5 /^hzwdI+7mۣEy3 Pv\~r'5%:ܐjI|k@wZ u1 Oo'(h T2V}l7@o >5O6CRix~"PX;\,ϟRSuզ?QSE~ʱ>]ӝQMz;''硨)(/ԗڠh ;U j*^0K0h nk͘ XŝҪ)5i?wknPij{mo/4zkHsuu55UNGyP4/-D+кc_?Z7+DM]{}cBFrb٪9O>yѼ5ge>   P{ԿTAZ1JX|EYj-h,Mc :+h QE% L8๪%zu7hTYJ2 hlʲuOЏ  jal=0u^be۬g6:67IV_fq~0 ;{-6٦@VM% Bq2_N>t<];a`(u$Z¿Ngœ]nTMguܠW__Xl,t~+ǖi5QAϬ/"tLmo;tu6Oc `ڼRS"jyk:|랇U -#?Q@Ox\X>}fTO&=M~֗]yCQQQs*{|:3a $*KJs{ qGqtv-Xm&l^:zZCX^4#€y÷kOyk0c,ߧQ)zi $,JA؎ZVFXm!u-/sؙ3 d  U; 5-PѪ%"zZ`ԩ9(Х~tS[?\{Q>W-J@XA HuQ?:d#jdn6P†b;aWc0.6W _|5ve;K~HG }7Mܷ>'%i ]m̩pWHΎj C:p/wgeÕ|]k Ά N86P2,pW:+|aJ'Gi V| B|{׊€?ېPJ۾*c8A  'k-5nWشO]{mnI. lD kn^X^?07pmuX~ƫ8M[IDATZZ$Ko'LX[iL+9ho[oYؖ:wlϽi$qet`X,-y|)+ο,Zu5Wskf9{nL@@ (" U~y2e_ꠠlʳkk+L%4% S @m$nҎ4l^Q-p[mI8'ꜚ8ir<6{s\#)x}? ɯ罆3a7}'u&.d%ÿAq'Dot%ZW:gIk{#/6J|*榒F-8=5  @Hd@ ƼM+P@ 9z5?O ϝ;7jP`+ٹVYZ+Oo&$ՊU!m_Z@R-P' 0lZQ T;uT=ZJ`]WWoDcTx/%ۻ76j'Y یmT{>7kl;6ք ՎV|m`[T+؀SO>yy7mh&hѳ[Q=(cV͓|zQQ~׽snPp\5am>6OCVY)5&,UCXC$h}%sQqʔ}Ն4VPTJ:<.RBgYwqP:TWMBK[_ =|M6oLhⱞw`HRچJi+A>3@'^*1< լ >Ifj;Th't랸[M70J,X0J=Sѡ)A7ws\>YW޻o͛w|/CϖbMjlPJ8 J#Co}'Zv޲<o67tWqCu[7jpV4ЂftUa>*Pr:: ϗb7yi2rPN7&wQ:i;] ifDHc@@$2ȀW榕LrPdJ!Μ9G҂W(X怬bZYuՏ ?g_|3?] ڥY\X5aIAmT;6PUڠڍQAA6< _3rY5Yoxם:,eP@Oz&iQ`:FTy Vh2o_j[ZMpP`p{Pmn=' FO髶7Ia5u+ּO،j#\E5ۿihzDׄA'Vc^suo$SN=u6WM|EiCt:6O85UhP`S%)O}19w+Zyd N*j/SOZY)Ij/h M}#N*% -0acZ&E$>pO=b4+ Iroi>,WQjBi%~)rM+AdUi%DTE$u.~GjwM~io[p&ݎ;l6hh&{wy;H8X_.=3O @ʳTz'w٧D8^On#4w[iץ câ]@@*!`C+R\SNяjJ2j5Sꖭ~TsQeC+6h]bƌZQv 5o){4KУGC_}t=Lp'VyZ1\huY>i.@TK 1+(P`!yZC ulg&\Q`%}%K58wVr j$foȻJA=y Ϙj}|wlIvYT1 ]kP~fEa%=קLo&A-WSG]2uZtOLסKW'7㤹߅TfώqP"K^˅˔RgS_Q_ᮿ#*1+ǯ}뼳 T&Nq}]Zա\k=P=I,$$|ݺ;wt^Z;Qk]~{Ytue@@@%,8$ AcJ?$JD,quվ7wm5`WP^l[fclk Լ-4(٠s(&hAdiZ2/im m#Vrz 7q}-ͶXЬhme9@@@ p,XL bTR{ +1JL;+Day.&V. d ۑUvkծW2elE͉ oߕVZ!j{4@@@@j pyy ("J%oǟx(ճ8f*@@@@&@ = xl@:KO<ӡi!,*e     @<6E%_Y9b@@@@} pHdcS(Y"3g={N^n~m@@@@Hָ xl@:S@@@@$2\* ">F@@@h5IdcS(@@@@@Hd&M *k@@@@V @<6E$Ϯ@@@@ZM@j* ">F@@@h5+;wkhhp4ltիUY@@@@v-@ de86Ebjkk]݋Yu@@@@h$2\J&tb)EP$VA@@@0$2\J'T޼yh (5aS (߳gOWSSo#    СHdNء9 0dP[n4M@@@@ڧ - :q>}2M@@@@@(O L_̮]FkUCj|P}Q"Znk;4$ZΛ@@@@@ PU5%P=6I0F@@@@hMKhj&[oXo<.Wy]2     mA@ `x 0"    -` W(҂D}؏%gϞj Ų*     7o^ٯ%X4d)cKhP#4ճrmmmʖB@@@@@e\}}}TA]k5-jӯLvx+6[@@@@@V V_ `-# C$ `ohܣG*"@@@@@ ϟ??-o{-pm ɷ\49 {"@@@@@Q?q[ckw 5cc{@@@@@@hIoXZ6nhvIoh$>ۺǀ     @Vş52~4v%llA6      `0o2[WŇ%⫶2+5/L v61     A|}[>Wsܮ 6q8e|F@@@@@ M -o4m{g=nw %p:mj@@@@@! 臟iMs[8v0d1      _J-nNJD-g     @%rγC$d4&j0     P)ϵ%“c@@@@@*@^y@@@@@C ЗC@@@@$:@@@@@: }y99@@@@@*@^y@@@@@C ЗC@@@@$:@@@@@: }y99@@@@@*@^y@@@@@C ЗC@@@@$:@@@@@: }y99@@@@@*@^y@@@@@C ЗC@@@@$:@@@@@: }y99@@@@@*@^y@@@@@C ЗC@@@@$:@@@@@: }y99@@@@@*@^y@@@@@C ЗC@@@@$:@@@@@: }y99@@@@@*@^y@@@@@C ЗC@@@@.%3" IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/docs-logo.png000066400000000000000000000052351515660254400231160ustar00rootroot00000000000000PNG  IHDRL$FiCCPDELL U2414H(c``I,(aa``+) rwRR` ˠ\\T#÷k .,YBם>Pg~Z qZrAQ  [E; >V d3f0uӑP{AG!ăڠ$D;Teg(8C)U3/YOGȀ՟a(!DXm b*[*H,JD74c#Ǟ5'20] 46ÁJS_RĽ pHYs  iTXtXML:com.adobe.xmp #pIDATxaJ0Q#xEc3{XJ)tH[ l @0    X1G_YkArv `r͹d'0 `@0 @0 %GqŽoa#`rgvH`@0`@0  njv.\q"Sc#`@0p;w"XvH`@0 @0 T'dF,2`@0 @0  *v|`@0 @0  Y^_ vitalik-django-ninja-0b67d47/docs/docs/img/github-star.png000066400000000000000000000065571515660254400234710ustar00rootroot00000000000000PNG  IHDRprEiCCPDELL U2414H(c``I,(aa``+) rwRR`Ϡ\\TQk .Ȭ3]fP;+k+~Z qZrAQ c \^Rbw"E@Gs@t{a ro@3_:IHHl jdbh@mPZQ *23J`d`d sAdۇ_`񍁁y"B,i 6[1y - $%8g``g  '{Ϳpe`-J pHYs  riTXtXML:com.adobe.xmp bj'RIDAThZkLWx ,K b[L>R mb4>Dj4[c*Z4>XDVEmJZX((嵝sq]) qf{gvv9|̵tF]kk+:;;aji՘_lll Iia4?v܅[QdZYZ>ݩt:Vh;R9V&i=p1g1kSlBYT*eغOFgeie@a 4&"y=Z-y;$pH$nc)XZYOu?y5揉[0)bMc@WHw~0"9±M jc@ Yߥkxe֨yB2\s0'(s_ˆ(++%%^_߀cb1 s vW0|Ɩ, c@c4Gkh)bm\<||qB@j'5_}[%%㖼;+Wy1s+^QL9G /vL؏Vb[2AAP[p=Z2w¥˗}[n"{w~pLĄx+W}oPa/ĺQ%+}&V6S?VQY9Ҩhΰtw顾(:*/6,+Fnw8;Yd==?VUqD,/j58> I Ƣ𾱄$ݱuf;uʯFuM srq/܌&1;`GMm~gXYkun<,JndRv)ek'veeayyG( >nD> kttC*iu.r9ߘGSgBۋ{kd<ѼuN#]'3Bw9HI\34իL+\6o_¢".SRp#?Elo\qsuuˋO4>0U(Fn<<-@#rq8=rO7oHeQ(tG B=sg ^O^3["ޡ|:Y4~)ض}JʰvM .~ E3j ͹1;'G}LCLy I0*of*2<S8х)sEXu,}c81oo.,\7oBJZNw~ DDRT*u#wf?://to<<<%,E wIIU>bjQ ۮtsMpT.g0vcGлKt3~=zЪZ{ͲZ5p A)IDATx{\?DX*B]KQF :zqz8tolxء㔮ݚSjk㌵ͪ2KBD "FSTw0^@ \~| $ߐ _~>7D4::J? iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ $o>h4644r@ə3gNbbwc l9999!$>>ދ8'455UWW8qرcގ&"Rkvttd2R088H7 <ϻD3kHɓ'DqhhZ$ 0-? ‚.K---^ |jllTTՍÎW(999!L&FcyĜ1BVNQT:.//ϝح `BA*Qj###˪ꑑ`fܿC!|>ߜ13gкC|6 I;-ioovZllW^xQV+ Fsݴ4Jr0aQfފ|+JZJ555P?ޜ(ܿNc%{FGG?1L Ml۶СCz^R)JF_牐 і}`t͖#!|H$cK .#HRˑBڐ1#tL&B</++kҥnGuj_VVAg3<b^գ\Gk4!PeT;i`jpp0!!ٳnٳDaARd2O"-e4 Q=/wu3clOH H$|r~WꙞP(,**rP*333..|g2eeeÇۼ曖wm( !փy`h.?:[-czW$ !Dחvttz2cޱc/̧d2w .q4f DG48A*C{]|yɒ%oܸQSS3cƌ o!333''vC?L&mh`x<ˌاzJ%A&^/..޳geP\\8r\.$33ۋO~bٗ@5Y̌ &7{*cvCR1+1w{nkk ' _VWWGvڇ~/.X`/|{ׯh݋n2,?vvvҎ ȄlZweQь9T7 >>>**ѺƝ/Φ|B~iN[MΝ;/裏Κ5뗿 ,^x֬YƢz+&&fѢEOtС7nPёΊ&f0hw͛7[_FaB=ITTZ Lu;w:!i/X)߯۷o) Z}%S.TL}_m{Z[[/^<@vnkksjQE,o~a޽tA뙖^we{:@`֭[ԩS-? \⬭Zʩ_x_)4R .9xW_uww1IjIޔ?ۗG6O~g==kˏ͛gܽH4MJJ"I_""".xH裏͛7o;樅'Oжm\ Jchܶm;7WZZ* m-//ߺu?f䴛"UƇ_@iޱc>su!Q]]M;rZJV9cy%0 EEEJw?.**jL&پ};KQ{/la9`OIPHHq#H?I[z\@m-RcܹsÇ555555kUT*$ `VbkKLLLLL4 ǏcoيB`8s_LX[o?(//ʛZʩi<׮][zuddO>;v ^D@Ҟ_F#iۚRw܃=r/hBvࣖ.]jQ&ev=mWVVZWr[N0L吝0m]8pę$Iff呼<)@ۇ)**jϞ=.G@bb"-RV+-ì|q|ĺuBCC󃡡ӧO[}f)==zɦ3fBTf=o͚5aaa}}}lEװI&ؓH!w_cǎ;VRRbuڏѦ}YxBrarj%sv7m޸qrw^{r/"ύ5 8/4p8k< y̙3~{… ݓ幹6L2e~ddQ*,,񞝝]QQA[MT ^+,`X-..v|P(,--􍶨W_u8|q0bO!D*\]Pgjժ?--ͩR2P ܾ>w/'::DP&|$***-"$HV\Ig(iv9gPo\RENն{;vPS-xYYYK.rD"HryOO.tyyyZoGVSIO֤1$(AѤa```͛E1Cml ;q?ݞO0LԊ**`\0.(lHzon8 ϛ;fm"Sߊ_>n$ `JN=+ &%P·/#aM|XxXʆ.֜El& nlb% )))555ގE c'҄Iu]ޞ]Ai6/zGGG k ؂&4WҰ8vP&L[,n %}}nSWg鴕(X&^֋bb>5ax'8HY__aoG1eׯI&&%^N!}cӦYpx]lG6ó3V_Oݻw5 yꩧ-8yAOƊ~ Vuܰ Q#9@-Ct((Hn߾} BV[ZZ!.$ G ӺFzۻuX6ph_hc4̈~MJVx,$d҃]A6v,ðw6sp%Y'Lb_N|%CGp$Lz&L^*[G~b3c`XX1 7oh4JRV:ܹs.l.o޼dS=yG09$$4rjwR!3f,`%ӐS[[{EJ%äET*ٳg] qԜ>MXJXL1 kk0s{9U$33ѣvwwԨT*Rpa=uFffegdna!kzbӦM& ]]]NJHHy633O1~uDcZ=ؼYnJpppDpW+jԅ6d +ICrr2g͚qFTۻ&--7`#4/8 rRYph>=uftpLGLp20xqZocNJ?"_y=Ao읝={6(ōY[oooTT/OL|B&̍ ad`Sgnݺ5gw#@+= XLKΝ"H/^Tm+Wlnnf5Fk8y晧4u;ڋp#$<\jxJjN]jʼѺ~n ‡)))R455566֝ %I% jM#VINR[_^U\[RpuR(Ḣ^Otvvvuu-\VI*J,Uxѥ_2%L TmIMCk7Xikŗ.]beAk>47::d2y;u_2"fK'_5ZMkoù~ܹsYK~.͕k7N46_цy]__P(jjj\ ^z>QO*Z¿Ը,@i㏟{9oGfϞ@ RRR&M .4::R@HfΜl2oG4k$I$ODo>W۷oWTTڵkٲeRQ!ҥKv} V[[T*jukmR,YTUIII.tQ//͛: W\yRܹsSΜ9Zv|TWW0p8x; FA.rrr̙RRR,?z+p`<7nPµkƼnxx8ՊD"P@ b1RD$D"ׯ_w`R|h;::d2!$>>q#O>|;N}իW gMKK[nԚ5kjDTnݺ`_C[g G<4\2(ȹ%FGGjID"7bƌqqq---NU8?2mϞ=䨨W^yZxFחΖ߰~zvv>kX4lv,|=A';;{ǎ\.WL&***oտcǎۿͳ<ozW^Bw^d #233+**-o<|DәL&ZY`1x<ˌe3cRI{d㋋|lGG +JwﶼRZ~xcPTTd!\nYOffݻ)?O,/nhhBp$ GӦM۲e;sU0sbz6|{ψׯhMMK#:;; _s!ˏٖe׮]5͘cK" v^MM͘5l߾}H3(GL M߿W^YbETTSO=_ٳ 썭MOOyh*@͉jފgLv߼ye;"!ޝVl2>Y* 48(gQ۱wj4BQ[[{yWUUرH$LtFTz;:x<`0ݻg=._L;bNnݺN++VF#PЩSZ~4 4u>4;wŋK]iܹ ,~ͳz}OOODD1o߾<@}|}<񉞆}{?\(xĉXb$IRRáNs8awUUU7 >Ȳr@b}!袢"V{a d&|oa/q9a3f̸ >lNN /fϞknbR(o񆷣VkyC֩ӽ`ND[[ǘwZ1LL^^GGæG pO V3taǧMfo XB[/p!WK.Y~|ܯZl,oYd 툽 ,?:u+Νs1lz.z09[|%ipjdXXH$z7]h I!dɩ_Eo EMVYr h9ٿͤ6jǏ[_f4iY,Su+Gux<گݺi^o GV('J J_r%ɛoyԩ{>.% lxBCCE"ƁZꫯx;.eiF8kMT:t3uuRB;vw kc-//~( HkE0 ~x'PM߿<СCDydz~X+%K<#SNݼyo}̙jcKԜLV\is tɾꂂ!vd^k\k.leeu%ؿMd2߿´?ڳN;p+?3I$L#yyyeT mψ={8D"#h \N7=v֭[SRRRRRNG?\@O~9s旿͛фϵ-555ގ`l:޳+**%;uöJAAScX-..v|P(,--uy"x"۷ے***J&1RTTꫯ2XC= [6}Q_B`WPPP@Nv&y;_tyZP(>soŽɓ''&&%%%y;KHF׫T*RY__}oÂP@ bqbb-zay𡷣1 $444$$QlddގʄHN>_)SlܸqCQZ( l[oIk?mllwX,ƇBvPp 믿^TTO;gdd,"mxG]]0q`OCppu@dɒ3gz2(/x񢷣IO?mxKKKggS&M 0Iòe˦On}ÇZ^)DE4 ׻PDlB[>5[|+iﯩ),,LJJ2eʆ L& պvŋx| w^tQ@쉾FRY]]D;{ԩTgA Z]]]h޽B~zގwT__R\YUUBҰ|ӧ[{vaӟ|JPz; 4;w?TTOfXDT?wI&[]$I$d .L~dd$8طC?rss{=L<#<<ٶz{{m:}ڵkͯ]|yގ޸>n߾"_~ m3VXr]Yp& k֬ u[1$ qMLƲ2vð7!3PxKOOwz@RRRحƫWz; {㽵Fٸq AZZD"IJJ DAAAg{JRTU,HTO~;]:O7֭['DS1)^{ْ/NK,pɓ=[˩DMXHiD acqi3IC])zAxaEϜ9s|z{_ݣM̝-X:M$<ȩd`GzO<}k.\@|ByyGPXPP@MƖ---^ ׍qVZz_&L&%?G"d`gh( >22АfTzz Iï(|RF{M]WRwuo$yMh dRMM p̟4_B{cիW;V_˅uu3"9"~/g 8I"ɴZq2L{sԤFٵk^gvd2[?` 񧞆7r8aS6lYP*jںrxfX^p8wu9RkuM_T^4::R/^@D St:ǨW^yz`7^*++e 0(?4Lnee%m憆Ow)i ;uՓVXퟢk \###ގۻ{_#-AmQveQѰf3///??Baqq1.˥t^q~4І5Z?ѣGgޟ=f EEEomXL& ?;ؼcB(I!ڜb/7n {WW_߽`D'8rZddҴٌ{|YZC>_\\xⲲ2y}=6ˏ1111V2&&PҰk׮[n]|>xϟO YdphYnáo}O.<WUU|¥K,?ZsTCee gϺY7\pc\\b6yd2Äg'ܱh"W^moWSYK}p8ܩ\F.\?Z4j ہxYwwGq܂^x @o7f=!F7/l^'h4Z|7 @= 8բVsEN9wvinÊw۰l8gw0!$""6>ڍ`4i4JСC6tgЎ{aam۷oX^^n}3m% am$LFbZ={XIC/-+ˋK[+~ޏW,#kqqq??I&P=K.h+\.ߵk큻V322o9EI[az N;p? $Iff呼B3tyy9Psv7m޸qrW^{r/q!`kff Ei +W.\pǎ}ׯ_Gر#66V,{;@ر{駑1SXXh=;;zvS7l{M8\am\.x٤Btܶ˳yjΝ4UWWۻ}Rs5g};x; ]RRP(/|>ud6q%ʕ+mr9mpΝ;̙([.TmwޱcBhnnxYYYK.̙sQs}`bBL&ӌ3٭6442Q`R$##+1`)'pB.㏳[gCCC___uuuAAÌx`eFv+&:[$==\v ` ??o޼ .8[G>̅RVbwbm0쉖ZBQWWwm+V8UUBBBHH[UUUg?s… ;;; o3ت&?yEspdff=zٚ|ٳgoûmΒjllTTՍl@9rȖ-[ح&?i8<(h4wy}}}Ç'Mr|XLz{{9::Z[[K% Zvddv}GHe4;v{^gg_Ԅwvuu9j1֖/_/z!`zh4Λ7N_{q|͝;w+Fm?^yjxx8""{@i~ZVZH$X1XOICPPX,v6ih4}}}aaa6~F&<<|Æ RT$YIHNҰrJsr= Bȧ~38Ud޼yϟ6mͳ?я~_477]֩"ن233_yܳ&2?[I t`…۷o՛7o!6mb5@RUUlPgKmڴi`YO!dٲe6 ƦԘ=xw"R NIHHhjjr!ӘX,6' bX$̟?߅ڦM|/^CCɓ*lp~(\I͛GFFDaܹW(YLO>|7KT*O >}څ1 lV2BK/J=f.Xv }.p% ,jkk+//٭VR9[dʔ)+Wt6'tM6Whd2q\J;;/ qk&POþ}-Zm۶2e ;[*==".jf4;wڵk<,,,99Y$b{{S9vɓ'2Z©PIÕ+W:;;WZelvv~bsG,K'xWX_8[K}ڪVJemmm[[O?'ؼR$tFFg}bR:i#oEHBȥKj55ۖϟ {y<ޕ+W cwܙ4KVSͪUD"57ICKK9Qs玃+̙cw,FYUА q'JJJyYf=/8c IH$ ;P*q """==&_O^yO?ݻ̋8X'Q,ӎ̜9駟~w/\lx.,|} ??ѩ"gϞ=c qFX,-g7f[7Tl7o;{i?yݴں}' .7h"{B }|=ix3gd~_xdښ5ksɓ\h BHjjgĤR+3.\冂bBCCbtbb?H6md4,\М(İVzzo~o-`q'xbBHll,(̟?mٳgSrD%$ 򔔔sC[֭KMM]f84/#i#4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0A iF4#H$ `I0v3IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/index-swagger-ui.png000066400000000000000000002724251515660254400244160ustar00rootroot00000000000000PNG  IHDRKލ _iCCPDisplayHǭwXSTZ RBoH %A@ *! $]Tp"eEWE\tudk]kyXPQł 7)77w~9s9'3ɗQ} Pքt!  '>>2l^\즲b()  AbN/X Hj.Ppa r4?6F+ʖD ՂK yIڱED͍ q-rcr*Ve^2GkXD F-Bk3R%Fkt017vPGLPo-Fjc@1/V&b\U(N-7 rbc5cm"i6^쮬04A;WɢH(Q;S>#+Ogk@ 0JXT $m=='pJG{JD@14.T+EPiHyluozDxD|[%-<?f@_aUSƁD9h7I 'Dg  g~~'<": 7HJ2tBڈw6P<Zq&np/83{C)W*vs(rգSP0Jۑ.CVT:?_v~Wy6[Ml1v;bFŽaM숊C-AO#||휪L*ܻ?j@PSe3q!"O*9ꛢyMbY6Ewpn;_dNpvpf@)/pՃzpGK` `DƂ8dg1\r0A+Zl.ap΃K*OxzЏ  # BWa#AH8$ iH&H%2 YT V9@"MҍD>JCP Q&tZ.DUh m@Oѫh' 11k cc\,KDz196+*keDp7d\OK .o/^3N0' <Ba:PIA8H8wS Hdp7s3K{lj>dJr%H|R!tA"#됭r:YJ.%Ww;ȏ}=şGRfPSS))]~ՑHMRSSW:::6:~:u$:ttѹfHsqi4%mm'8&NweZI];]H]Pwnnns=Go^^z=}}>_~!} qK v5xbH2t0 7.4fxc2 cc;ˈhh350ɨͨ8Ÿظq'c:0y|r~5a8DÖ 1pI^&LYy+MMf.fͦm6;e3hxpa'4f~"BfE%22rQn+Uj1,cϪbzͭ[۬mmmJmܱڲmmضYٍeWg=Şm/_gC"F'&<:Nt`iN5NWl~|G f%Nd$NIܝ&)4iyҭdderK^JFJm԰UFM=|Y$)#obĵ232MrTb|dQхG;.;s"ă)-NN8yu|k۩Sg~icg>9>.x_8|.^lw}Lю.vwثגݸqƓ7_QGy ߩk~_y^ؽ z xǮ*[=}pwDv==)ύϝW_z'vx髝^}Sm;w޳ߟq􏤏U?5|{``@ƗG V4;;5w>uA4T5ƚ{Pq `uꨞPOϡ-lO- '@O4]SUn:i_m T7 pHYs%%IR$qiTXtXML:com.adobe.xmp 9 bIDATxeeXE邊YгvwzޝYOŎHG{e+|&LI6~޼"L&3L;8p?Kw)v0J(PGl7"܊<79-ЍPb{l)2͛3[NU[_A iU}G*ݻ RhLZ|$B-ʠ\#B-(HP t jJMITK OO%\Z@_P`zŪE?nidU6?p$5.nmJefdXFFӪ "Gˣ0SWzݲ23-3#j,Wy"RoYYtKR<H<ٷ?׹hXTw#PԪU޼y;RP ˁhQݷi/%NAu T-Z,+Ž:Upn@538Pɜ@@nAu [j_l9^ Ip8[tEJ?7Z Tנ: ZjMWM1(sPI:ETP^T^fT{K)))ZZ TSL?t@f֭[W"=-ͩGPƽR }.|KMM-hᇀGcٳ[[Vv*no?WxE{ PSj,/q!L饗VBuYlJ_޽{!4ڵ˶lbpBqvqE fΜis _)jԨիW/$@Sp^wvEZA$++˶on 6 +Ż_htZ`r{KfOs>Fn5eme֮mޭk_͛ج_YlUڶZ֧cI13^Uܼmo>[dfmٺ֮Yhgk Bi{N"{K/]eB-o%2lj@K֮[_݂-E^"nwl\tA}2*A[rxiZ`SLQ玲~rv6gС=3fG<ù7s5WZe+Wt* ۵ogmڴq+Wƍ7on]tqK'K,]I&β芨D芗K y6k:tT&o_zٹ:u)/WGy90p}1wxr- ׫|WȽkqFBѶ/i˲TDYܱ~m[ps塌8m ^vc>cӦMs?u&eeQ:/};[tv*.?xz PL?㩕jNPK':A;:u8c?i)K:9rCo… FׅɚeY K =>`Zn+;}!ewҾxb;o߾ydZ:sF}_I] S yX,msj׮M%Zj\iq. J{&?Ԕ)!jڴit9Xp5Ō/^UmV;mr][6;WQ'/tP];w\M gyi^IN+(?~7O . )>q\zvaZi) SX;m܋"uS~_rpرdɒbU=W :͛b\si!BY+bB[zq[ 4VHe)mNԳ_KXJRPPXh5l=wTfuŹJ1XV[ Bȑm=cG}LW몳'dF$:n:!qZiEػ|':Ԩ>b.˿/뮻^zQ<4xo4jn@SwGf?PnW*%b>:Z)J֭C_bE kU_\ @@K'kN @]=ԭnQ\7tnݺ٥]Z->K:E$]kUVMjU<7х:VXEi۶ms,+A]k֬q.ܾ}{0=^@ݖ=zkL.?Wx|:Q?rrrH-OesCKmsmߖ-[Ť{.ڵ˩Gعsgp-K3fpO~"J4נ|ܾ#Њ[rh A}?i2;)r6*tZG:.쒸Ah{m%c_F ++BT;JzN[[$?+Xt3`ĿN8$d[o9 0ƌcb;8LS!Q7j:*Ky ܥ3(o>+;NJcRIcȹ{Wپc{L;ZǒZ7PtqŜU)N͚czʳne*{Bob:66:2eJ0Rh7(7<K:7KޖXZ/-."՘RQBW'~'[V^~>ӲZ7ryqg;v,VOrk5wlK/d_~S+x:L] DD;߆ZZ.ZUyJ$RO͂ +[AaRuuRu&<`7r=`KUo8kܹ!wUNo9 k6/Qn7S:%7k,Oy֙VN`{ϙo>h-i׿9ˢ4Px8PRW:u-cZMd 6̹,.n~EVd>A9=m۵ yNijȶۂ5@M_9{r1PJ 5tqqOܹ[uTxW Aq*r/:VԹ7rK:gv/Brӱ.zqCN]k᎖]caϞ= eTsx7u ި,HQPiQ$VO0tjNPo ״ZWj U`k[*rQ/iUm'_Yh%:[oy9Z@K"܃ΏAЊ;W?#Nsu}P+Bԭ_kM6qctJM79@WHAY΁*6g>[@4oZj{lYM;W=iHSXPlBس{s?VvBWu|#rVvsׄZO8x@Kѧ>uN6ltMW|`/6o:^}UojiIhڷoo}qZsi@NZN D-߰a[;zh^'nz^:hh%JhڤiBAŹeNe 4n8f7^n*oUZb_%eϓNߨEF߹JA~AȺ{C~eܶu;'w~:uZq:[q}3u_}%~5Z^z֢ew&%5vrKcuV H-~6h[$dzh?V[-[bMݎnz95fs*ʭ4iSfg8KTI:patv78:{s:j9uZ[86T/n('8G;:sn,@v;q\Ux [tgQXuTW:T,TF*}t^ maz> lHիSM]*Rx:#?,V HO/R,|vq}#V7^ & %NYh~{;P? {=ȣ˯{SNv7ڈGcH(:眳?aH++.. Ӯ:zʕ~ b?@ Z91k2lyiQ3``kEZե+U}o87`Y\*ֲ]. |E r:W_Xi?ns2~PeHsi ~ჟt=V ,N'j)SeZѹsgG\ŋGICWZIݨwNcd7.}7ê,8 F$:1Q^2|kt*ߪvOfC!vi~wNe_U:m]uTwC>׸x~_|l2t℉ź8Ga^xaJ{ߧE>/7t_yՕqk_wu=̳ OpGI;ZH{g~/?OHg͚eAeT)?eSw%n@Zvm6_RoFwQUD7T츏9{$NE*Ӳ+~ߜooT脗cI7^cP`sy{qч{>}Z:}Cijsu): cep]~'pCl.E12v'?Δ"[[u~> ;c\IAaqW^~ D:@J/gZ[ y^;*c nPk!aso$Mj(*@UӦmn±h!SxŻ_RQ64X}TFA'LVxHNW**UIO[A|=kgF۪;PH|4#[r]ve!jp*R& ~\r%!]$UH=pCE_UZZ +S n)B(}{BԓO9'aD6ڏnQHx}y jU/6wNFc*oyM8ie{Ψpk q~ƛntƽ\V茽3LFhث,e2?_ZXO>@9ñ!zнP+o<N92=gJ枛}eqcG]Xs=k97qz4Q9<*eEq"-SHSFu!S2PЊ667ִڏtNSPՉoB-䨊_ޭg"~%NH:h'rߧ"C-|뭷V!LhѢv]٢?#^ފfo~`Gg}I'N V.;zP07R98{|WN@駞vB#D$J vr)֥k۳'|f { i9u/~ |gs6mϦOw?QC[ڨ{I7к暫XTګsZQyƹwZI˖-B  rEW+TQ/v /kb ;O۽4l0|V)wQ_uZ9݀ύ`Wr*y`/ 'OausAcJDc<Cۄ ;G}$MUz5*y_~J]yƅڬ Hh@C4¢BUNT_AEt- ggtc(tP0辷;@'!G:2dQpQ"%e ijըa#[rSeF{eǥբ}LZ81cƌ`aֱCGGWQ'rr&]{ݵw}n;묳G JU@gϞ[P;^ COumE6:u_喿B#weW߱@w;DZEѣGM7q>n(kjϋ}nz7u[&KYd|{[j{LrJNI.$¥Fo8 9Z]y/}Tn-[9G (!P2 :O/:_umqzλ .P:Ϩ*(t\/E s2Jh:űbqmuuqU^zE1{fj D}?dЀvg~}ji.2A-E^j w%g,K]{zEKl"vҭ}[;vv\ u`oi#F]U˯<gO>8=Nuh;zۭnZ7Sn?ڧ%*c7R}ޖje?Qx,iIFY+ܞ ݯj/Zhy=yj}UVnkujCH-T~^tE!AL!/u^pAZoZm\U ہ}۽:$;L<uy}>'x {\_|u\^6% *f*;s8A7D|%v8~Lbcƌ k_){ʲ_&ԲM72iQ;m52T~y+  my ѼA*:ܥK@|@CAqTݖ6:y.1;7{N̩eYB-Pux>rQ˯9;:s[乏E[SëB<hXˌ?1=TQ|j(xZhyï֪Uh/D-Zjyǝ%o͡[aW32Xa~vdPWKHc:/T}Jѣߌ'xB𾮎J;Ʀ~r媐HGltEڗ3f8f4HRoN]؅ +\ Vv-ݧwi^#Nt)~+RPI&% »ΧZYrR=<ϒZG>6w9Ue{_O^܃a+?;'ޫg#KۭA|Ur+aZӭU#G,6뮿yoP/ טlS3ՍUír!|`0r_m+KXrw'JdíײҺWEuZu NN;`wxb0|!}Rk`GEZԸaY8hj Z㻝[sL?O'Z˚hV,_qp9ۅ^رs1AA%/(kwEE7q+I߁ٵego{d|ԽϷZF/+O@yO~`wĢޮKhi^'V[x/ps+`}tѓ+amۉp >:rSiZ#cTu]K:7>czsX oZ|RK-6oࠁkjƘZjAVT~7/8sPԲo[iI۶mViU*jly+~+-¯nL\(@jPڃ:]=3qDg|y۶ۜdu%FW.-wb 7{GuV7ݕ>|XCɦ?8ԘN>RWO8[cH@_V] Fۦޚ|b}S;vxe}ånk׮QWeU3uL$TQK'ZTE|,RYZy=Rer[N;Z;vz~Z\->6}WiZh<{wז-Nwi^vjX|ݲoB:qUkIFYy?]k,}NW\HDT1ۤUmVdM4{»OǸ{I]kjB}^VlWu_]Gѕxlia- T=tW_tRw_~6mەl GuZ^jo:u2[)(ƒǵvURk$UѾ뮛*AKnEC6rRhԓOC:\˭ Z9NxlܴmjڬiJeiܷ͚h{D.2xy[ʕ8O7 }@*$PTch\>!q*=xDj񩓓hש['%e p_qWbdd& kgC]lǵt{G yUXTX%@߽vɆ/+ 6ߪ1 ¶]ohq#4ZF{f͛eLݻyK}x:S(59Xc^{s_[u7xqk`h)q/rW".ܠ, -u.X;X|3bۺJ] Uh?PEz4AOCg} p~[ ҩ}]ip2^e,~`wP *;*σ UWi x ,s|>i&K.㎏^yv&+U[('O Zg*zok]7UǺkɒ4J%^`.2۳{_W;Uk. bu.*|jƍ@hSW^xǟ K.6}t}æBK1Ț[)JhQtj|mZHٳWd TXo%Cש 1"RqUۈVZyXoKon:C+9mРAQ7}oӚN d:taÆ9QluReOɡb-{J_Ruс"g d6nE;(ډ3ފkx{O1D7J- c2wʫ#(^+=VnږSKy\v]^X:;hY4[*?R+kpGm+Z 6Ήj+-O Ԣ*;iW;]Kz{ѱWWt7ߺKuڏ}sB>`v|yiQ(*Z{WYkyWt3/UλsDRRԭs]-ZbQko}xؚ鴨13n5m)!Z~nH*¨nhi׸6n [W)Ȏtp¸V }mAI]Ԣ z+4Y3gEhtn:u趚Rm`lgQK-O|AV;D+Do߾vs+ui#Osnn+]>[|ONxIFY>xe1T[C3fsQ.n=ŕDu۽`+>U=ryTPy鵳fqޕU^t3k̡x[hDZ+򪱣9:~b(̺ۃ>_{{==tPnΞcCʡu~O6uwT}9x}U{[=6dPD|[wԣ{bgD]NQ/3vZPy&U-xTZy o5dȐ)DKwQKO*+E"Y˩V7Tl<])Rj~7p !unsZxƊ۶u[UoǽOk-*gy6X9ݺM븯o;#Q#*4{ֻQߧs^Fnit%3O?yۚNfmVw\utEs{(q2 ׵~ѺwIFYk9HDO?r^cI7X~LJzc]ꢣwIe{abiC*'dHus/veNHeÏŪ7ojq\zH$c?k*_㽱l9,e/~KZ<`Jn[9ъ')jm^ުIӸUVZn 3Z.릋⹹ӫ]-#q81.11UGsuϭgB<]:޺խr{|{s^Mc.N=e?[@KზZ4СCl #^~ek#N?,q~P*3U°&MkOw/r`g'xsRʥ~ᄑvWSZaBRaaAǟ|2vgQ*<{P +4.NjTb o9oZ`* -0^Z?}_uUN8"y7mӲE ƹ@aUg׬vʢ^zNm閅0RA-ue?o~HxnKQ |)gIAZR({ݸuHi>/'/(kp[N˨.2Z#F$ݦY9]C;'{kyUwJ4w[_[˧lm#uZ=#Q^n(u[2Ƴ~UZ@eq$NT]6UK&sHj }*~t?{g[nqLO<ᬗhw。{oW-T2Y .GRReD[Gk־XХ ;9d𐈯u(79q!z{\UAw]>oEX7:^?X&nk;RXǁ9guQԣ.lj{-o졞htDXt7X }id"s|@1/ Vd)ri@VۂC]f AuE8ƖR~m6.#㔟@%s"#f~~kja~Ɩ,>ܥ]Z)K[=/뜿'M©w]+O.UU/:p}믷z^sn^gup-]F$/J-ҕ==#ti׮p c;?c-* )1<$ r;~7+`Ёk2)0t-AYV .BKeXr)&TA楗^rV}Ӂu_u9u`/>{ꔩ-nvM~?T@+t}UP+%Ur*{ZkDnwz9,駟t juᶼn5np ,TaFkx@n1aV f"]-@ʹ}y˯|>m,ٶMۈEjݕVrM7:]0sH2FZߋ._8g9+:w; "Q==4qb(L6mZT:5n U?4_ok)˂-}Եl$h Uq_J;u)';C'B%H7^j%w}G'/SWe2>B=V6ubSN9>#,G{{>]'n x_[u/7RMt-~y]XչA)9D˥sӯ!.8yKt駟:bI@.*BX':|5kC3Q4n 4lw 62qTIh+BI5͂ su \|CX ~_C<+= ͠4r-=|H6rd%;W;ƖK<_x˂.MO?tp )/U^{59*a`7tcU_y;{e]u?ɏeefzb< d\ wߜV***n-8n`4{tk&0oyh ?ْSOu-4^*y{wZKoOMPJC;V3+;+d 6JtIVY,yhUy c}G z|ENmfՏ| o&g ~7 Ym`O-u"CMDNB5F]l!_9-~R)Ҙwڞg?y{?M!o׌۵qڈ-S8VHYd}tLHJ|wHfI[ne~tnGU@ 2TQu۾}3Z'~;w[:z㢤KbevOPvm`t*Sk*D,O~N*UHTmq9JW>JQFIH0P-2V?/#,(ټiq+iu`nۭN%wU̯f:*)s޵jr޿45+g_V%t"C7j}&}Pj/*k/n(jN<}>;^Yi&gԍjiZM˧ykPSFbN2Vj- K㡲˷ZQ/IEQi:r-hw>j=Z/o9uǒP݅;tRsjM!Pݨ[; Vcgyo>JXPǩ:ƬIec(vUY,yܫqk:wZ^xsu OtAnܸ2CBS,Rmb+'p򧰣*X^:whK.vmXn]:*XE^Њ&3p{hF:- ,Fç.˳ViG> HT)GDrρYMtУU"AոBc %JALYҁz ju[<4 jUrsUVe;SI]E*sr"Z'|i}b}&KZ.(/:YW\m٬yr Ou"14~`Ff]r%O_+%2˱dɒ`ZEDk%oB$J#Y듌2|Oo(uި:ox{ͷl9Qu:ts[wcO8ܪjaeVEZږa*Qn|@A|N¸H])Kzٴis쎻 BZ^p8?nEYFsG}Bk `l~Punu1v[Wnݖ_P[~~,/5ۋ_v7_iՋzbp[h:] d"\_z.zjo= @DI> FUDV)5֭KlLW)ZxsmV[zSM΁5> aPyt vXUC}TVk<ϱBǎw>]vn)$!tDY.uuQzY)KkNU 9UR+3E))I夞%tT } tsaՠZgAպ9-FUlDTAɞ(:0ݰas_'y.1F6† ZcJefdkoBA:FmN׹sgkع(#Ysjq̈JpF"9< _ccWcaޖf}R -!PDSP }s)j8._֯[ιN(et+YR+;2鬩rJWw#r[B) *2qo*#7 _/ﺹ7,TgB-~рJɂB'5N@;uMZU[ujac_2Br͏]%P@ЕRUPΡcDB-eg1P+H.5jGLMubV cP]#~݀JstI@u cHc@u[c J-@uFØ|fS nKP];jQigEP "u7_Ҭ X^~5 23fj B-R[XAA?]fPKTXjYZQQ9-t1takjj"+--չ AZ@UV PR;B-|P G#jXd_|XKS*4/-{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-^:EۊUkmնvF۲uܵr}SRR,33խc5V-Ym}V\uۿ5f٦] lޕ'oVOJ_FzlbsYӺݭuֲ1|HB-na_͚k]X5º<۔6mj.uWutַw/k԰~.}5 M5cqn?d5.Gϲ@T)[y=zTڽgMs #e' >Ωݛվ\}f4!#[kur2Q5{Y'ZPM̜}8cbSVl#Ol}=Bs9-¾E>]nΤ@P >D){ vF;sr} uVMg!@J@#*ʰRPTa c/\JAʰ<-27Lʎ` .B- V,Uɢ. Ne 9[,*SmY[^Lc}[F))^BSe2@͖N@ղ{^p|ZX6-o۾vڝyggeZ,.]v-[lڽ')Uv)mO?g'tnau@]۬/ْ^^hyl6sqCְX,;p?55y"+c[,)jk~2uԡe)xL7`9疛u./Y[e%i:̌sl%6qۀz[Z!چ ߴR_e2>sReZ^A[FZ-;m~OMIsZl6l΋l?}^o PM/Zс;dǴYpnO|nmκ#|0ϭkSKݲSm,7=nj(*dIv'm^)))vu[nZiӮtT?AvIZf[5ojegi=T*Dط:n]=ݨV$aWzd5kN.hFvdsK|./hEҪ6#ʁoYE|]3=2{lU jܤKm7^i K}AA79dۈSr-]_T.NI1˩U֭cuԶƍZgނŶti| y囹 ʴ꺯qG[VVfĖTe1:?+w;z+5p`+PtC.oezvuՠ~6nhl+SY:|`BY8WMv/mlÎ9NhY0bz+QC5# s[fzg̮Hz3='գyXZ v_ d C_URO:Eg{ U޽zG+/,xc?;<mJf C:o:uB޴ykiqM`<5mwnn+vGXeiW]Cvh2c3=[/~N>!i*B4~UVk~i鵬uþd5sns˭~6s2ٽeSg vw[$+Li1d㤐M:-%Pj%w9g.;Pr26wi<@-2MaϬAzZ-[y+Wsn^$Zcn\|3vðvY׬nv_-ڿ.)e PfΚcL@uv싙e{c[AAa(y o} rVn^hPVXbB6 +2/[4i!^AQi^Ah^% TW^km*8_/2U4i֦qv/:U0KBWQQ-89ie PZ+??@1e9{N)igcHՁ-<0K𺢰1eh{##צepUǾYZŻmr'lƩNkx4;C HJI  UƘ'&e>'LQS*2Y'>rUZZa3B[*.7^=m +ٱouz&j_:6,\ }`5=osϞr6wh۶wӪ*:Yl@[>?m6kKrZۙ>@N3Ͽb#Nj TUcĒVEjZj^\N/ƌdwCˎ TG6mq#OeWm۲RWWvvˏ/0ܷo5Q< *ضm;\Zb۟v- <ִnbSPiˮ!eKͰ6 m喑XlͶ/c.=KVڜo[,εn'|lܜ. C|)k:䕧S Nٳk/.VޖN۶*6Fs+dރ|C^G'Lb֪*[7]4wMӊ=~AgCo+j۞}ߝ Dƾt WK!TfޕSZqZ?f}- {M㋗qA!kPR+ f|S?!EEE6g<[f[V]g{vﵼ|k٢iڴjaV[X휜*Z9sm]M-O2Ef֤I#ִIckܨur"tVO\;Z%!NG1N5˖#V˭PHc<ܵҖaPN )WfyӦe_Wor;㴡!R+/{!-.}S:9AN4N /o3ʴ*kyZ68d5ݹbNѷkeRt]ۖ]5e@@3ǎmwI;׶lpT lPyB[as֙Vuhw ϥN;zZ;_߫w{r7!] [Q}Kq`W,?5V᧭qZFFFqn1}u•X{%k~/]XX?/۪k^K/>׹կWT0(:P_xstg[cl_٦M[bN;kĩCԓ8P{{38%0TU5uEH}>/t\ۼy5mUN]3"Nr:+:p YivC"Ng˖.sY'K6{1),ʳ nbQۛwGX=BQkh[ vy&u:]^;u߭}V;Ibmʗ/}"$:?5V{|h~Jywڶ;61lodW*qvm[=;}$f^ze3>U_`{ege%];w;c@VZc57ajG8789cp;C1fΞnG Ή;Rh~FkѢY6k$+uk%M+VvЋм?7ڴjnmZ}k9Q։:Y%ZZ鸎W;cY]}ՐGl}ny1' ێ}k~í4^o_z/`rH}qMpLVGsc땯ٖKJ,cLDjp&v(URؿc^#[|omҔOnIJ3tŖlXSX6*J]%2XG%u^aQQܯ vGٲmm4y! _.s+[-{e[ncDeNB"Lr3OϷ-{8ϯ_N/7W<Pn-GdOOa3iKс#mo֐l`oͺ G}{ا>*[oZqP%h\47kr4fbPiz}o=гiݺtΝ9-^-Ynyy=ᅗvءm`ۦ-_/\++2.:^c6|dy%/܍WYvF}kQhk^4۲kmu_\[圱IZ\}qbٿE#qn(խfpq|۸ۘ)8٦Q?k8KOt^6^lMfzmlPsjAO |rYv#S5lmna;|ן+m>bfZ^zs /)tqO۹SkӦsE"rשc#Olo??7ϾvsKB'$[VilUƥt&KeP7?R. K0\asKTe t%9c '1q6mRnVAJy {X5v丧=y:[w6aҴ*jܥDˬ[ϱG&BvPe[V=[w7(Re P+NuԶ[o/f̲}E%A<8*2g 탃=RSRS?dE0XyKt֭[wpa֣['(De2M!MSe2TYZ 8aqwУX~AVF3gͱW{j=JMݪ/ ?):L՘qڷ ylЀ~Z͝;JW ^ݺ\K.8`+ T*ˤng2P٩ aL^oUf;־j\9) 9o֩c;[_/\3:}7o]qݬ-\4.`ucM[jX_Ħ|<^~weH5"BztK-1~vQ=>;ڬszMm}> cpR5ǐ8u9ZL]p}f4u9H -xj%HŰlҔOKOh l׫1_e'd)))n s?z*y.\BCV=1GaǠRzݜѽz=uʴWo[+ŐfOh}0>y7ne6{w>L]5BV-ه?<㐕i#O1Jpi,`CfzmV@1Zp+R+gӺ&xc]9kpws ]hOoh4[ٳj)O<-i[lKO;ҾWXV6ھ}^ l |RYޖK3ݺvNuIO:BMؗ˞Vju\k,'bJev:->JI5:vhWҋ-1N;a'qGvuY`q\ө^-o6WPqO?ԡQ'q&LPK{^rMO J4j5>լ?C~Un;Wwۻ5jXRAaZm"nͻxG;wS.uZ#gYZmQV)]r({ݱm}ZU_C;Q-Բ';6&c,X$ +, x[~)ԺY휜jokl3F\[ͩ::-֮h[nwB|'iffb5nZlfڷm[frs[k[mmڵv]i{6[~^;`keX&V?c놽ec8@\JI7x,q/f̲Ͼi'S-bȠHD.㞶B>j%NWvP5~qO۴im"NKqʐjUfZUz)A(:;@Soo_?m=sUr(Ms$ZZfΚk~4.ڻ{ZcZqTPC6|jAjJvuv8Bwuz+N/nU~ m5x]cmے+l}1Tiat[mF Tl*J B2udqPhܔ}წ[)FOZZk3mƌݼqЫHM Էݻ5'jɔsvx۪es/M%>A?B- [oZzu]~;F=ƶmeܿpbӟ6$aD$_x9Z<سNfF-~}۟MiXޱMNhx\give̎<ٳؗYsZI o~{%N>bcU&R:m _-k,PKcy|ԮesrVY͚64vtBhIۜK?EƦgx>2}:}=I_ީ2\z-\ԺuT.oӦ :jB$JIIn~pOJV=Tj}vܱo233ZNƎ˲0r 5Vžw F4^]٩#N&Ŝ6? ˻zͺZVx[jj*;̨m._{)PE;1i5Oo_r^,_*q4oe$V9Pq .i}֦u˸`qҗWlOةIAUN?Lkڴ1Qh<{5Qz$h%} ~l?v"*'YYvǭSUȖ-#'4W&}y'L+(_̘(t t>͚=¨vEE6??-L /,,N{v99?-)7߉{qA'ʄPvuv ZvqOcټ*,*mw=' tBd8gBIS>u:ujJYlYQU@v%v}U{^ĊEcU%!VNM7#k>sv0@jUk Vno^{]y\cs[v3ϿRej͵L{^Z>}JjY% Bʂ+@k.yԔ;Nwy6խg.+VqZhUQUB:e`HOG}@ǟ{_}mluZyPԪ sjٜAu3KdZgO|4~JB6t@˩]ֶM^3etv0@jUP>7l@_o;i_=u=x1eO6(?p";*PZ{S>[K|.=">>z'r)OhڊkBUn ?n᪤ͯ[N~댯Wヶ?77?{T]w&E ( Vо](Q?iaUz=?YMi7nT[pI6؜~,/`cNVCxZI}߫0$i_Vf%0?̈{ZI.x>rʓv&ڞݻoy-;pY?oBve VZZZZѠ T0cǮ2õsr]>]I3TuJ#T+]޼y@=(T9WK)iv9'4IlUd [bU ۴niGþwֵk'6 4zY'0bJ֮mk چ6i\i)RP~Z6 | jP ֭6;+!B3㞶iU cjJZvʕm'۸ S~m&ZT5Z.RIF U Ʃ];B!B2dЉUj+.>@D~}G.UjB"BSv( tU{bjsr(0B-TIݖgyVPXh))NpS5j:ujoYY AS G#j{Z=B-|P ^Wl|qt}Pc|&RR*}monQif/ki,2ٳ)k~Ɇ\ ɧ v;L-NE.-}v?8廃Q9Czֵ.:_;-4߬?ze԰N{ak~F%w% M9sSl ƬZ|+"G:]5ni) {BkZ/rdZÒyY^K ]k{^c=ۚoifMg$,709iqF]$feXZjbm[Pdu{*o-vf=z[)78i [Ya_eO󚭁 [6 9p1fkklӮÁsWﳛZaKgyxFg[}'~znxf*[% DlؙHyu ˥i(xyNZ0e{ y*o-[*xߺz(ç&n Ws.acfpA oxuRk Nldum WmuUo};W;*zUCrlM`_ ZI`w|EWpeh@#;C-L K-y֦qo;^ `Ԩv|Z3:۶37٬{mݎ|[vukuCڼ`ֻ}]:5as{&۱f.kmzԉXjÓYexk6;5KkPA!—>w-EM7:٩V+3ՎRεX\F]Ϯ:4rd1oȵerK\Is k(Ӳ3n'o F6{V2;s #|<ٷ(%m,иUoя6)Oxc7($j|to^^ Kkޚ}*x-,y'6tTW*2EC~[}xs_HtTK<4]ε/ ɛ"³~Z6ɴOld}n5A &}{08"t*/7hfwݲk{+\uRӐ4N:,Xeln;k8׻XS=Z7̰c;<֠v =4Zy5 tm-Xu0p ,O(?/p-iT,l;~Nv5pn2w>0meӦQM;&krt[ (AjMY1dHz!ϭt-L+-X<<N);!B@B ,Ka՟G=ylgm !΄@м^F.U-.m>̹M3Gŏ7[%N#dG ݪ[yoyfs_߼A_VWcKGϱZ>tحEum {.najUӷsmZߵv+AqtԣsKTzvFqOߨN .XQrh]˹+=-źvn;ح͹6]4B- `ǞKͳ(|P <:RJ 坨:Yv.oy=zP*9|gPϟ߳g:nJ!S{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P G#j{Z=B-|P 6oaiii[}ےmwrfڞ{vN}tOkڤq~;wlÂ5j؀$ ;)siw#,s__}un;yؠ {\z:wN@j@^VZPeDb%B ;vh%ig^j{/ruԞPԱcGsU='تS %ϏU~~x *Int5؎;o~goCAl*Z(юb>A :س>;p­p-2hYPR۷߾1˖,[a7oT+:p7kjsի$= m%oluv<^dM6MYGY],5. >섗uݺ yz:۵sm߹yƍ5iZni={v{Ym=1+rrj^پ}GJzի[ꫯvw,BoؕLzoWzwPj%]ɧ_0twۺvTTٿ@WQg%̈Ys b[Z-uGxN-6BqڳϿjkmkƝqp>lu.O>S3g~cwQ?~#fqO6O Mf,o"^m#vZ]EEYQQQUXXT%2>ݏv @QVĘZIVM-M?}UL(Rv-?_[e@/@+Z؁S B%c-P+ vmϥ~}"Aku1K~Gg~g_RI~M<d[ZV1RS_P`ߒ6?-WT-VXm}0>p$v:&"[{۷=MhUoUF;vrƧG6N`qs%vwQG؀YVVZM4-kܴi_A'8mx"kRkټY=(vմicQֶm+̰͛'>IS>Ͼp))Uj_2kبA|<]p /=aPm5{l6lM44h 4^"Ъ7+q^w:{խ[{nqaқ1k\rѹ׽=~`u1GW(+:e`kݪE.\u;uGGS=̋Q_k._^WbZg<:ul @Q`@f2P8 Ŝw`W\v~0В, [O=X ?X+4=  V>o-Y,r p\yڽ`+RWZ5-`PG9gs9&L̝{~#$]Eo]}3gh4)STTdOk{.%5N=`VDU%jg|>55~r׍v嵷n];Y cY&8V6mw-pK4/kۚmҕ6q'6m v0b[BU3j c>?KG,'3nU<֮yܥa@K6l\eVt-Y/Yn / ؒ+^@-rjB2X>zնM+gxo-X״;v|*۶m/ڵk;A`W`ˋ@f!*u1™-=jܵ\)? v/d۶`$$cQjڈύ:4i223V>3uY]g9†4ztb=ZxUܹk7;5aVFUmڴ޽l֩Sرs͙;?•Zݺu|S>S?,˯~#>&PUVv ɴ?R׺u˘ϿNx9s3gq+\۷o[QQZv}<㔨,[*mڴrs>_XXhS}N OR Zjo ?D 7zc>2?q>͜yvvI) 6E}CQ;p}\^ >b |bzg{E2EZjAƍ옣9u?,\RK;ϩDtrrjE}>ڼe8ď\V\M쫘4hP?k~EKC/(_~)7?ٞ1hUF7tƟD}^7>ٻ oƕwoK+Jjԩ| Ŋ4ąqe';+&Dfi/{;Wܙll䈈\.^}mLUرC|m~v#{X /;^x).%AV8Hc[F0Uv޻EUUUnڴWPk7_Rt&LG,?_[s{nQYQneJmfqa-޽RAVSǽ,+u/|bͦ+ȾfUg;lu9}fmw={m>7z}i]Kk /M˪~ݯƾ KGZ=^jI'vas[6)IZɜ9Z\afX;j0p`_:wn;svc7Z:eKb;cWY>[GqhV*kz6j'oh#jwgWyq!19h߸_{;Uh}/kuIY2vc#muK/O\5[_QQ/\ck Gg+&ZZob_ᶽ{[YԱcV[cIη΋_;1bam>T˿ C?s?yf6?r?F=ven?s7~:1k6tp|;_imڴmE­'l7ϵ/iV[mUV&ƽ?MӦGP}6TNۭ0LZY5551acSΣSѻwoU6k[O bY(կo,jͲjܐ^~6 \@iX@G}4jij]yuieVϦSzjhfS|pֵVÔ?x1ZoCVC04 ?\4jfUTTlZd5LTsovgc悺mdY@"6ꒋvƐK`+Mm[2j:fVCU]].@t/Mxd|}X#D4Z_­Riw?&|7Pjj#-sSj15Y]m8d ZKB+Z;ℝ*cPϜh7RN7/ܹxyz!@޵bxLel>i0VC-KYG<,$e" HҸ[ntisoVeS-`}2}$) iE[*j4X 3/5/4Gz`|J$g._׿*-`ѐ},JۉIdۯYB-`=Ґ},*z/Z_ W>_315ژ65`U,nP>ޤBZ^ZP+s$Y:P8&ϩOة2zwiVH!Ђ5'{ BՊ@ ֬K5XV+RhAՊisUiBՊ߳eC@jPZ=eO@jPZ=eOP/|+35H\rq_zX*5>}F?G~9 vpn)n7;}u=H\z /m:fk]NJs1G.uE>Q]1q!f-(ĭ/ivrty:f]CŪ_˸ٵq[ݹҾ]uտK/XЮ6~ ˯z󾣢bP(dm-\p\ҥKˮ~6/Y]Arq}Ƭٳ=s9kVqUQwsѽ1uN!.yliLْ݆WDn2xt\. vz+'jfϞ]{cɺ޳]_…[`~cGq/{ #7d\c=QkZ^mI'7V &Ӕͭi MUy.bH{~pTU|t*!X_/sWӎ 7\|ȡE~}54ZqW,x,ܨY~EgJGkWue„qqԽSqԑǩRϛ7o^4y=>@XZl_~ֶs;DyP#j,XڒuwL=G߾}˝;w.]}ԠWqk5jbV˾6QqĻ{b…z\賺$u}7i^himu3GXSw \[TOk۸>f"zqnTU4٢[{ͶVb;{o<|;ƘYf\mZW]Y: 'UUU:S`w?-w?/Wy9Okڴ7#g}b555RkTyv՛ P5=*}5NK%GgcW\l/'ZwzΩK~->Jy΂]١St.j.]ڬOxJ#Uz-X0ϯX`TtҨZ6~ر]l~8Fǎg역5 ,Yf{8a ~u߷shOSعsCM68 LSꫯfmZ73d6i_Y7M ol>U/gߏnݺe˩FsmMRhU!זs*xa6`W]N<6*++ҤaiY86c̘1cFfC>`jkvB묳N/ }Re?Ukij) .Ɨj.Z|Ҕc֬Y)hgΜU>ēͶ9亩.޷Sr75{MRڗz)/:+ ֔4Zڿ䱃9(ewyoIL%):~m*^{cp[n/SV>}6k P5jեCɺ=*b`PS] WiM}ki\ӄcO;wzP*.xuZ {f믏Ykmk~0m#ԅb W㎥ c=ٺt^jyϸodNEk>߮J]6-ۧBn5N?C{gio[tߏuJ֏}clq~wmFE:#b8:6P sKTG._o6J5+ܮsNQ! ]uUiqǿ/ /g~kzڹ͝3wWuuun?UZW^qMo3捒E`j&Xn5~f Æ ]'SO=SK??pinǧZ唩Ƽ߯_߯ou&ԏmLt-ImP5jUǣJ?1nI+u\.]z[v|f4y{KֽjsSLc4֎uSc1e%R-iG _+mv=-6kV5Ԛ-ZO6>ӈM6uҤi,j lWU5coE-nƎ;W?`ߒuFP+-6zk曖lBGy|1bf~lx~PꞻSI kLa'>yNVֿ`[WMszuib1Z3sL&35kԼ%x֟kUj,=z罻Od={v\wݍ%96?6ڨwuϏY3g9i̚5ofn6k{7n|qyȐԒYg7[׫wfR֊l2bDuEIUVkIװÚb„n }湸@qMk<{8<;V>?4p@qO?1Rs/4[?ӽ8v8\MY kT2vaxP^+_7{䶕Y5iv!f/,Ā;=*6P?{_۶>?mhqġ\RѲ"47w~~饸4*_Wǎ _LmS 8իgp~+fi^~,Z{!^mLҿEUѽ{,`w~Ԭtߖ.]{ch8cϤO8g7]sK]Ν37o{5UG6Jxm+ ^wi}7ߜp7&Y?h'緸> r2Utӭѳg1x[ůWX k>X:u^_mZT%XcT-xa6qTB}Mۦ%g>,~FǎKԮ0jZ>!`rZ}1Ҹef-Zv]{{qVUI _ j ~oZȪջr O~]\+U%"ӟbpq }ǭSEEE{NJ˗_~u)qψO:=zBX+:vO]]:>X~3V;)=7jO5M;ȥ '7wAnw߃%ǟUO URKkI>]8w<{λ;_"BnG'?wJBlvWz6ldw_xq6K<]RqƇ#=hq%ʺql*RW=z(}7(ٶMa kضm4 ve_~o?*:ꈒ)I&.^9Wq>u7jo~q^5q>m҂T!_<4TvOW|=J^XRomM=_|[ӊڪ^LZaJ]rUWWҥKcɒ%ֻ;i_߾xK[mMu,;+|`zhѧC,X\S,G_f/;}X8gYV˪TϚU:߻Ǜcحq irU|߉'*O+)*lj ){XRBa-pʂZw52C]~_`VR0ZATje/J-`=P\ 7rN' ׆;eO@jPZ=eO@jPZ=eO@jP*5P(h;\N#!+q<7Y!ף՗v D|߾QQQ1bdh{]UZIraZr奱{5 ښ65ҽ]~ᄓ`kjB aVmmm,Q=z-[3ٟ|>l[yM4^u@ F=J-cZoi`ŰGFVDJs~KkMGq鞯um2JP.U0J汇KKV~)QEt/{:ۍ{YZWZbYVj^yT%b}to7%[P 5Ti5TjΘQxrGMt7WKֺ!`*5%UijvoZ B-V̗xhuL@ݭi 6BP ' ({B-ʞP ' ({B-^&(Oxk,\pt9  k4wxqT?tԎ5Eɑ9rݺEŰrQQ9r\Nc5kB,(WuumXmZewk,XOMGxk3bڛ3%LDb_/BbܹoN1ǒ{|#5ZICb+YUQ!b5j'}lO/FY%Wz}\@;_%ߦmkg͌qt>yƃȘZ7oh%=@TU3 kJvb=FőGV\1sVu1D&F,Yկ&dE_]u kPdw=JsԻ1c̏~dqZǤISb1nzsٳG'n߯okjj;t萝GmÏ<K.cS4ظcIٱh>}6!Ŏ;l͎5}x9t>ݻw7Ǝ3f̊M6;mѽ]:͋/U 6$vmZktiZ:Fl<,6|d 2(EEcAt.\snuN̝;/&MR\իg /ƔoȺ6gK7n}j^7gdֿlMZ#.-YW1|Dt9qٺ#jn1;_/پfykTGĉQ3eR&O>qr]4;Q;erq9m׿ bEaڔ}M7!CqBNRwv(TWGog]T>筨~cLԎW1rӨq:tpNڹllEuMC9s!ڝv.'bȐAu)h:{~7^{l] jZ?H|GdVKtzbtJϗMY\>=xW?'O|YX:y6{n:?\[=Ϝ8|e~ٶqO6%7pYtzU9FȣOwupn׿_l;j-Z(.UKnuM>sNmXCVwاJӻEd}+/Z5ł?& ZΧ8/< zQqbpbЬB,6SfΚ /MLl"{WKn1xma}qh`Mj/^R>}F|c_Ⱥ%\~.>or)nw.n5KAR޽{oh%Z?ǟ/mO4>W6~Pђ 'ZM翍;oR[\[lo6ٺ]\{:9d]S>d}?zZz<)^sҋ-]˱75HUasUMCߵ쁺t^mydŠ/X}֜,hkeZ vqopeKX@+U%]K,]ʫ]np\}%+|N?W|(]qhsύnfVj=vߥ$k*eR|MUr*:tjTo6]vJW5,}򱨝6NYnX'fewݶ@Ans#Vj'VWgc;59sv67,aw@cKԵ_*//}%؋_nemaCgˏ?Lm~[o??%ycllf݇Gll5bG:5k8iJn請/}SϽX*~OV-µ;7KKw[mG/4.Ǐ<>^Y."7#F o'J;uI|B'|6sNLP0eRujL%:pػǼ ~jV냳ŋc%qocbؒٳJOcu|ٵ-Xr_w5<DaX|Kۣ_r'"kXñ\{1kPHcK4TKvyg OR R;t3>|Rq%֤ISV}+>{1cfIU{sXheuK`5 RZ[s*GgmR@we#F ϺK6H_"λJKɏUUU3g͎]vMq[o;>3c\x8FSi|_>lHƔ5n܄[Ȇ*{xݺ7H]> ^͛o6[*v挈=zZ;ĺr#ߧoΘ93SxHq9_b6FgKz:w.L޽:xJT4:j\矍~o,}f^?tF ;tpٱ.W_ͷpCV3'wtly)T-@GqZ޽@UK Rh4ktcbՠO 3ӽg~N.=x>_Z~qkPk=rƇO|l7~OjͨZH;㶺xұqG>ok)𩝾Pf|TuqK,ի?_Z0)f\,,\fbjiʘ>cf| _o>UrM~ߵi_,Jޱ6[vm_bk5n+lj1ZNk,!\uXk=w^ "߿K3vةTb,%:xZ *m{>F'׵kussW6 ˖;v-Yq;fbjǞ~l̦)d?MG(cJpgSNgJ][l 8 ;'?1ԦNM *+{Ed ~]>鲕B,uQ3mSWC5ǕWCU6.cץ1wYҸ Ē%Kx䢾Rk.;G+c)k5sN/6kZM<;V1Seet>q|w**ICRUVʬ:xHIRŰK'h$UH;X|-%Kװiq|YEY6߳Wt:Xt?Plezͷ?X[`7@ih kRL+l]!\i"4Ӛuؚtl6.Xc{9']uNVǢ_>m:CNUstuזst|%:=7LUO\׮%Wy- Mz\z'5t>6m7/Q;TnC|9n *VؤT5_*/.;o0f(p̊VϜ{v^5ӎx1GON8kz龛>'[~n/ⳟn<}'k\DN~}+ X#s+lݻw?Ե>dלByqV}G+ tr=zFO~6:c]50(un` :|% sƒ}{Ml\ +JKW]XY-^VmI5 tn ޡt>z⋷[mUBPXNձdɒXxq.Q[S{|_y?~Rf[Ç iڬs΋W^y-gf-,^$&LcNo7P߿ ۥ M,ȂUU1xf{'X͏W_uX]]uTɵɈ@kM߇5|ZϕM=&*ZAHzbwuB@+꿹olUTTSNϪW`}^Z]UZB!?\zёax(JΘQ[h'rn5uҡó!ZliuEro Jںaǒ!òav{+Wj-{O.X/Zi6 iJ+fZ-=vUVөA+8j\͒Z)JZ|{OVyj& _7|¬>ߍ,Vyjf aV`P~ohuKJiK~_[B-V/% (w*VXwR!X/g8h ZR ' ({B-ʞP ' ({`z֕R 'm0V.&͆Tn@f6M97kj& HhOr\QYQQAgD{{aE-* Q(fZ-WY)Ԫ>ƏCă>R\GOnݺ1uNUƏ]zeɺvޡٶ`|ΝZ{'Oiv&=)q]/Ǟ{!O!/^]wcqyv6۴<7[(.zIB-,~555=/1#b׿\\E *ډqǭ~ ʐ!c!1n>}F6\|ieb׫kqw^|^1 wqSNnB,ڑ?D׮]Wy1elFcСQYYlT V(m &fU1[lYtС93gI_<(***Z=ل bڴiѧO1bxAc=Ɣ{(^{8KkN]N4%:v#GXawz51q=`بFY_{'nO|.}ɞWYvѢEHW뮩Cxq+4ދ-=?+b֊mKҕ{ĮR\n-jx/6 ԹsۥqiC{ϦW^y5,Y V ڑ _gٶquҗ?ojX;K­3X ##68ٗ oycRU7mv.%/m[qI.{̳>}l- M_tl{s}^=n6cwqwfҸ_'pluwYS*n}){?]gyZo>O!9g[|7x⦛n-9AGA?Ř4qr6/{󤓎Oxgq%?.}S8]gs#== <|/ᦸJ8[ȘZ&l\ǤIW$}~ՕVq7~{a/O//8qR|_-X Z ~9_ʾޣ{^%^}/~ J<%}@^^M$T]? Ze_IiUӟ\,JR6G+yn-cZhV?K_VVFj]˷fVC?5~ "V;w#?}yWb̘%vSl6%x9W4i*[ _7H;n|d!BcM+]RuwC/6+eM7iv%=Dq%Jrf̘ͧ `=wQGǿyNU R% 7-uB^u4FqUT5n+&uQYYcjm=wao[<^{CrALiٳ|@z]{W_ts~ڭk󱳊U'=HV1RXX..Ғ/njy#vi5cݲj/|9 Z?w1tRuoc3Ic\y5 b@Tӟ^Ug$)zWb-7&z*Yv4я]6V֕WvwűӦYR]t>lç;p6ݳXc%%:3ߛߗ\|Y\wݍiW^=ȣ!m:çʎV|,Sf]4fYK̙?)}$cǎo0Ǽ7g%Yj}۸;M49{jr`%qCEE%~^{^/(uӖ%Kf<#%.Y}/St%gϒP?: ߧ$Ԛ?7XەiP+ZْťnbE%i4~YjzYtҒ}꫹Ů[oe?oWoU]]/0Ty\.ݺuSN@4ꖳ7Zjw1N< ;G,uZ/~d9YCl8Sqݳ>bjV5[j͚5 4#j'|sY-nVO].yfk"t38p| +j'M)Y*ZӴBXUҷOfaq?cY۸Z+0SzC#gl]jlMG$_^G V5JRf&)jjM:Z&#c ՝msOhq_#6^ܿ_?73BjGvo}]ט3wnۦxW:n|~oW,ϴ7l.m,X腦^tl3fX{.ͪkq $]W]8 _pf#Q; j07>|XV>+ڪѣ6=K]wޥ+re`Tj3g.ʒm^PJG>zFx~}K0]w, H_n|}niuh{hЩg;} \w//0%nlZ?$v|#~?= %=찃kRG=wDޙ:uZvkitr(7[mEL2$Jҁiuڵꤓ:dM+Rio{{[Oi'4[Njb˖v;V}S-TN4رcVa }׿\;N&OF5 I7;s?b5 UcHɺ5~$O>t@+=CS8uoqݵ7L>ԩM7Y`J/}sxIlJՒGr.k|9zGk+14,YM>)*.KUr&65"O}mQ_X{q\e{d| Ւ8x(üxt>}3dAnS_3DV!Ւ}Sss?V6G~GuDI/}]W1>d]S)Knyi%A>Cя'|B*.OڪWkr_g[?[ K07_5jŤ4vT j.]K,#[Aƍ&E..њ~-X #)U3 }%6kH 4ir*6|h-fEEEIUY&N7OsE=o1tf568ֵktf݁&Ls>T1u/E6dҥr3wxkΜ-zmd:Ǐ}ަ>-훖d?Ϝl8]fG|^=:[.5Zϥ/˩K%[nM67Mm*R}M\4U Ӵaޣ{6,Mk({B-ʞP }?cj3C^{eqBZûB#' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({kfm1Z=ZeF МJ-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({ ]a(w{BzڻoBlb":t@B-X j_y1/Z_x(,YRB-h({*(Qxl>{#7b|BDԹɁk#̏5"u钺CvV!G姾ZPQkjO番v[[*Ew/hP|c+Qxᩈ.]Od S'GGaGFnC#7xXҸW7' &o7bo? oUynQ{ϭQluX~y](̜^>}cR^wECGo{Qf'Gn="'U5uחI9"kkxn. oۧ_>m b(,ZP joOI=訹͞W;^ǞMvĨ۽ZDJZ`~عťcdf,>o\lm[x WJe4ݷD#?0i\?pfe'*vƛQs,ڐy+?yr^bP\MM>XQo4Z~;vX4  Dn(N[Ēv]#ڻF\5heꖧZͶE{Ή7.nZv:D~Q8=mRkVx}l_䱥Brǿѽ*+IOWQYESB}~,=?>Z$ c^ѻ$pK],sQkyJε]Domv?]׾rϭj WL]%>|V@KXmg#t;D~m=уQs -s ]MZiy=^ ^0yn1T+&*s .gy.&N'LuSǎo߾1`@m]cM7Y}W|"沿D̟_xnS"?h/œӘUO>rKD4UA :tȪִ\0kTI֤c.Xa#J7y]C{tX8N,Y ( ~TVVFN]sQձ&2&*cG?1eVƐ!dW|RUVӿ ?P7{gҹs~;w-F[D^o.[1on8 mPwsWkbuڨk0i]@esfNA^uw=t=6YL -mvIq_'[ڨUiewG^e:q^F}WUeJ9yBܷn#WXJ&zܥ~y-ceUTMsH>gB|>iey,*x3"'֧6n6tMŋ+zݻwukB,^8ΝfʂѻeHU͛/+MW\_Vy&j KQsErU{_+6S#%0eBcd)vϗwX(jﺩwl}u6#6xk-UՎ~6 O>\]F_܀!|aA}pXEnuװ0 w DJVUUU 4(:u kFGS4H5yw;-(?B2Ѓd!Ucz>3ߜ=HVس>u@>xwTv' DǾU"ֿ8(wܘ->roDocDf)itˈFaQ:fx}ut1nywXVVJ$d4VC-֦gtܸq#*C>ٺOknR;S{%oܹ{nm>VOɅQݑUUQpV_P ]w3F0U*5T0s#7tCw5R0p'ux1JyK"/jt"c#˶fԷIxu>?: O?~.뱅d?S-ֶ;h]4uE~7j@yj]w%W\N9nZ\NʫͪrZ)|>dU4]Tl]f͈xkVDӷj~›S7 Q]-~M_;' Eg|m/C}۾u0=b܈}돕7mwʂq5kM)Y8ZX)j(B24jٔd˯7&Oɓ3q믿'NӧG.]o߾6DΝ;/Κ;wn#6d  ȑ#iy:t[l( ({B-ʞP ' ڱxnP(č^/>2V ڧsފO`YEK.^|>fN39`eHV;)~Z|>wIeu!u?}1ixeHV;xlݺXsfΘS&Oŋ#O~YׅsԱSt9O͙VdSԥKV?ͩ洩A?r\W/]u٫ؼscĒ%Kbmw]KZ[[WUVEn݊-\ /Y\7ƶ~x+?Cn4(3Bv= w746|VM]~x eP>pjK@:+O5;mwعjMFޥsʇoۑ;n_Vn8VMaˣ_hTTzK$Dɓ?\>Uj5 zZ=]{qq'Ͷ('m~Ǝy=&N,j8)Z5ִ^zgג=M/߰n{Gso冒:uT!JYǎrjJ(Ω_8cO~Gs|۸-Ǐ2Rxh[nѢS~P=qMOa>ͧ'Ȗ Tn'ya#orO).oNq՗k-ϟ7;Ьkn.qIb9[e 2,N>^|NgUUG,Fh`eeʌP³M6ݢx䡒;h%ouI5|MJsڔ#)j<˞ct[8i?*opy$Ufz9%XJӥK׬raqcd~Ṭ{} wqkKʋہԕ`Phǝ[i7h=.yW^*YT"kƕfi-jy8re/izⱇ_Ů̙3'W zRw~%8hH eUX .ȺGj[n55ȃ=wZ%'/Yn\!"lyq>Y `j6)Χ z[7:{*h ։e4Z t];-no9붨iЍG,/]/rQUU ,(ns<sŖ>T|@QV5wΜsWx=Q~ -ZX~wA񯐩]}_כ2LlܽarOh%v[HQ]4FSN..)P^Tj]v+7^%[oC1Z Gv7IXM$H<CiSdc5;8]_*kkW>}/YrbU{3%m^֡d?Ν1X'~m(Bv`,mSe=J_ꊯo.l56hfaP:d7HۻQ8ٟ\Yӭ[챓O;+vsc;//gO^]GӦvMm7]_\t-knnusYfŢE4kU4.wS|Ofcc*GϦ|^[|q85͝SN޽F}fb-бcfUZ3Ml9gm9jNj6fWknߵ8\I | nucҭg,VL<9 B֊hA;i(/Bv C]t-Vi.FW?{7wNu:u΂]&ݺw\sMkJiS^S\?`ࠬڬ-&uʳTEx/֝4֢1nܸݻwt';vXR1T;EC+u9PձSwRډCsd\{>P+=W_j~?>>p1xvc^{%sե->6u9~aHf):d!w!1g洬b+}IBKKiJ;{|J7^[ PѾn'5U:p)K 5tHyI_&0,bn*-V\f3)R9渓;o* Nv fj4Ɲt-c! vc郞ŋ5{G~ptw#l,0WX$Bvf[;M?ٍ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({B-ʞP ' ({վ\ċ/lCn|ܨyl6׵{ 7kЅC D({*мy'.Y7b>|Z9~?/¢\T|:M:_$bIԵۊhaDUUD껅_H^KwfH*7=P ;>~;'ƩV_F̟@AU{QfN<= N{Dl= fd˹.]#7lrDD{(}sޚUϭ{DMa?l?E̝S \/Y j.C|NQq'QxO}haܨkJTȍ" j; O=;r[n;xEkx. ߱]n|XkT + oNso?^{-QȽY0? )4.8F>hrmɶ)45h\啎vUT[</\l}jmqƼTMh_5\'4G6%ǜѡ8O<Pz ^H*cj=_>'v*5 [E4Z)%V~"Aޣ~spǍ.Zn*nUB{ Xk¬@"jy$[v3r !mhZ;Z^u*ȂȦ|xq>7] &S"`B>jnX~]"ן6;F͟.k_9w;vSOԏ[U[Wi-ȏج<joncGmw_?pHnzyUFriʪ5eƾ5oר+;+um8{lE}5?jj33ǧ^O?l̨6|hl٦6[F}6Z}V]}(wG\f;2+ѭ*{O¬e!Oa؈4tImG zm?XsK}e5 )ݠ{/7w .^ ω%Duuu - 7D=eIՎEd?Z7{C -Z[/_vxkV_%wݻ$0*kQxe+敆I1w]]6`ުu7X\ߒv:֟۩S]㪭lQ%̜ 潥!X Q]4~L{v3zl_@jn(8Cq _͞5rUQBM\ה3 &r_;puc]Fa~˞8效{ -֎ytl>g{sUU^ssPؒQxJΥK4Z~MȬic|޽{ѱcǺiVB/sƬY`zi?D@k_zqL0qWFafPDտv;WɎto.j~4놰j{Y>**#7reێ7\/<5w/ O<W~usԾL>z_r껆MZv^˜Wti*ԝgv>#iڛW_gw-Uh@*N: Xw;g3~MGt9Mi~mj]wo9}zQ˿G~ U#.5/J'D~oڡC>);, yvޣv;f^}Qqim>XQuPN#v͟ڧ_Te]s:ȍګ5TF'-ί1u9(`mKEn cj*_|TVV,{/ćOh'N]Ƀt{m;:3? :dY~}0kzFgNEeTzdľDa|s+{,joym^fS6iiے63rG ̺k֣\m.l=VC օh_wS|ډ2zl}߾}b~dSv۶mΑ:#Q5 ]"l5ln:ٱcG:h@`;1|zl)v7n` YhAc@jkhzCܹZ}l i\Qq':tpzHNk>67[^ewWFn 7 t?N<1ifL?hhzCՎ|;?g̙?ϛm7d1blGƍ>G>ѣ_ 6\N V;϶bHo>mɦJBBIHJ"X\ׂW,WTD{@B JIvMfv&"{vyțysޙ|vNEĤɻnu7P^^NE[?4|ዟ k?|oaÆj@`&L9|_[ݶ~dci-_`?a„  .iڴi{m~ʔ);/|gϞ k馛}&N*++Ë/XQG ~5kք+~? .{` 5+mnر` D7nHJ-Ks=0u԰x~0jԨ,ij]Vޚ4iR66<j<jY8kZ90|v wy>/^yeUm79g|N;5?p?*BgPVVnP]]_?>tB7i>ê+Ŋ >|I뚴^P平.^+w ֬)tYmàӞou[\zч(DSOVjmh=ģ;okbXt_N?awίZ3_j_>]n, bIa bER pƍ)׾"-?~;x谢 0Њ]xḓN]x?~sѱʢu@+gݻwϯ˱k®(̮ipigAÆm2tx8پm9o,o8HJⱇhia}ouG/..8T>dcXuGe1SysggÆwA'}(cbwrsޑ_۞ᆿ)xlymUU5v1Y׀ws)ٱ/5Wwmp޻W{c6|d6_Q-~;3[ t7X^^ juӞ6??nm-|ؑ@+iEctɢcpU8c{G-\0^*:opKrAZ+Ub9i*>g^YVnsfeN{~J=a'vV۷si`, ث͛Gpp/PYmWEMٰT8Ups.2eׂm>rT~~9&qksX t_ؖ|P R3kF~>M5zBuLIiqf ƽիw=a΂MM9C |{+-8warqm^_ r]^WU՚^ƌ!̝=3_|Yk*[[6,4oiQ^J~~k]㕔4X1]EK+V,/8OI>vK8|vE566Wa_.q®姝v57G?{EAZp 7~| r`lO9scwLMnJ65gQT_ѳs7__3׷wԘE˵~***u50_Oɻ-ˮw_2tX?``Vf^O6#EO2V[mؕaǯZ2TYf8=GVXnŜ3(Xo6uؖnݶzncV r],e a/+֨V?{ m*:~{;mm}/ϝuQ(;5~]u6C]}}no~Î9zpGdc8 ZG?c:~z j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<ju ZZM".)*i^D,jOew:Щ46n1=֕vt To;lljO@r.uj.Q}xpeͷܩA{b}ccc?a1sN_n֭\Jw럯 %%%5jjШA :ƍ 'Mhun'fg1za4):=vvmgϖ<7mV]]};P__Ǝ***Ü/0rİлw7__^ T1M׾-imaѢ%jm9rxӵeo516٢KèQ#v+--5{^Xt cz^*^&>U )ju"cǎ·ZkֶԩO*L2h{Nș+|[_|U1WaݺEb86/ Wс.a![[Wrj=w6l g?2 >s' l\<$>Z…Km]aT7\qU>Գ4s֜plQEt/~ۭ{Ís痫kj,fCמV>R?2[l!==M_§o9h#>1֖L25_*jkkw}W}O.‚[_!ypm[n]Wk:mfӐ!uV{=yYxx?o}7PxvԢcmG}Zo=nN~kuYpqߛ72V:ḣví/:hj|׹a.;Wǟx:r?m_W4Us{`6,B vC7ccEN z׿}(+*v-wŕ/ς8^/||͵7d]UVn?%g>rqbeԞ{L8v׵1֯~n:а~loɇZ/L`bEхW{p;. 櫽rV 6{5υ7~{; t.?E|OgvPW|]?{ȷ,|9#׿yyVٶx]xU㒥˲Pq'6]3YZ@ l~~M~ҋ'[ޛ:=vmgHVlp-wdbq{ߑXrbscG+H/>:9#庛p*{)+ Ūn?zax6noxï?aa8[q|"Mbv_/YZTvE{ҏ0 ~W̧> XUhE_VCb˽xpoʷۛ+'kf) /Ơ*K[ " GܴqܗN>,hin'[^ԩ_zLxcbO|!}σY[N\qj뵽'T Dž6 N:cmĊ.-[=ʽO=ccac>?<0y -ֆkc?CoW}k.B߾}Z}+VcVpSW4r6qܸ1o뎕A BK>6;o~~>,(V0@+3;ע2l6mWО ,ozvaϽ뮻|tq àA9еu7B1aUl8W|-cM%kJ͝•mß˖p٧?joNAUpAAPՖ8W z|]qÆ -1 ŮEMMb7}~䫌r^uu9bX~ԺP+;;Beeo*V'1`@0dȠ|>V% ڸmn:p0qN|.g͙~cAʨ*Y7zmgvbժ(/{19š5UG ?WYX㑦3O? /ak.j)D,lŋl/h+mY%] vOYJ=06f̜~fJ8{oRMyV=*?϶y|̷'nl]Kӧh/lu}꡶'|3:?_X]gk9kN{__f*>}zg̗Yd3zG[bH *}'x'8{4\*x\~5sƢ]_ҷx] Ƹ䧿u뮿5[n-x9̓Q#*uW[WuC\\m|{}#2u+Gu}o~} +U9x[VM657ß|}V6{ܬy;w-|?of] +rVzO9`/1O*\ǿnc^X1oA]S)~oϪrg׳gc<0O~s@䓗\TǟMbvߦ1b(1UR ű>󩏆O_,WmU]0g cد|{'>嬢?zqή׭n?mݳhݑGV6]+Ʃ5_'\{]|X /kq\ xY[ ,2cBVJFgL/W~?yIm'[w^oo|!\wzkO?_pG?Fi<>MWm_[_vi()))v>V6;G>t~ѺO~kꇪc˿a}=-9.K6#v~}RmӶ\4:Okz@{ߦ4:uqń :illOaÆPSSyoP_.?g@뽗ff aYҷo+|iƬpl̪w!7,\8fpQ᳟h'7s֜P^^9\rPZV.;|]޽{֭[]|,l'禎bڴiĉ{7=TO:^]P qbww{-z`qz%VVY<(ժ ;LtPqÅW;v{ @j4p@ߟ_!:2@J5j<j<j<j<j<j<j<j<j<j<j<j<j<j<j<j.jd@gr.t7iɊ5>44ԇƆHJ%,sάKZ%ndIIi(mE74-75|%R1ʢCGgujNjn^Mw6e7&4QdǦ+[%:mեll*6V%z[;ō-)T*#`̒\!@VwOXM& uB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' y }$%%%!ABDYšVcxjI Vr!V|: &?V1/ۋP+L %jB-' yB-' yB-' yB-' yB-' yB-' yB-W TOˈt}SׄGfՈP Hѓa+^ӱ5uBMJKB8|bǒ_X64@G%dzW;heK5aS UVM>BĄZ@PWޱU݀0j`uVՆ97w\PVwE}Cj9&פz; e%aҚԬuaʼacTn= FV=ua քeUu-ش_!\RSOnazÃӫB*Be-;_yX[S֬U5 ſ GUuo:Oc:<>cmh/B-S9h>_^9;۰19e *ڧi?r9Հeg #7 vYۣ_s. e[1x3Gûidz^\Xsâ>' z76oن+:n{/3kлGYyZm47za~uchӆnŽO#P[jzw=ƛ hW:k^.*+- UsoZv=1-B%MѓNb[₱-42|Qk:uo"*c+Z@bw~X7 |=ۇ¬hze]OPQ^"=bU׼KNab-{6W2]|ҰЭ|ێܷp@{Ӵ=~bֲͺ!cUlV@Aޭ8p[aYU]bCMŒE-|l<觷/ zhE:eٸV*˺{#7]pk[u mzFUm_>\yǒlܱg PS[|CvZ@gq7V.(.+Z^[ЧhݢUa͡P<XmY ЋUE~{p^9+- oJ|mpfd1ֿӣ,oVhB- YuG.~ WնWb[UuC[;v1Xweixϑz CUd}zbֵw撚[߬{(tA][F jB$+v ̵w|Eq ~л]LzMO_ x>b;|]yhE*o YB-Sڷ"[ܧ[i oi+ v3, k`@Q+>G׼>BU;{~{EyIF[ZWݣo8dEqWEÇ=On}ꕰi+;kCǼ+pνCW?Uʵa݆0sQMe抯87:_ kׇ&QtUk)v#MiAtA[GGWK){/v),99XbAm>S+&wncETjOo_5a񽊶Uvmn؅bfmw>kܸ0\qآj]t6뻗zCTɈX[7GyX '/ Cm]6=K w,)Zۗd] nMc.W6;em~c3׆/q[-\m굵5 g_]ozbUx䥵`@jhl|[TwŐhl>fMGˊ}wFoZ.Y }e WSck:kj4?۾5qi9U]qN~qҰxUUW ԴO?7(Юz5MNzG\1a„ pc~uuu6lذ!|끾>_:[zА]om^EޕKä=„zAìe5ṹK6ca}+n; i 3ֆEn8+,Z+׽q)ϺR +kÒյ7ya,/- /..,\UMM.PQ^BIii())Ir>{Э[PQQst6mZ8qMSN7T4d֮ Ԇ;~M,NՒ5uٴ-"<j<j<j<j<j<j<j<j%D@J|wV J6Na`2 g֦iB$4Z;{Vj%$;RC@Bw;|ڗP+Cw }>=>G?A()) {]khG}>~}iBv?qj`ܡvwEZR(%+Vcch,+ e1_ Y5aƒr]Co^F++ a@0~hY{\0nHPV^JwRTV;j%!~7Vk`+$0$RCc BA%׮pvSׂͽeVY٦Ui7V*܇aS㇧4444Ɔ, YT ^K¦Jҍ f*-V{j)r}s64zZ0KZ}p6}(ccdaV@+#7TI;{ڟP+N @+j JZ} R!)1 $H^& uB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' y]766L 7) E\@GSUҼ"%5wP+YYW2tSilbՙ{+BwOw5dH'č70v4 :]Z]R+y*N*Wq7;}EuΝN]WWAJfR' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' yB-' y1jh5i͔4M{4M}Nzv 'NaԩM35MSf 1EZcʦ{ng 7S..l,ƪnnzٴ|ڦi}TZbU6X0vZ+Z՛V h/`+Nrc0`7KcP0eV.  }; wk_\ "IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/logo-big.png000066400000000000000000000273741515660254400227370ustar00rootroot00000000000000PNG  IHDR,FiCCPDELL U2414H(c``I,(aa``+) rwRR` \\T#÷k .,ص<'TKd Ӓ JF% v-Rt=N7I g -4$Ć <.>> F&& %% 9(3=DJ yz: FF 0KF}% '"Ē00loc`SPAbQ""A< w>/bTNi^@Wv pHYs  iTXtXML:com.adobe.xmp adobe:docid:photoshop:95a6733d-553e-bf4b-8a1e-12b4d3234c92 1z &IDATx|Ǖ^)W4y<HD1 P""CE*Д HB14i!l0ݝ|6̽s  > 9 9 9 9HHHH@r$@r$@r$@r 9 9 9 9  ɁGD0AM"HgɁ=!'xO n 9w/ⳃT O7s:T,q)+j|_up} 9pyx[oATשkɁ:3X8w5 9;g~ nxqM!9 &:ouyAvinf\cH{5 _c+^k\ثq}ꎽ}) :ɭȣqpV ~$;~>c MIJj_>rP'+bAr3 fyyZJܹLBZ2-$ql jzAAK!9pyDĽjΝ;ӤII&+W.1KttN% *$z' [lZ5n߾M۷o &PF(gΜH 8T(9GUHګnثޔa򑒒Baaa4n8jذ!eϞ]Ut.IW)J˜ggAr[2{k2o޼I4vXjРe˖%3SdIh=zTx0vjǠ d;;U'''ӦMhT^=CBgŃ>H111.ÇSHHk׎jڴ'?T S.H'{KWD 1֭+]jw呑4k,j۶-.\8BQ^5gR}) qF>|8=S^:3ݻw}EDDЌ3M6T`AݯŏqUij[?He)88ZnM pfϞmx$ Z;i٪de/l8 glceXoˤH"VBrkM Z+̙s3Ǐ{iZd ][q+Hn aTz\xNS哒/X@5/.Ak^={H֥ׯwyo=J?ɭ+jWjg5/ϟ?sιcܹ=̱cnjJ>[RjWkǎ{–V4nX RK.K.^$T}ɭG]8O<jɓ}n~I7(o޼HHcGrAJ5\wg Ai.޼̩v2/Y ,@qq^Buz֭"GJ&7"^iٌOC[E_ĩF/xHnbjsayyRtoܹsCNײC֊{~ۗԷ%tJ;Zɭz+q늓`fbi/l4P>=:^:3qP惒*2ܘUxȪpPXK*N)NS<;oT!hF˗/3J[8u!A0zPDFJp i>$3ZhގH]ҹtIJZ_5OԄUɓ5zgBrsyD0PߊwnmN{Ō箍iRP:g:U}MS9U%wBrsxZ0,~ RW(W^2-=Y\)YjGlErqGyy %^W{^b2|ECd?~H]BYխ=-"sє-uf_G,HIlRօ䞧ضmJ]rEz+PԾMʝW:=Pb#xeo\u^~nPHnr)~G)Dž1r9ul)="}9̻RW?hݸt!yRs+Kc^jU*ҝX͹Qx+TPI]dHڵ{JxqzrkGArSYp=8qI={v>J {Tsϝryy$.wt?:уذaOɿLwOxTr&\[R?/?eR=^zꏮ,5m͚54l0˜% ^YzZrYn<{(W2:?"uZfˬje1/O::/.篞o:VQ ٮj曆y/߭layo;V?Q҅^:\-IukV"j^Z@޵K;~YmRBgMg2GSkgNURMK,={*5^%J(=ЍFʶY9sRFh„ }va$WgO:/*iΝWd.]T!㗰L&$W?z?I.q:(׏{+2CvWX]ח{˝GtO]};"㲣Pcn.؛F/8ytoDz `.Cu.XTW!z?u"rBBW$7Hw%ykzll{ԅ mҬY(22k׆h˂]Ő\yIz>u. ,Sf+vQHH>lNd ѣG+O|֮]erYWcGwHJJR uօTSRcO믿=** hl}8a ܈\ #::YyR5t\.š~0n|+[bYc޽{e?!\>1Kj͞~pm{ $GSoIyVk%xb5f .u Cry{Bj쳁R5\8ݻwW}ma` 00Pv YArYbӀZjʘ(pׯH}_'klUɒ|ʔ)|bV6l,)]A!ټYw2/Tg͐ppݸÍ*/Tfƍ[׌柁O3枅&me ^AWWj6#\>"z'|R ͓|,9]\OF ͓,̙c(kqݻ˗CB@{6Ob^,}~Y;H\THYRg݆vKX36t!b!/͔=svgH"Y~ZlI1߿ku˗WqW^=G ysOՎ6w0[ J9s_9 8oBgMVd^<(U,4#7ntچ 7nȸ䶦L8x9_qqg }'lS]e/\U;uw%gV\Ɖ1ʞ={|!%뒣s8iIG,\bն >ܶ:~RY#TkEyU&o[`Gϝ;UuFClo d;1 -+Qr1fڴiz>p?MEAh'_ҽQCrf$?s VfI #y~^ϲ6 ٵkq#$ə7v7Gs>D;\D9%ŎYfQ۶m.(6OTo߮<茗!H 4c jӦ.扥vSżȾ-9[m$BiIV9?#: O8/}K2*j%Yb@j'GKEb<-y.A3Gclnye͟m߾=vKHN{^/x2Or> *u3KƑ>H׮]wgϞ nJwHlZ>/~2D59SOPP!= /Aܺg6cobuz*nݢEBj'C!}$2Qn*DY}?Ú]rr̜9SϥhQ#vFGɂ R>8A+BBB ^z%="G͛m6iǧz R>!E+N:[<ш>?)[d ѣGsΘL\`AZV-|СßFp˯|W2*]RRmڴFEuu:pX|Y)ZSz>:7<|GFAO=_2%~Gԩd~j-0XNO?-mJТE aÆ)f^QDjl^@>k64hD9[Zi'NЬ(B),FiՅJNjرCdoDJJrdu9s/XU-to\Kh]IޒLaܸq^Soٲ%d5/Xޯl)CK( h]gyފ jbŊɼ (\1_eZWiرM hĉ^郬ƈyIP_nCЖ-[tlٲQÆ /0elF@Tc̛7Oxr+h A,5Ϲnݪ?8xǽ۴rܽUm՜Z6od+;v(J+)zYvԱ믿w֭@֘-B^lAM{o]M/%}V~:e$/^uzrͤիW)58?lJ(F^7:} ݹ|,Mē|.>pCソ#ɓ'e^\ɧ^K/@!A)b:RRҹCwS覸 W ʼdC!3[ڝ;w*_wƍuzȣlԹ}k<ډ4ԥ s^w3[Iޭ[7Bn%7Wޖy^ߤImxpO۔9˕-E]_iC_̘LH}WijI}ɧ(h{/w@9~\A9Brs{xKܹsk͛7kId S=]O:ưԙI>I7`Fd8|&$7Weޒ\<1ch -U)uVܺx S\tJ>[s=_yЁnyDqʿ69yM灈 M&w%_tiӦ5 (5/)S[iFTf5m笣R/Gm{Ν^7"G4"ȑ#5N~4_ `gx=y9K ʟ/%/QŐ>os/+z@ Tzsxݯ2Fi'jD&1Kz.W,$^:CrH>3תs '0jGyHn޳B;k7\97.u0/׎W!}hdy-s; мݺ|LCNB?zBU*=׽\c C{I)OiԾMhGԫ[{X,?fhѢz@rP.?ҫQ4ﱽ҂./Sre >39" \5HsȡԖϟ9wj4ΩR 0V\I.Tek>,nGv>\rʶڒ%K Nr~[]$s~:k{1c$)VZ갌\} w?jAAH*V >%Bge|) 9UL mJXO >r'huUaetزvmqG훒ۦX%!!A̛Rs  B; /%e&]nw+o c)O?{qB^)VYz^EDD\[oڅԾ)GU@=> ,Y fVy" 4럒 4@-PrV+VkR[-9ܝ?~ Æ SJ 9|$W-VᖾFnRի#pС^|Ϟ=yO:F~w!@`\XK;]s+'O=֭[59/]F6yg} o8ߺC`\XEkitw{oI(2ό~R1)) q[EZ ba[Bު4yx>{ɝ;R7o0?T<3F?tb j2RO PDAK#;cu=,D )rNI!*(dO9v9O](z\s!!$wFUJ뭝b<9=/ؙջ-o޼J1f)k\3\-3SWج ^N2oڲeaW~3(*\f|U#Si7l`O40jj"٫W/ÕmY]r/ᆑ2ؽ9/\X򵠇dzigtuհTz V<F<= c܁O -h95.G ;95,X n%66Vgϛs#'@(.5򢣣Hŏ2BV#ɩS-5lMh=Hs=Ȣ?wMWRUTÍ9{ Z@H xeo+L2nyr%\;e2]nbROP@rX5R͛ڻgϞ<}):}v &8[<ɕyy蜏Χx:=LŔ (DV$R5ɕܹ3@pE[ 5GЖp'$)=(X+x1%C,$q/pJ;9/JcǬ8Uto!. 3`9뿔֩F-7YI caJ;q۱̏x y1^P̏>X A0>GOob$xW8%ˀ\1-6rY+loHM!ϫ)pAB8;;$ lPW!šr*{)g[p_傸?$@,.*)9HHHH$@r$@r$@r$ 9 9 9 9HH}P`Q3IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/nested-routers-swagger.png000066400000000000000000003575451515660254400256660ustar00rootroot00000000000000PNG  IHDR.>F FiCCPICC ProfileHWTS[RIhH "HB U@B1!ؑE."`CWE] k^Tu`CM y3w?_2w2N5O*AuȕƒYcSRYt/cc/?u(+.J r>H,9?}|,7[O͓*x d0@JJ*8; xRm862E2~}`5?61Ch %Dhxvy nJ؉A! "! V A>Ъ. C5 @ "A|WfI%P#;ƚrgj4E?/KߒJ !FÈ QG͞FxHFh'ܚ$. C&s C~ȍ3qx MGU]cGqA Ï3=X5BX?J `%ۋƎagX#`aG&vHVc*'TVRZY=',P3Y:M&p!,7W7W#m S0}ͳZ__oK=7}pf5_!Wp@~QX~ Q $0VY׳ L3\PR T`v=)p\z: ށ^AHa ƈb8#n7"QH!Q 3yHD6"riCn!N5 Pjv0eh:Dh1@khz =^Ch0-Yb.7bT,aRf;_ڱ.#N8 w+8O|ķ ƿS3%%dJ-k #L= ~),t"Z.QbD"IG*!! !]&u>d7r9,!ɇɗOɽ]-ŗCPQP6S))^՞OMfQR+ԓԻ7ZZZVZ>ZcZs*vkzOsqhi bVQ-:nG \ml*/u(::l:::{u.tRtt9IN?T__I#ưfp|C s磯o߿\=i?R8rGV< 큖AA-AOَ,``Y_L,$<45T?412~UXfX]XwGȈe7f\>=kQ'"i񑕑dQͣѣF}76Zb1+bNc qL옪1O͈;ψ=]Bp’;Ė$IIC'6v)&)┦TRjRԞqV1d  &h21gI:xҒӶ}jx=n>B$X) fg,x韹"S(*u9J񫬈Ycf$%K%'&O.&uHۧNY5[)"GMy~AE ? *Ԥ{ $9M[8iaXo-3,g̝`&{YȬY-g>g\-/z;/y^sYGRW]"+1oօ ,Z*(=WZV^yѹ_ZkŭK<[J\*Yz}Ym.b􊆕+߮l+*جYsZUpծj ^^~67Ʈ|qS'6-&[ʶ|*ھ-nۉZۗԡuw\ޥ~.殲`b~'rO^lUg/m@5t7ۛR:׼l=hy%)v%ʩܫE_kx7o n>s۽w%-{9kWg!.<xыǟ;П?xZΰK=x!}U_/^; c;^^^ַ#޶}>z<)ީI+8~in_n_'㩎lhF@Oq{JT껠J<9 n@n+ AuwhghC R3_d}}klR)Dx7D׌&,?ȿ1Q pHYs%%IR$iTXtXML:com.adobe.xmp 2034 928 iDOT(l@IDATxxA( " t RTŊ D#APAא97dvMGvΝ;3}s=>@@@@@@@r@~x       F˗/        <^xrp         @        9H苋Aĭ        w<>=k$zY^~cEr       jrIHH%^@@@@@@@ g*]":ĉ 3>#@@@@@@x<9NC򈀦ˏyyL@@@@@@p 0#߭6,)dz}6.      @v N}Kر㢁|       my9@ZBYsp        +x<}\<){       R)MA K4 g7A@@@@@@ Vʛ>s?z3s[a@@@@@@H/D%p |        (f<O`= IǬt'2wE@@@@@@X o) k        ~(`'GIA@@@@@@B %C=,p|$/ѣGeeϞ=m6Ѻ"EHŊtR^~fuSw2;       m1@~p&O|Ks}l9RXmZvjp~lʰk.ٿrJ9S@oSؼyhjΔO_Y~k}N*UD=æm۶{V,Y2gцc9_Դ)eg>vr!ː!w={9SoGenUVUչ4F@@@@@ 7 x}qqq9܁X ϿdKn 9rTƽ4!,|}:^kR_߼yIEGnp ;vkFo ?ܯۊ+H&Mb&5im&K.sK/̝7}/W'e`[e^{%< &H RRw>SO˛oeF٤Ic4ibDmݍ|)1mw3<-͛7Kq,  pCdΝ)Nm߾ 8efw:A{IrFKRs `B7o'.29\޽{I:uR Ё &.: h oRqAyW͠>N:$R\CAgy̱{,!aU._F[[>q +܇R~wN;#4@@@@@@ x/gfAЊ1?geժ5C7lPd^([6|:ݻ[h+tK7sFQ+of *]Zf׭[7իlY{v@3h?)sAnovWm ||ͷ)V̙3ҷ5[݈>5j$SQ[衇/UA?~)i׮mcT.]5kưMǏQ/]ǎ{>ŀܠ-&L 6mN;O[v:K\6lzܮ+lb\rL<%Elٲr뭃Bu&/iVy5B Y)Q8kժe;MtmjE3=3/+H;.S39_qe=V/e3fL7i:`GSo1A:Y/[̚,dz ƽAM֬Yc$[@W_͓s8y(vM3@oi\wݵAgO6ݙAΝ;Y)ϖҥKMjwu@H4;}@%f `iu ㏏pM@k :`Z x~ 袋2} }߿,PFK6O>t7jȐP#Jz@@@@@*fď+W'J ꓧ%o3fc[m k0Q?h|;|M裏D5 kJAn#Oo43 l-.pһ&p!kDǎ~M{3> nh݄ /G_-[^to5 k'ZץKg}<^Im5)YUv!=zr,MIf֬#:ufժU>4ui ҧRvmi?3SU9ru׹w 4H8k>;]fMׯqݙ9sÏaf 5ЯFLw5ĬhŊo*zmtƍ}Z:ud}?Z؇S|j%t`F,w}8,FjB ?5!#    55# ~_X滃NmGv]x+ )Sk:'d;8yNci3#ž{f%\"Æ=*:O̭ [Nul{vwߏ<\}UMBl|^zfFAh~{,;t$[n5=,X0_t CESnаdRpPS }L9E:bѢE樦&/&e'HK _@Sng2j/_>g<|lٲUJ,a(hƀPEnlZ:v(\}wsN3D*;K4{mNvi~fS۶s)O؇Zڵʰ\t20     d@ b[4?_n'#1|]ޡIA;}IO)e˖}~wu]ǎ;zWz4// Ha ̘ouc_ V恑D+M (| BkNR]˫"^f!:u⤴1>q„W/]]GkC~jz۴ 7_͚%Y+Ⴕ k _S?ҰashIZ _&Y֚I^)Ś0:W]@;.+{֝ٳg[Ϝ4+]r;tw}쇚KhQѣG9^, 3nEFTAnj @֟}2u֭L9/ƍD3K p7s{l@˗9 Dk-:Fp {o}逌 /-u L` `>i;wQʀQ]b[ڗm߾O>ԺPY)Q     @zrD ?0K?W/Η$;+iu6kfwb rg׎4z)3cUS m)L,]yi򝆩lL3?2|rxZN]~t4ԩS5OqL 42;HƮXztnveۻ?AZ7~8{1A[f,uF{wj|}QFˡC-q`PvLM{65vVZ%>T}V& z–-[4h ={pр ~^~zα ;!W_3͛4ilȁ͗/~XmĈ*Poذd5I~+B6mwNwYw0 @RJʕ3;$`pٿY2@*D{@&:8BsyM+Hq5jʔ)aÆ.nݻc@@@@@x /ҙPsi ?/Z0ߝVefQN+Z3L>].Yjֵj*.Nߤim<3dD ?0y_YݶtZ^{9fٳGZncοdؤڦ"m7OJ=}w5u2kLy?w5B5M>@;h\:weɌI4hܧ~k_לZ׉?p,4U9":{_K*g-41mYlי:m@@@@@"@~gIFrim]S߹NIo{EOFw~933k;v1z7>Ҡ%|l&@mđܳ;8>q)ғGŋ᭦ˍ7{ZmDg.]ڤuW޲| S?K<̦} Lv>gj|P:;jj! ׀w}gy{Ѝ7Nl /:Ch Li3֙ݭN?/NfϞmtt]r@|(K,1uԵ蠃~uz܇SvOe6;t0BW_Y2"C_p|g\uZk/]5$;sgI k {Io ժU3 K/[LSٞ5kN˖-StI ;s^+Z ѿZ4[B>?@@@@@l2.7=#@~~ 2}z&=| $~u}` Mݽ{SӨQ#2u7{80i`Yiߵ״zTZRl1m"o.ΝX3'83ﵩEuȷSk}2eilyoa+~t옶@OTg57mdgWu.k`&ov>׷6l9M׉v΀P|;^jUwf<݈4{~` _i.˲j wjzPJ(w4{K#ԯ_oBj}p@@@@@x@x}:7nT6t2iDiҤq*g?U^˹&RK?uN9ZdF~9}z]Bgk`.:_gpؑ7Lw߽bSF4^KR'eNݻԫZ_k}-ݻOk0YK&M䪫4 7ߘȑ#絏H}욉CM #F<v6=^߇fw6#:u~o,2Ye^_;jZ 0}vy͞; ݗ{{Ŋf wn} ]A)     d@Z_xSZk 17tGn+5k63euk];[J43u_2U~.mNWZ-7W>l?zTgioTgxuZ+Z]dN|d-M[sI#mJ裙V!Oӵun-!O q ||0o<ӻF0ঠk u]v@KϞ=Af[gEkPV~o)tփ#GV,׵^S^g P߷Rd׎_5[j AaڴxvmS׭[J}}t7;w|U>v@O vSg2tRT)mg-ZԤ}m݁|wp^zһw`:BuY4 ݻ6{t)AR     @D_5+]M 槝/_Ν/3ygǏ'x2d]V|9dLo ߝb}ۥbŊn[-[&fMʕW^a5^yɒ%.7~lڴJW?Si{_m^*>,=˾qrW5{sg=z\cfw;rʵ|f-f+jwG2 rwmv}@{/?Sȴ] 5#_<ӼJ3<_m&/8Ye̘o>E "v풕+Wɚ5% ;&]&BEW#     \cG|e}-c5O{rЇ~jH)[>'OLZ{:-}e9G dDv5>'j:w<܎yc.m~akRbŊߚAGP@cdJÇ…C7o,/?3}T]wYSC~fvimZ7>y{6}͚5_ܝ׍nFt ? G65APb{ƽ6!.K.5 akFUV:\n ܸ>믿Dxh Ӂ lap|].Ayҭ[7ӽuFyY3u Ͷ}ҦMRI&I_t5w4{ĺ^sҢEsݤ      nק!; ֗ohJ'ȯ~3֬y 4Q'ş8!ǏgTw~hQi^vX>|Ҭn,^c="xNz݁Anoڥ5ΆrMȒ%K)S^FfӇjI"ٿZ4,@:t$[n5)qiݺ`ɒxaӗfSᄀJ9`_{m Zs 7xuVe /Gq`yM1onoBS<6pϤ'G}Y_>?JsY]=[_[B׶@N:I~!>&Ob^ifucMKG˗/Eٳ?j,6-|gpBGೆ 뀚~Ɯӿ) 4?h5`孷$;uMͦgYSw^S⊤ )R     @9.O0?+uΟx*9Ӝߝ_!rvmEA^?;~2{ t$A~ZF^*^>n7@0`Ys\OG[tW'QrI^wҲeߞ kfSf}L?OdбcGkv;v֍6۷m_og9sf[*ۧ7g)Q.{/)]H˗/f/:̃;|7:K,h*{MiXt_mաI&^yUݍ٧nF@qMfjժA5~'vz-krYf]6_ߗ6 k Zᢋ.2*.Qݳu_QߙǏɟepyYi33_;EqsX)h.:\r.     K Gȷ`-ۂSke˖ܽ_{˯I=mtSX=9*Z&;8`7)5_H*O0iNs=AЁYQR =zEu+9~o1u͚/2x!Cy,]*TM#Z̯>pg[>NϯuoԫW>|נA:) 6K(/yS|y3?Ҿ}`~kiY3G@ wSjz`EOZ^Ut@%\ _0BC@@@@@  礙֑gdUVi󖤵 *Ԯȶ9*/53r=h@Q&8_ kkq /Z_{ .)Z4 _s ",zM߭k׈6̏>rYR_Egck:x-faTX?tk=݈>uk;p gVoLҌ;nG߳gYs^g+~M9G!dV4Pyͷ:gJ1>orC*sNV =z ?ؐcz衲L8Q֬Yk (nf|~ɩsohUkAvjzx^=c[l1YY5k֐뮻ΤXwncϾw/SE7wIjzޛgk]VfҾ};i&9;5O5 zz]@X,=c 3N=T3Bs׬"\#f͖ԤϠGØ1cM^3h}̙q3;mtf\z>n#;tp;o~z{耕tJG@@@@@ Z O&pKJϐwf},<#3Z*X+V0umۭkdz{ }X v]:n:{u`UV @ީǏe$mS>߭P6ttM`.#AH5S`!+e{T`DTp5p)Yݹs QJk@QQwg[c{р>tB"yo|^M\B}&(~8']@bg]E3jvy =%* B'5u[u}$.lCy#     }G\(.;H]L~FYgtfzMkMZVZ-͞bv~Y,8 `rJ3y3#s?Ϛ%0:zf:}"     Y%Uрڵk?֚[n3} WTQJYiխ+իWϴIƃ>dҺ_rҶmLɌ@ >329@@@@@ ?4tv>Ν;z맜rJ׉Doʔfɟ? >,SRm_g}TO     Iz}'M'sD'p"!@@@@@@ @ ?/e1 h0gf~}E      Y.@ ?ɹ fxѠ>@@@@@@XC_\\ :3DBB6G@@@@@@X}'#%xkv>:       wHw=OC|>ğ9-@@@@@@Lfg.}# 8qB4OA@@@@@@!yД ֿn@@@@@@R aJbY:{      C@~x<       @.X{}qqqqx @@@@@@@b[{@@@@@@@\&@ ?P@@@@@@@ < |Sp       y<\8<       -@ ?w       <\X<       )ٰq/!!!6F@@@@@@@ e/A@@@@@@m*=       Gz}'<O       @ 0#?_       w!      İ~y:       @x^}O!       ȏ-#      ^d       1(@ ?_       {<^xrd       ĐzY*       @ ~<       @N`F~N{#       @ _?       7       iy<<#       S7}        ` Z       9H@~z                砗        @        9H苋Aĭ        w<^xO       @ ~z        ;       @`F~z                砗        ILL!       9@9%p        m >@@@@@@@_|rp         z>ǃ       9%p        D_\\'       dgl>F@@@@@@@|       d~\@@@@@@@<M@@@@@@@.fg @@@@@@@@ HU\@@@@@@@M@@@@@@@*fg4A@@@@@@@  @@@@@@@ U\@@@@@@@<@@@@@@@2[-L       D!@ ? ,"       _|2:       x^DД&        3[@@@@@@@B苋"       @f x|Vɬ@@@@@@@ @@@@@@@TK       D'z>YF@@@@@@@L`F~)       i 67B@@@@@@@ Sg +"/ivٸilw>9pǟϗ7 w,X@JT\ʔ>Y*vT9qzLZ{om߯*wd>[N$T<JBe䢕I5 崓Y@@@@@Pi {]./_eD ׫SSmXGJ*[˚_ʡSZP99vRB')YR?O     @ 0#?1 .CȂo?]mrn]i}yRX,#{ eYzXXݤqվR`Xe@@@@@L td/V_}+Ǐgr *(^r4jpN<_$>p\/V/R01iQvUc>     @ 0J:B^`_3 ?:;Nf3i/y     yQz}'/>;όĴcϮQMz^93?ٰ~Ę~reus     dP@ gxf O!=     Įcq GH/>#N?i3Β@@@@@bK@~l//VȬOqy..F IWm#_> /.q|r4'y'=6ȂO#u+Rd9d]+D")^ϐKGҜ6      5 2:~ϔWvp֭,oOFϫ;ZAӥ`xk:\* [45"E (;w)>~ǢIOHSWD.;JN/4yO}F[4ʂ6>YARkLP-ٿ|V5K,l`Rҧ@@@@@ ϭoB\%g~yϦ)ur izkN=/ƺ `hwqKiq~`]:u`7N]Z6GJ*թniHާLɟ0Bj'jˡTXڝ3̬S[\iԠ4W[Zjn)EX1q#j}u76m.^z\Aj<3li 1?uL+ؾ\aZҵS[kO{g^ѯ.NE!7Z2M]'ɐnD/ΉvWW贿&35ն/Z`߯ݚ_ `~JWٻSוmG9pЯu5q,Y?1hne H@нd)[,WO&|}5*+Cc:m1<%aqwn^Nu     *<9#?@M`ߌPh#>e nd9慨g}Ϭ>:UֿJVU?zTȿƞrjrZO=(~AR@r{-2uZ곫/\cK79 ǀ׈.`͸2W4}iuj4st5MڻDyma;ZΖHh_+Ο!'Mxs"5x L}:guVr+Suq+t Q=Ny\iVCg_7^ܛ]a7ڻA?e ڐJ@@@@@b\CF:|3}9J ?2#GJ"kЪi^$]ȷo^3o\sUgPYȟYz}ۈ5PZ~m[liߝ7IbE7l*Sϲ0L{sN^;Iͳ:OOpufaٻiz^1s?ٰ۰mW+MkڗY3wjv\\!߷'VW; ~/q")T,u_7_a-_\^oT)ү^S/R;a`*e[8G9ׁ7Nʪ`Wq)5{7greu=F%     I@~oskI3DqF򃻤@~dj/a#qV?!NNIrJ _~2rr%"z -ٵ{ODME H@~l{w{~EW;\sჶK:g H˓gkV kZʕ--|mD=)l. _ڼHYAҰ~ ,NJmYt'\j~]Wɦ5; %T. _ `c9#T3yӒ+B@@@@@ ȏ6jXW^x(ޔ@~pȏLޡ#%D8HWvoHrR _Vs#p©>\VuDQa~vr]S(#xq}%%&bc 2ۥNx)whv *(YߴaLkƿaϱHRr}$Xi_]xLc~yN[{`ҧL3߮ 8\]=~ ѽRxu˟?2_O*x)Χ@@@@@&ILLťAi }=fҲEd&~Fz6[G J ?BV.'k ٻa?X,u_/@oW,RIz7{5QvپRDVY4p(U\t~}~WmW[׺W(V\^ yК+<[|X>     NQR]/)㤀+u]hB'>2sg ڻi|Ǥii>?ԉ91wHCݶ'/[/^.ZWץҨA@" {_`;CY.ںm6]g_7V$7¯n;eڍ~udt H[Hׯ,qS/E&x6ξn\\!ueβeMU [G"V:VVʥZ8y }6Cn+'<9Xg>\sN[khv}Q}M%J"E@xAҋ(A@RDEzMztD !!esnݻ=&y?rgΜ93w9=~Z~yWip H`j@[97uU~+7o:ʜ}]s[&oy<EY>YOcϖws ~?.qh4Ҕ-u4bծn0?ʿu:o!]W @ @ @`V(ź4TLr8{Wk챼OZ|i*Hxwg߱>bmS9W>syeYakoK/_~_5AbO<9>x#}pDŽ [=*M_9 qcK}{SőD +;>Zpʪlz-cgRXrZ'78 @ @xW^zf,5tVБA~/F.yxY :|gU~[%-}6>n޸Z{j<Ǜ^Ǟx&V{K'tT]c>ͼ8aãwS7}b[+/W(Ǟtn{ښVbʻ1e8 ۲wW﮹ZS}x3P'k3CM1m49 ?b܄}#UoFկk߸p˷o.\8=U{wƣ/V.mAb?lPwş7S5Ym%vM @ @fIBNq]MM,p=T bcʻ^?ψpa}W>^@}3+_<Ȁbo_yjC=}O'kj1wY,Nm8BzF!@ @ @@!8}X_>_ =GF)b-/HmGe#G7*>?!&Os` ΦF {ʼnM_jOmߙ?>DkB .P{uśolPך3='9%~r?iLsR(^=Q>/F9|],N,gST>-bOxc̣ ;i| _Y|J=JU|XvЌ#S@?Ӊfh?R( @ @vA,^yn5}薺 /KR\}σq-wUkR:wVa{N>T\v 1b{-_nD>NKzþ`=~f#S_~ߧ>0*!FK]_~Y+ )Xjx @ @ @YL@/~mE:2ȿ; usj|űpTOlaWi477q{M۵C]<8Vvd?g~>dWwls/&&M\-i&=wa fVEiF}PYwoyZlW#㺧jv{%RZ2oq@]+g4hw=kyxi{l*OPz ?.WWZ?6\ >4?h#}>TVj#@ @ @l*& ( ;)ygj[>ŒK,R?_cOVgl}b7j0eyG\Sωx$WW[c]1F\hQWv ?,k-ٴÛm~yMs/6y/m<}O[qݍwWn4Zwލ+I)W6ez33l|ظ#QYkŀFVCUns.t^ucmi)h|SglKSWXZ[ieU/ZA}y5Ym^ه5pkqS6"\G7tX؏GM3?GiF4qIo~0K?z [tX6C @ @fe#ŲN֛OܫJo*AN;l{7mTkV w:suYA==~^{ho~eM'~mC~K7\}A HiY+K Y,\m[jA{nt  n0=Ctq}z2_Y2xdko}fB`ݯ_y+Д @ @ ~辱{ń vhUW3N=vBC:V7[쥣4zx=~;AZۮ޽:?xr5αˎۖ1v'eİ=vնZ:ljX ?\GOgӝLߘ5S7>~CS7G @ @@! . ٓ SܯSsv/cW6[;q?׍7]xE6yB|sM/ڛ˧t+-gq\ zoIi nizr-$jߏ_}σˏ;lu+O7swoTJk ~ر#{1[~̟[u7XrZ'7G @ @f#rF"-.?;zlSA~4 }z+R#'_;7&O%ݳ|+u2$"@ @ @Y^P, _gէ7Gz?˦^S҈4285E}ݍ7]xE~s<4zZK/>jMf8vY'Ċ+]]=U1lϝ;\oMxFϧ͕4%}ޠk..\W 93uѿݹ[˯ռ^hkr^هye,=>7O6{f׶f ?]q1}?n\J37q`)>K]w^Y028,6h|Q^w#|JN|>Ø2uBe7+B)E> Ā~X) @ @t gsA>'|v3:_ꫭ<"ۚU\=N<SO?uBKJߑA&)S[GϞ=ZlӋ/6nۖ5O+e[IT[R㡇cN8#Ow6:hsl8[+ou=ȟU @ @ @O򫼦b6u}5 {Zi*A?/6t*3׿_}wu?ݶO?#ލgSGbZI[t]"cvlJgޒ>VǏAC]pZYmy!@ @ @hI@_E ?ҿ^|֛W*A~}ʳNryOZ9^{,7FeӖ7jt۹? qa4 )זqaGO?+4{3[f,H[S @ @ @@A~jA~:ϊ?>XJkmt1s*f /i+~Un,A~ |?暉هj@[ք'l-<qAKrаfhacf -Pif[v5-$5"@ @ @- ٴu555Ö2oRƶUvnR_oıGji]>zr'7WFզ^~}\uU۔}'Z_ G {qhrA_|nCkoV>jG6?#W.wj3KSn})Z4 @ @ @h@X,rmC3)yW^sS\v +΍!CGAzF A~]]]r=qo~[?_cO}2m~G4w]Q'SO?D /8"wCj7ȿ[w^hto|K s1iD @ @ 0 _e6O]]wmɎ( 1a\k.wu1\} [g wp-7(;dx^4"@ @ @U^v[I&c|T|]1iRl^}-.8\mS&?>OʫǞ,w0-=pWF>[ E"  @ @ @f3ԩSz1[=vgM_F|GZm kwom{wW^a>OW 7ޑjxqGZk_H @ @ @l&P(uBaz恇*KrwMߚ`8`zSL<*Rv1p6m~GIm*8ʪ6oMܙ3ZsjH @ @ 0AdS][nP:A~x7vm\5Su%q~ /4;Ͻv Ulqkp?G9;9_A~U  @ @ @fCB6·fz@8l+ O?ͷ5{:Wl &ƍ7_f4w^Zq==~sԸD߯>M6^j{A~U  @ @ @fCB]Vf ?M^On[ kb&[Ԫt~?8zUj?hlOŕԪ;6X|E+귿4)6d6Ҵwquٳ?]=Uy$@ @ @ U^z{/w{ӭwŹ_^mկ kR>x䱿_WJ缝M6*/zCN3orCm]k!(wx͗WޝW?  @ @ @\@_#)Szʕ>$ >ǟ|V/ k/:Ʋ4yşxgf<$o:Ԯ9rT뾕UnrаfM=pqEWUm`~qG -{IS7\8gF>}{ŗ^oiBKtXW[oϓ.;nM$@ @ @U^~G2yt]U 8Kc„ _H+:CO8xGsp'Ɗ/[jިG;]fD?~:Ҹ{ʻ-ZdFSx[Ӏ @ @ @`6(źµY{+d0O??aXknqz?@̋)݅׿n\kk<ָoiuX<Ïٸ&S˟reG/;~,\G?juz8׉o&Rtק6n~u >Й^;U붫bg8knˮa*V_m8_5u[:璸{s]{ @ @ @O ̖#'ߔnRn<ȓ;#ߎDBeI/H,fKg+ @ @ @h =zv?`mmm1u1}7O @ @ @v   @ @ @ bP(O gI7|'v\ϖ֍O+ @ @ @3qo- < qaǴ.58bV# @ @ @tKu;D o3W_g~L|ksՈ @ @ @% .ymI&;ǟk}\ @ @ @% (I @ @ @ @(t@W @ @ @ @+`D~{O @ @ @:P@߁"@ @ @ @(L:G @ @ @ @@b]P耮tA @ @ @W@^A @ @ @ @(t`"@ @ @ @*PJ[Ov @ @ @ б @ @ @hl1jܔpybB}7ޟ("v_g`m4*źM: D^5:z(ĕ@>^vݳ"6j.k/;W @ @ @ @fi\Иۻ&.d68OF= _|8rA `^ 8M  @ @ @v.?wQ_oP ɥ-p&G~1t_ dQ`м_e ^1~Ɯ}o9 @ @ @f ?eayZ7o,6 :㿨Ͽ(s,Mq?Cf*RslE'^UʦQpbc)+ܽw1ij]o5MU>4>D-_0g|.fnjO;+_?>[)H1A iՋe;H,u @ @ @[P, )= _;>ι, }|:%z#|myaTew<36pR/P8xc9ϼy\Ș,/i,6?X:-B687O-k|uP8`Ӆ\#u3xkxߟƘOKϽ犟70}'P:·fS@>Y9kWjSǧjЫ߉uǸHyO7[hӉqu#3If[o>[0[ޠ_}^4~G`\olք6Xp7oxr wwPY{ls͂Mt씝L=5}XjzKĀCTDžoܥv#;i*#ᢱ}JGҝ|Bsϴ<7. `??+S@K>0ŶJϜUAf!(,ï+>L*}bi|k +Ⴑ[8nm+w=c G]?S_h/ۨf>z5a~#N @ @ @f9&O!wZ>4f Ǫ_6Bl/}Zz< Zu,x靉qe6~ܗ#OiX|ޥv װ7牵]ώ4M~*)`?GKەam 1Jojx%oR|S`?<%RǟƟI<}ʀlZ"Ҝ A~:>&AidB:FwoQg}̐J:g,^~HxqSǛ٥R|t}{GoesɟƔӱS?ͮ+ﯭA~H#ͤ2=cF cwpy6l|*ceR9ёf_He}>x %4?}Pi]=d < һ2[vA!@ @ @ @`m G+[^׍ٔi$Y?m?ۻFT-7m|e sǏX^ v;1zܔRTam lZ_v;tS9qĂFݗ*f#Wg ?:F˸,NR~Bcoz7^Ei*x,4u׼9eʠd84!]AO_~dmp%a?5[gJBZgƖf0H+Gۧ W74z,4H1yV7a}P]Oi}Z>`RٿT88]VN֭ocL_9| :ߘ6 ]6? SC+{m-U*9lyK1 P7u]]y 1*}7Uqx+kָݗ7>?AEFn?M_Y  @ @ @Ei6=#4C)Oʦ&/4BK.Oui+x`X`o6}*Mi KZ?}s*]6b2 Ӛc>`O֥QvW%JܧS)^oڼOwM}IqӖH}xPdPAk7^#һS㉗<҇SueocozAHf},n[[LiɄd^q%rj'O  @ @ @G`ӣJ֠O_?}l =)++}Wт/in{T[Gn q_M~Ccb=>K&ΦO] һ:")eQxw&iUZڠGM!>`hT)O~㒖15vJ:έ7O @ @ @`׀x%cξ[or?( .ӘHkʧTOF/h]ӳ&/C_֖7A6J5.U[IV4A27J5?[a! @ @ @f ?}\, 9@ ʩ+rĵ#bGc6Wҧ>P?΄ҺuYr_@e_>3kal_N;U5t:?<>/8O830!ʠ54S@y sg7_dך2Zx FT]:?*eU}{=twUX8zt .;-O wߴCұd'!S_låR!/%@ @ @ 0 b]!ij`ISȧS9w!1ߜ=gx;1~uB_d韟])MuF%)7T>4}Z\x!  _MFէS8|%ξgt4yҺRs?ޘP1^>~w"\ -ҵιwtiKT̠1lKSӌ!jטt+ V6=\{H-<"?է~sR]">/=!μktG犽7Z#TWһ,ϾyyRn+&@ @ @ @`R,|}Y+Vү4}qƫ%]B/Hv֜Oalu ֗< ̗jo _~xk̤RRg# Ϋ #'ƈ"}g-ZS73z7䗟샏3N)08Oj6*SY^RfiJf2  @ @ @ #=x{5WGTߑwW_])qUrD~w= @ @ @ 0 ߆wrnmgf;3#>Hkէb/ @ @ @mxߝ,vO1""l)>%[ 9p-(K @ @ @Aߎ2ƯhzS*}{ry;B]kgzWdXqH.~B#@ @ @ @tBmmm]MM[f3ѻg!zd @ @ @t\ @ @ @T +5l @ @ @ @n(L:G|.O @ @ @$BX+ ρ @ @ @ - @ @ @ @ @ @ @ 02܇[ @ @ @ @2A? @ @ @ 0 gV @ @ @ @@X,  @ @ @ @L `DL @ @ @( ~  @ @ @ @L ȟ ^[ @ @ @ @eBX+ } @ @ @ @@7 ߍ.M @ @ @ '@ @ @ @( F|&@ @ @ @ bP(4O @ @ @t ] @ @ @4'`jd @ @ @ @nwK @ @ @ @ɨ'@ @ @ @ t$@ @ @ @ QO @ @ @AP[[[WSS vI @ @ @ @@X,  @ @ @ @n0~7$ @ @ @hNd @ @ @ @n0"] @ @ @4' oNF= @ @ @A~7$ @ @ @hNP[[[WSSq @ @ @ @@ ߅.E @ @ @Z$8 @ @ @BԩSzхt) @ @ @ @9BX+ WO @ @ @t ] @ @ @$Pi @ @ @ @@q  @ @ @ @ ?& @ @ @ @]%: @ @ @ @ @X, M5!@ @ @ @:[? @ @ @h X @ @ @ @w  @ @ @ @@+ bP(M  @ @ @ @0"dK @ @ @ oS @ @ @ @@g ;KV @ @ @ @ bXW(pS @ @ @ @w @ @ @ @@;L< @ @ @ @w @ @ @ @@;s* @ @ @hA~G @ @ @C@< @ @ @ @(tt#@ @ @ @ P(uB : @ @ @hSw @ @ @ @@;oS  @ @ @ @@G Ѣ#@ @ @ @ϩ @ @ @ @-? @ @ @ Bmmm]MMM;p* @ @ @ QFw~ @ @ @ @@;Q @ @ @ @ SNѣGG @ @ @ @bXW(хS  @ @ @ @w~ @ @ @ @@jkkjjj:+] @ @ @ @(e8 @ @ @A~8 @ @ @t CuB @ @ @:FP, B @ @ @ @]F䷋ @ @ @ @c7 @ @ @ .A~L @ @ @:VP, B7 @ @ @ @MF䷉I @ @ @ @sW @ @ @ &A~؜D @ @ @:GP, BW @ @ @ @UVqiL @ @ @:Ww @ @ @ *A~4&@ @ @ @+ \_ @ @ @ @V [ť1 @ @ @\A~ @ @ @JP[[[WSSӪ4&@ @ @ @:GP, BW @ @ @ @Uo @ @ @ @s\_ @ @ @ @V *.  @ @ @ @@ ;W @ @ @ @UVqiL @ @ @:WP[[[WSSӹW; @ @ @ K\L @ @ @ @w @ @ @ @\S#Wc @ @ @ @(źBйW; @ @ @ K@I# @ @ @ 5ں @ @ @ @U uYA @ @ @ @]FB @ @ @ @eA~FZ @ @ @ @.(źBet! @ @ @ @y#q @ @ @t ] @ @ @4/ o @ @ @ bXW(.H @ @ @(`D&j @ @ @ @@ ޅ  @ @ @ @M @ @ @ @n(źBm7 @ @ @ @tAt [ @ @ @ @L  @ @ @ @ @ @ @ @@  @ @ @ 0]@? @ @ @vA~7@ @ @ @ jkkjjj"@ @ @ @MP, B݀  @ @ @ @L?gÛ?BKRE@,"EdM@, #H@eQFA (kY,`䗓g{4M`yxrr=y@@@@@@@b`E~?&       UV_ @@@@@@@b /G@@@@@@@*@Ղ3@@@@@@@]k *0@@@@@@@aE>       A~=        )''       l6[L&SL)        A~1 Jvv BBJK peI?!dJY"der=wJDpW<Xwj ӭ@@@@@@Kk ʫ 0elYݑ;C_m+ʝJU݆7f<Ҽa_FlfJHv@@@@@@@#z5R_&ɦtoҮ2j@ݶ\~L>'_%Z0NjՊZ       APZϝ;/:>'ȿ)oծde],-uT\ѩS@@@@@@(iį ?AU&OAC-:^9KI%Qիij)"      @I0fd*I9`&32#ȿDՂ3@@@@@@/22X&!aaa2)+\ Am]*Jv-W-FѢ+ᬯIDATunn4k44       Wn 򓒒$&&Hg,{">A~,Ѓlk8ߢՓv*=ݣө䗜g7E@@@@@j5 G|| 2^,˸qPA~q D 3ұsB 3FTa_ tn      @k*_/CWűށi2s&tefNI?tXN:#AAbX[#wI_A Oo^~9)!!%7,Qih;jJP>S ûKߖʕ*5?|'9qpd?/fHoɥ:Ѓ|Z 設rSgITj2'      @~|B?1| U ߲M7WOoJ>9 mJmq<{M2zqoz\^"p[˸EZʶ#ˀ+ľm^E‚ё:_TLA@@@@@@ x Ǽ~az2+nfY^ٻϰ6_~L>װ-.S 3zч]} sssex|x` 2ɘءZ֭MUZwXTMUЀ      @  ˯)#^1'O%7mqCHgf̓5k7]+J9W>ѵLf\`(URTaA m?dXnp6{Qڛ6i$S'ڻ>䛭8$3ewS S@@@@@@A@/W 0YyL&XFZ8UMV$ߙۦVwfG]uk˂\GEYfYZ9vw})5      W@;J|g Z'̐_l׽ $nX6msdj[Y{_w|Vm_ צsqw|cZ@@@@@@(J0?O>8+{ӽɃGi+/Ljmemڛֈ䄙. 2? Pd @@@@@@#TŠ|,_;M?Wlh85^>߰UY5P=֫+sgMv ?''Wz=;#:Ұrg3Ey8 #b2fηq9b* v͕f-;9,Z8מ$ΒմՔ@@@@@@X "##v}xbJպW,mVzZٯ _v[9}+ۧnCJueʸt5?ˣ'-thOiѬԹ\}Ymïv0:{bk>7zBoHC      Ako^/QQs/H^}A]6'&kAdڍX[{'궩J ?arIY56{eŲõ'A        P&ᖠB_oh2^7::>F^רVl,J\fG竤T)ߵ_rE,fV.S&D_#;wս{i;}7_[(+X澝=ٸnw-xAN:}F:vyz=HTPnth$6.uI-\5T?9vw]:؋.EF:YFe9FȤ5mk5(3fHݹR      %C 7Րee[5\p =C^9No{:A+JN1[ ^<;e~ ރ%y O䵲^],eTZY:R)]ĉS|ŇO] ?SfKU]ϝ;/:>RW^]]=&;ݭE(֖.OoAJY_UßН,       p fd 9/0qj|ak/ …ҹ{_ڭKr_{} Ӭ)n9W N9yꌤpnx0Sj#4ǀg>M[3:1V6i/(       pM1 `|^z׺|uk~ݞ|\ toGv'IL]:P ??/@@@@@@k\k ƿFM2e&͎-d8S٢Yy-vc{jg9""\NmΕ~3g/G .*Y#Ұ+ҲM7{ Q>ܭ^#|N<&|hhYѭ˦&8L.۸|g.[%Y?yΥ͹PJ%iyicQrujfN. K*;W%jez < ](       P"{/Gw qA[[ˋZq~*x_裿f硌#~0C<.Dʕ ݿ]uazs_QkTPc.9rppY **u)jk۵dm;>}"AyU+Wʕ*ȭEHv]QWG.]sKNv*]"eʄHjrӍ7      ɺb @ 5       #yL@@@@@@@| @@@@@@@ zL@@@@@@@lL&$@@@@@@@@ X)        ` ȷK       @?JT@IDAT ;K ٗ%µ\ҽDn (%[JR"k$"dM֫(Z өs|&3gfw|g;yΔ~3&aB@@@@@@@EјK@@@@@@@A~]~@@@@@@@1~Z       P#      A~zZ       P#      A~zZ       P|H$8       @zhGkh       u\#      =~@@@@@@@:.@:p       %@^       q:p       %D"1ߟ^5       Qze#      A~zZ       PG|p8s       /|>_z        PG@@@@@@@SDb~?=[G@@@@@@@c1ձkr@@@@@@@H[54 @@@@@@@. '5#      I'[hLڙ ?mE@@@@@@j@1>@@@@@@@Cgm       uU y@@@@@@@ -|h4ҲqU((Pԍ      =TD}Xq       H'*O:;D`       }x+AǛ[ew*g       @<g`u*K4WFcVލn:O.gv@@@@@@@pֲ5~eVV8 DZfͭu@@@@@@@xP~3׹lmzūc6fbu9:ן[H$bViL@@@@@@@_ un:[ۜZ`׺ _/I^|7gˊ?GOn5@@@@@@@BٵOZ6 ^#f3 ֎Z[5p8l@*m       TLถ"gWhYYYvo ).AVo|+ȟl( 3fL@@@@@@@X6I6 ?x = _{[=7~07r$_+      ~HTdܠ}"O*999~_S kM|+ȷzk?̋>ǜ       !0yNb:~ }iO_@@@@@@@(M _{[?o# #O/**L|g@@@@@@@* Ik?FޯVeVsn@@@@@@@dRkc|鑿`ED][ C@/{#/m[YG@@@@@@V 8G~VV# 0&˚Xɍ @Z4I磲d       @A{=i&Oޡ+#!~&?=46;I@@@@@@@A~4|32|N޲HE"@g`$@@@@@@ sc1@?HEz?sW~f/Z      P~|#1%M)RrjqY      !x,+3ȷ 3݄# g}       X%''G%++K|>G& ݥ!@UW*u"     ?G"% I0(ЂLK;\      @rh4]3ybhL{. ϵ#     _ .e B *T@@@@@@ ]= ݷЂtU!@_ԉ      .VLH8P($`PFolޣdC 2]n,@6 $6pm      WʟGјhcT~4n ׭"     uM ݏ.e B *T@@@@@@ ]= ݷЂtU!A"_zE<EUZ ˯gYgQA@@@@@*Sʟ Z2+BJj:߰a\֣}33<~d;I$S~tѾXErvU|\ܳ      @@A~4|2pU@_ ?m`d]}|'4xQ`L6"lQPtQ,i3a8O6ْ($elZy"ej:?Iv3K?\{=ϥù]~Q*;jgYr]#e׫k! f#%N{Ar(OT0w2aS^^]?P      e C m!ms,ncG+{2eaHYs֝la޶ {dxC&<#k/׭ҬYSWY&J <)ҸqcWY+-\ n^{ʄ'5>b]Q |P32ᑧvr뀄۝= חY/Nweқ޳7}QDTX0     @RS?~ZZUV0s/\]:[Zc}*|W$ȟiP]x_asC@Mӧϔg5V3r%\|e|~4jU-7.K~g^"=߽x~2plCwwT믫ou۠Mz* &Mg,;D?;9*n*ua 铰#     P iXw<"KN?ƗįǙv9U(d|W SaD ;r 5J}d۶mvǎ{Hgo{=S.G6lh6__x;Vi][:AvvUTswKǸ-O<y㍷USAgfȌ/m*5:8Ef~A%|q),"     i jnoEeB ck,9ݑM/[ =߽Ajeq [ļ HMAEF>D7Ge _:XPSA+/&O<1?ce]L^5_$jx=h^)3d)/`ԂĢCfz[u_jut(yyv肾ѰaCWYyVˣž     T\ OQ%lw7wO!)2|彛Ƞt!W9Eyek˘7׺IҠI3dk2羮~7{%ʩ'R D ˮtF+vHҍۤ`KΒxd*˷n-f͚J P9_J5؞DiР]VڂW m,iH͌woVQ)#=!{T|` {^ZWrC6X  OoI2G@@@@@z IK,6r\{U۠v E% JQAоܢ븇>ʯy{e%{ͻ*s%S Ax1]vq[2-g r__((S&y'c[^}A #tQrr__TT$?| u!̯}rA򮨗Y%5vvwG?O?Y$_~3t҉r%ʮbʕoOVY~6^.عIw߽Ķ'?R ?//OK㸕='1:ȿJ˖^=Yͬ ckaȐ;dȐFFja`|iҤDAۍ"c9Z4i!     X 7VONܴߢah۠jl@Yg8nt9:uM&|/ %E#۶QhR|=X";:yօd'\g-ߊ߷DdUI $2 Q{{+0א)ș2Rwrl|p9`wx7:ڱ}{ zh>% -ZwV0IU߯?I'&>px7}3VlVz|yᱮ7mlذ.ud0{˕})dݛ.|rMg/,ٳ_5GCdסȣ=Z-|Ⓩ˞{(q#G{eu2A~\" @@@@@+ro%{-$O{s)Yj][8<w5AO5rj9"Gxoܷ巿 ;EJEuUVW |gZu\wͲǟڵ{1rC+¤y~X.>:UXОo+&d.'FG,TPP(C&K~,+%_nץ OM'6y̳ΐc,1 ֥:DӦ='3}DyYDߝ/5'iW^k6U;YVz_q]/Gܱ/MGENGsOOA     e #mkAKY+ggK~a7Uu}鍥ayvs[K2[M  Ӿ 4O`zRA}9#K okOkuAc3N;K]6eo@Ρ"ug;zUW$a5pN;EnuZ\Mkibpڬy=yh;~p2>Jzk՞w~w9+_}<0aWЬ;z|Ԋ#_۶˕H'2Nԧ(2g|R1jpiԨ}ƍ/X#AM     e Xs֧GւtV^;e. A/e:$?TBm+!/ݧVgax{?d֭[o? ƍ%҉z{|]=v%^(xq5eEuryW*+߶mtve{PZ/_B6噟hذ(8uww/PAsZҿ΢A(9(^W^ w^zUzrzI>[Dƿs7s]?q {=uQ|pqv¬YegU|K9     e X3A~$"MP($sƦ^Y69{&D<ǵ˨wnG9Uk?k_ˋKa!yM;$XZ]X_Gm꭛^]OeE z56)W^RUk{A,XӍ7]'i%^zt5~IΝO> t̻RYAk)uߦMksDf0)DZO>5o#"4pÇto|E^]A~WoO}IHo2^2I̩ ggҹ~?o|N92_b/#Da@@@@@VLO)-ȩö疄eڜ#/[]ƼUG;*_ ȏ'Wue䏺| ѡ/1zv'3}72' ksi:Z9_v{ݮ2Je2e=zyq]d]N n}št\`3e&oɵWs4i47k}]vqu?|=+.XEO>Y(i5pi~UeUaaoڲe\|QsA~vxa狷.#ȷ)e:5kJ+v]όH;Fpm'W/k#*3~zӞs}= SF/yyҮ=ErH_{Mއ25t2RjC{SN9I9 ]]3?In os}@}9v} 33dƌcDN~H:..N0rч']i"ܹܺ=n{I'ɓA>ggX ˅;'ȏKD!     qR=yӻ uNH>xciQHHfCUwXRv iWA~ h8:| yne :H>Yp'nm׿ΖkV7@O6אxQFv]ae^wo.&ׯt8_ nG-wӭ믽%c>,D=Ľ#x|GsN=> ɳ}͵hzQ)M{pkOn/hoMNy ζʜA9vS$'g9߫ww w%/2taBe0F.a`P #\r}5kT>c9AЦMw~2_bXg2lHZg 5{/>H DoI0G@@@@@l|/)=o#ʖާ5@qDMў(Ke 2|nȮۻ@|HծWekoʸ 8ce]d 5shz ڧ+o={ UJ s/x(%3%b_ye/9z 'Ng)sDf3"75kLoA{5N/@zn/YuƻWN tX`kœ'?c0۬ ِs5ߝΏ;d] u{O >yyuwKYrl͝@@@@@:.roċG~޾H8$7ˀ{Hr6vְLxoc|{Gʗ+_\c[jJGAD}'po#r{OX _s5}v!jڛ'& |i]&5d|۶-0z? ۋscy J7l(W?aӵv)޷k~w{QGi"e?3/;`|EyCOi.ye)?utvswsyO?#up)mkɍnի7P5ChXكYs-7믽e^]=ʉ=Ү=|SQFeB?Opa~1o.k./zDBay=Z| z3N ߹-ae 6d7F$AmWT*U~g(ҷҼmnA^UWJf*A@@@@@A>A~<3Ef| #Oqr {\.6.^ڦc;Ftx\c#!:=}Ms#     TL ?^f _3 ԕ _{7ٓFz2u      @ !xf^Wܐ ̙FRģF+vHR      @z 3~z?8u%_ ?Ctǎl@@@@@@2R ?#\]Jw9/olڔ7l@v߽Yl@@@@@@ۦV_|Y=񭹳9#_/HC|i|gz*m38e@@@@@@@D`޲,Xc[|퍯~_3BeJZWMZAέ^PHVdʯi@@@@@@@:,`Wr;{̟V| 5̟,Z%Kt>*!3vs       @Z h?닰l*q-EkG{}%;aa~8=/7IF!      d@$*~kL]5fLae7_!wL [sk} u=kõr        )=گP4 ?ސzvHN*+̷BlY_02֊ $`        @ }"zokT,${5}ee2[`0\}]~[        @V s6ߚ;x[%:cz`m7w6ڭu       pllmzūkegkei]ZUfax׭r       VZۼxxjuo]3Ol@@@@@@@ Xh9:}h4$3q?glr>,#       H'*oNȏwT(C@@@@@@HU"u6w"       @˝       h4"       @_1?F@@@@@@@R+@@@@@@@A~8@@@@@@@JEјJ @@@@@@@R O͍@@@@@@@֯V*E@@@@@@@ 58 @@@@@@@* ȯV*E@@@@@@@ 58 @@@@@@@* ȯV*E@@@@@@@ 5_$Ԏ(@@@@@@@T_4|J@@@@@@@@ 5O͍@@@@@@@:#?U ("      M NO'*W       @>Qy2։ 'ZN}@@@@@@@' -;.^Y>*PV9s@@@@@@@ 8{ݮVYyzeH$_y'EZy3 @@@@@@@2+X:OsWVje|+whTen!YY@@@@@@@'`kGz]׹lmWVoVo͍ :Ή2       ~@IDAT0 y |ouY%7Ǵ2YΝ[o~ϖBcXmr@@@@@@@&>]ծQk8"[?o_foݱv M_xY\~hU*5s         R ?++5w櫍A'{~i m[~ٽOD4#       P@$*~kL]+"6rXhoޞjcsO_'g=C]^쉿1A磲Ecc\&@@@@@@@*Y`M~Lf}MƧ޵g~Ivv+ FxJ^UO&/1&į䇐@@@@@@@O\2 {J˝c0k]=55{y=lOt83XC@@@@@@@ -2&g C[a~S׊ T@Vo|+ȟl( ~@@@@@@@BߴO)p@V?>{,ކhhUiꑯD.Gj"       P, Od[%''^tתVo ;?}9@@@@@@@C`[A4ux:k|iO_@@@@@@@(M _{[?oGG"џ_TT$#76[:       @U XA%77Z?!~ܡx] u@@@@@@@ |#rt:;֯H+"효j M+-d@/{#/m[2@@@@@@A~NN#?++KO_R|SaLf}5Cɋh'ʒ]j%@@@@@@ 7О:~E{O\"į븀}fq.@@@@@@ Gјϗ=c+sh}N޲Hm^>j\̃ _w      TA~%ȧ7~U>ԍ@-XB@@@@@)Fo|e>7(h|H*I ]N:5       P#߂ԻCe W`p{0"      +xRHvvdeeI gGĂtU!@_ԉ      .VLH8P($`PFolޣdC 2]n,@6 $6pm      Wʟ kSΕ:ZwK @@@@@@@A~$~GUh|@q=ϼ[HA~\6      PGRhe4 ?o%cus      @H97X[guU y@@@@@)w? 5 PN@@@@@@t'KNNdggKVVё󭟷>zI,Hw)k PUJ      "`a B e=J60 j@/?/"Gy\" <_m{33/vg)guFmPPP(>2HN=>      e X3A>A~Y H7l(c{ _`ߒy'hTNҩsG*cO=CGUM|qszmY8q<{y9M&L_[.@@@@@@jH9ȏD"L'3Е4Y"%;QO>pT M1y终,[o2]:Kd0uX0ӭMdRCVEe޲Hp)PAOʜW߰ƕ}{kgB;W^}e6wn+W٥<2Z?`?{ݹkoɧ bssڛ=KlH`˖w˾Iǎ^zI]n nzճwSʠA7{, Yhk߻Gڴi*Kuegd֬^J{:w OxDZ8sx;\{UҾY6e\Ԣ>Dd>@@@@@ 7B%u I 7̯H?Ӡ|6V 0*@@@@@H$rc@ qU]n#ȯj,9yW43.ٛW4F^ưΩBA'u  #2|n,S Pzt#۶m[=vC>{뙺pY>CT~}yg*eHx 5ȷ& :uú?C\WJC'*+)ӜrIr۠^xd\Ϫ q3t|8򝡻՞\us|MXONb|~U| 9     @Rgcv- )'zG˕ dFYr!;I#7_>*{{#@/t88(D\d JTzsT%*5kl?V5^ _$j kq=h^)3d)/`'ZuӞ3_w+o'( :q_믾҅򋊊-8_xQsĊ~zQCۑJmcd˩ _ϯ=%\(ݺ_,*2A~@@@@@򍀃Ud˾_ᯬ"#!.4G+) .c\ko/mAfd?m\}]/nYK웕SO5ڥD9 ? ])yyPއv^ւ/,&;^hذуwgJe@JDA53*31m'M/G]/ 'ptE7z{_]-,_a*=ztS}A #tQrr_ȟ%o% N%W\9 WyyWKݬuZMj^AD-,}!rG:O[by˖/|oخ{ur~K7 狗?"?B/v_SO=E\=¨K?Mbߍ<3uFZ-}^-^6m?1GG8ps?onȧ/la|iҤ=U @@@@@2R#dY-1pXmFol ЂfSO@o~&>̗܆MǢm({4)>N{j,AB2o[["2p*a{teC{+029cJ=rs̰ԝ3B>?xy͹v,j`?( 4pc9#|r}K-Wd ֯]z^׵g'# XI ?#B_xĮ=CYLD+ddUqwit7W;%ꑟg.`¸u+<3Cٔ+7neo\{Uig.t0>%]j}rgL% #`_N_hӦYƋ:KdWQ?;y     $`O7:#kgLY; [?o>|7.e[z.v{>ƫ3m{7yw,hL6&!oòtm避nxwʪ;:¾n)c=T3uIfU}Gp w~h^h?qdyy%m'Avm@Xi'XҫԓSJǻ;n'-^(q|oM {[Gsy򩱢KtwW9k[ i }yikε>}@'o7믟9AE@@@@@ )?Dy5dI݊w{ky1u9>i;_0wNk);-mwvorUxcun曯8e?k9c̡u_zX4y4o]Û?8W=FcA{j p=s~@׷SAA k,]^H/\|].<5i XI _|=UhJX;C2d]/pvW>2~ܓv]hg]e{ה;xJA0p wسRA%_ȝj{K/4G~XCs9Ηb^]j|A_rё 2 gfZùϑ;<׻/y^- 7Y@@@@@R򍡦c]?' .CǝliRj̍/no~_/mzciX8Ҡ/Ix&w VruیӚt&ҟ?_E K娣 Z՘~[c|WوC#*ӕ[oOUƷ쭐^_0;dCc^RG uiti-V5O _}c_uFЮó5w/?_8`<`΀&?̵36h7tQ~w7O?wDo>htx= Ǎ\ ck9ĢE! kO=ѨåQF>7!} >[p 9ie"|      H97ғ͊K~Մ^ih-4p78]LCC%ɼJo8A~>:ŋؗp}si'nzce?yoH4*ד&c<"Qoo=ǎ{ <#:{\v\tQ'Wwm۶KnW؁V=eRo649yQe{#MV%<𵯋%ް}搼٦,./ۣ6ywM|PWW⧟ tkҠt^zVQs!s/Ȃ KϹQ{S9eoIW4Hܩ{SʠA7{wuWV z۴i-:"@3:Dޥաۆ麯zN;u= ɜWߐ_|5{i{x9\r;Bgg]XyKt堃1\Vjޜk|fbَx8ο+swޯ9rb/#GXAӮgҹve }r2      '/Rv>2owS RDEET,ܡz*zVDQATlȩHRDņm "EHd~03l6d7̽<33uy="wn9SE{.rN!Oyʂn ^i#J$xr+ =^9}zKޛ]r}5zUD?ȿ+ ǟ^"cn)trn߁@xQҥ˞åAſȅ.\ÌgO?V45jl^)h@S/}|wOw^7[ 7]s?eoMZ5rE.\-Z,[o4$nڵ367A|$7g2J: ><ܿQt4&@@@@@+vo /[ݓͰ:G~m?ʤ_{6.)ʄw=e፥dSֹ}#u],ayLm+@ oSFPBmK.AO=,-Z/e˖{vOD/lThoSbA^hhjt)'ȠAEk"~L0ՔWeA^K^=N~];=u5>쯇n* }_yWz __pg.{:d33oذAz(&7 Fϋ.7Li>e=]mfsRu L?k֛rםUy5r!1=i;.iY/Ls]K/ͿnFߧ)D@@@@@ |+|)<-P%.z^yu~X;~ KthSOAΡLEEEV~iOmx-}9gJzyv)))!`lH5:d5-wl3ٿͬW7='O;1Sg[?!SOS`ew33&Myww;={VV:j9~+C<>F?{stAGr~ր$O<2?^Z&tz'0N~e v֭^v>( '%;7ޒ;'lo֨t:C亡Ww}#}      @OcR{U+dY b8_R_dm Jb5+둯RVu17,!=ddC|x|1 R~u p׿p֖ȷ}g B V᭽~{еV=mg͚ m3!};o'+W4MxyHnM{g{˖-νdwp :-yf >=lFVN:^:,wխş}wm4zKxocL}>)O4o}z7uGulzvt8/lvriHǝvt(w? ٺO0z}+W_OS{ɇay7vo{XĕRؒJB3v"Ł_'O+2䗖Zzωzneih>6RwL+;,w*W=^`^}:7 w^L oRkXmU' V5`OO?5S} qGFC)Qm=_)OFr~?oJSN)^n?z`K)B%hcǍ.]LsϾ(>]nj{f}:w#:LgwI_Z6lԩ=G~"7d+&եQ=iۿ@|Hf3eĩ$S!z5rl5HcZƒ|SA:0<;t.Oe9Q=fm2wN:)OtS]~`j[^ #r 6yN6mӞ:zΤ#{ߦߺ0v~T7ofʆ 䞻';VdSgvOk-^+gy^K./s}iRPP _k:Kڦ;ȢEA7ўL]>7ˬaOL     H;ȷmNszG~޾H\4oRm-*Hx+ׅe[+de2gS佅_Bk[fnXU1o񷽢8"~†ؐ@&| 43m nSko|/GGUL~P^}uJ׮5GSW 3}nr}N;{w.{ZaNON;d}^6n()ӀS!ɂ{`5IUg={j.#ﯫzOz>]FO_[5b}L<&ZOplX&nxh|N3xNIeF^_gfO8N>Ks|`rs\ε~ ˯uBl-^i=UAM6;r*gZOZ_qH:-XPFcO^yo}^yyBG0L3п<,;Y#n~ȩ     U ȧG~ګeúբswٺMcپu/5O%ۨy++z(9ᒢ;Na yQ k/l,MLX d<3P{/_B֗vVܾ};ilS/T#G(og>Nۯ__ѳ{ƎWW !?ws>ץKKKM6۴6mZK(JY}9mlVjKw~y[_0ݷ>QGW?…F֋'m&^]d l:lSGϧ+RjJ      @OcRUqZ)P$44/h\Za~\'ޖ [A~`v~a+"AkWW AſȌRtai׮muOF _/Nkҿ^V}E$//F9yŗe{=O:l;=@@@@@A>A~<3܇BVx9s在_ AXu?S{8W^y"ס oe >!96      @ 7u P|>y) ?=*ןRTB@@@@@u|ϱ\V~OwᰔKYY¾ D {4'= /jJqcd=vK.@@@@@@[C)k|ơPh偀=_Ey,`mɄ:';ɹ74<񆑕^b?V      @ [w,믮$ȯd@C 򕿨h^]N4mDڶmp;@@@@@@rO ޛm !@&R ?D@@@@@n?Wyh}z{o τ*m"     dɟ # R^^.eee2nn lY l!     _?ߧ+wrA      .H$ ro<z葟{3n s      @H;ȷX_ G*H4E8_ d?t}?Q@@@@@@4_ 岴8mH1b7jO} _{H      Բ@A~8BZ>ݚ=\MaDf5 ptt{*\      h,ʽŚ 镟{g[ϭ"     '@_CC+Ҙ̜fEB =ɓMrF@@@@@@,|`0ӈ5#`0,ʊu1DM)s@ӶY@ld8Q@@@@@@ g's#מZX>^,ҲI@z@@@@@@@ +4ğ9/,KcrPn{B|퍯?:%t_o׋0_a~81{=m6l       TQ Y.&,G?߄z27 uOMzL       dB@{ShxA~! Xc*d3٦ =M8$_/ We5A^|X        L ie}cMl"zW _Mo7s u:7A@@@@@@@ \7swxo8}_CԫEy6~f9       a.wo6mǽ_v:V]/7exs0˺΄       @<w oM`omzsMHonu:s@@@@@@@ y>f=^"ݡ}eS9       U0h96Do0!)yrw@@@@@@@ C{D:H$ mra       @T'wp j1w,#       @Ua@@@@@@@jW@@@@@@@H*@:\       @M $ r仃D˩`Q@@@@@@@x>r ߄̠M9s@@@@@@@ {ݮ,<^;@4sy:Ogs9w@@@@@@@ svD?z6^egV/{p[/,hg֙#       Oʻ`0h:7f/^v+%ژrt?&7H$&45s       /`By^P^7a殟l]|C| ϒ|[,\UV_^cHvن       `@Utl?)m[D0_}wAIvWz̤*6w&?5•p       *pPcv*C<'7!'z仇_fo"?kǐ>(m$LDC9        D"+䛥Qyaa6"( Moگ4ȷz׋eC|_^^.4{ⷴ2Ooak       @ ,-yaYm}]{w^^&&=?P| !⢀L5BC@@@@@@ h?rʤÖ1Ooz7 _{kkFpGwyXC@@@@@@@ !&v`!MGVS>m*Ąn?e       0[7 ȠJA~.=@@@@@@ɂ|͏&ȷFѡ7n(涰[:       @&L?b),,tBN}'cF        [=c$[: =~uz俿0",ʊuVlz E6 Ȟҵc(O3D@@@@@@A~AA#?//O*O_QuiLf ǡQ@ oI&:>      @f5#}^i h?k~W@@@@@@@A5},ƽ&ga N8sasVq      i 3W^Ȕ3%K      "@_CC돞U&hV+[A@ @@@@@@ X(iZ@4'@ ; ?Gn      ɟR,/yyy} p~MhL+Dwso s      @ ȯ ddB^ g      9?WG~$ǪsxG~plM{g,L:M^x%rZJ=V|f C*C^/NyǟZ?zyp~tW=̜ ''_|^x.,~*SYYλbe[ءa=${ܝf\ܧܸqctwQ.󲉿)wKsr]_ѩEݤ~sF@@@@T |~_ ILx,n_ ڇeͲXҨ<<+s2ȟ>iy1QG)W^k33f͚y]:'..qu{W^uu*[N׳_g &LS߽j_RR"7\? +8]TlzW\%} HxU /x,Yk&MK߾C5:_4}Ы≾2b$[[6:]z`Yg(ĿG=@@@@@:ҽK)֗{)Y#kRk}T @ե=+>- T(ׯwz;ewsuܾEICDCD;E^}\ )~ Ǟ'|9~ rG~"#Gbexm c&B     @aYc>"Vmp8,Rf}xMCJݪr€wOʣ2}JrQcҪY[s*߭=A ́X?,$'u.h"]w\hg?%kђ _XeMӼr9|2즡z./hOY=mÝoWn9O*/O=YOu?%O?SAuן~ 5oܸ܂r9Vs^s|NT|-l^zBiiާ[={Ք+~/vAQ;mS?ණ _wI_kā5칾dӴiSOYUVE]@@@@@LcsAo5 {ҷ8OvmWwqf5sΙf5yMt=zpg߽܇t9 _[o .Y*\s=;W_pn?^OVWQQ|-'v^F[a;^}*_VV.}O e2o'첳~a2pu#6뾾{ÇudcGˬt/:H5#zy1Zߡ`@@@@ȸAa>A~Ɵp!o׿))¦[XE#[Rb~{in\|9jVm6" Wj,PAp<kڳ9-ncXsdy߳*쪁XhX;Ke0[n7+/ptS-?=Amhl7eNT-fxOŜ{w10V:}r;Wk֭ɂ )-v7, #_w}CGF& 4)Ҷm{{VZ-<2]}cϲe-eȱnS }ic8l>ri'˘ѷBG7ё@@@@@2'@O+{tk|WA~>PmVwmoERniIA@4sηXCe)&[~۰m$YMk;|ŵW_}+.ZS[.]~EwOM,ڵu~as$O;FkA{n t̝{;nTt̟YN_\\,`y!Eg $wX@@@@@2&@O+o<6_hz$~[aM[oa{}^_&^H2&OUj3o_7Fu,yyɟ?A?T7i,쳗4miG~uK`}\ׯ_7b ^O>'0ᾉdwp-++aF9ϻ,     Ԙ@A+?kj!Fh/6 >Eqs[gj`h k塮/-l"~ACIoY*A5Qf ?OMoM&Òfr7)͗/_a ?Y*YrDQm뭶 ?'Uᅂ7o[1nO}=[8̿RSA9=/{qLi=[| :trnyAASV 5t{GxNAq以yd+uݓ2qm=ذaw3dVtbOwSv(jnt~T[Aַ~z _2sx^=ԓE{ͻ'scHZ7uG=H3O_@@@@@L6[^vI4„F8iryT0_V _H>=jf =֐t{G=/piGFf/ydb1VvmWnzg/@@@@Q|+&5zZA~8W(';7atKwhyʂn ^9V[I(?K2WV[AmNwyϹs޽Ow֓-_PkN_b'zMg]d-#jyM:ɹ}zzE7Jt31S) =|]t?Lm֬)zgW?cKwus N&/<]ȣSO+>V@@@@@ #{7 ݮL;󒢨LxTxcl(YunH}kg]* X^&x4J0h0gX w]|Fk#_t b|aibg7<|+ګ2{ןdoGk]ب> otf~,F5wo*%Xzyfk#7y?sU#޾dN&o޾eS$e]-:QG)W^XN     P& -eMe-$OeޒSKlSZv]i֬0eqErqǸ*,ϣC'_t,Ziaɟ|Bu}-=j]Tk׮n'4l-,,?~,'9N;VXΖ_S߫wO/&wkNG5l{:eMCEΕqc{3})ҶmOYx=9L}V/.ڋzȵ7fJ5:dmrK{Y-LG밭س^ ?ln#-ASXɶ ?{4R4Ot|Ny=OG 0ת7>~{YT "mрλnLe}:ߧ,AohӖ·Z3+񌔡2Yrs8_s=诺r-eǏ 7 S[y4uO>4j],g Ӿ֢Ϳ^|ſ^i"^2mcX%XuϜ)8ԓ=Q0kgUš?TF cM_s{;7gm/_}r?˭}wYuw˯/7q;t{&keUo!V@@@@@RH;ȷ3=R:RVҀ7鑟7|cMT=uN( ?Y/:A~^ T &Njz/KC^TcXyWgdASɷ=V7ounW{' 57#WDsnw6Q}S/2<ЦMΟ~j<J5jXz3f<+<<ٖlro\N~4U2:O͵^~Yϋ"fK6>wds/Ԛ WFerzdz-A/[&M\Boh;,hw *~޿Æ |{U|a<`yɉB1os?ps':.Ou?}q Pk^)K]_Ww}ީ:GZ/R\z"ѧR9W^}.nl}?|s{q ';6.cǎO;Gyfq~aNfqםɬYo{9ި;RTޮϸ:ի˯|R[ @@@@@ 'sV#r0IaPtت a+ׅe[+de2oro _rpK\hmKL J"2p:WGַORdvU~c={J'G>D!'4s﫽{:M2A'`RP#F 6lϬ^ً-÷;(;wItm՛hJzw~}ƍS{;e=^ p*$Y;u$UMJ}[]tqZ:;%X{һ颁fr6eΟ|bU /{~:`-/tRYHrJ>z]ɓw3ey5+/&/};H߾g_)#<3㹸A\v\YNoDNg:uh'rY\Q{Yb@жmeSI@Mo(,Vre@@@@@i 6vzg ӳJ'yA 5x价%l,V8_ Hdx/2gT]_ڵk[ӭ5׋Ӟ/Uim}㮑βF^|eN:>ήfN'[:ZA@@@@@ wZ?gVoDv| C+OsrN/ \,XP^y5׻Ӂ/:|5^P.ϛc#     TO .:{xh(Aro2]Tڢ      @ [!xnOG'ȯ!- P %ȟ<yWS"1TJ      -@rvh(AϓoG[C7q{7      9r [zE oxӦMm6 @@@@@@ h,Θ],"C )ϡ©"     Ԑ@Aj:TK Z|       (@E&      |4s% F j.@@@@@hih4rsq X |.@@@@@hiVu G*H4E8_ [A(g      @54eiqοېcnԞ@5ȑ@@@@@@e _Ejq8ѝCҵc]8W      `h,4TMǁzM@@@@@@-@_C=N.yaدcIT>yҲIn@T(A@@@@@@+voft|C4*+$5@Hfٳ}G}@@@@@@ wȏD"R^^.7nqs[7uq9{s9q@@@@@@@p/P b~W= u@@@@@@@ G~4p8l/++sHr<@@@@@@@a CJAA#?//O_{z#_/LC||-f@@@@@@@.7ȷ uq5qLv3&7CkqsI|} mrC        "Qѳ$hur:G~({䛜>no߱x- 7 _^ʧM /[T /SB@@@@@@q1~nA8k?&7s֋4__H>YCrtYF@@@@@@@ # #r`i' dG^ ݽeqQ@}^Uo+       @&Lo|=I-cv4ȷMYB2G镯=5̟|Xe'!k~p@@@@@@@! h?s^XV":_tJ#z;â?37~Zbgm&M@@@@@@@* D"+䛥Q{8}}6"(Qy*gF4A꺎;O\@@@@@@@rW'ZN&77eʿnʙ#       Ov]7e&y0~(@@@@@@@0&uD?zDz#߄菖np~f9       Lx}0unvS7^{z0ބ&7H$&We@@@@@@@ 0_&y(Mo'jSe57?KCopUPVZcx؆       @r`@Utl?)m[D0_}wAIb cׇfnp8loD>^\k@@@@@@@V:S9 <׫&w!̘D~mC׎!ٳ}P6 H~ÐR       aHTdź|4*/GۥH=JE|曡L!N_{䗗ˬ- z'[X0!       PKc2s^XV[zמ:|W ǛVoɟ鍯s32v'#      Y.a<2 Uߝ}BR$Y""QJ!DZDi"*Zb$"d)>wf9sޙ{Y^=y9{yZ[=F`7KN G:.'Do0Xp]4       %R`sS{ 9ľ:y_ia —A7~2@@@@@@@z_']N u|ý<{=c'bꑯ~ YTIA>$9/3?"@@@@@@(S9AyfӇ ܈{. ^Tټ-"9{@@@@@@@0ooA_f| G|w9Y@@@@@@@T kO|{>#.= ߘ*@G̔!L|G6       @a XAgnt{hd;9у=QT+3      A15~A{O\E_+q ;7M- \>      @i9A/{jO:IDAToHA|N~p}@ _'      P1 X` W~a.      @I ȏ%'PR>V+$ҧyZ@ @@@@@@ )ȷ E зA~0s@@@@@@b&iii*))),>/B"/bHvvdee!i`hA&@D{(y"      g||}:%Z D<      @bwz+=X ?b**"     $A')Y2s      @ '/7:YK       w[$A~|H"      @1<@q z)uܳ2@@@@@9ȧGó ݥlC =E#S>]'}d ]AyY(cqTHm7˖xr&q|Zr w?~s֛sӼKGD[1ϥ׸N7g fwMq=fZtԨaRm;oϓϗ~!Yl_~Y G7",ؾ}| qOR|9iժ+W.½ [oٳG^~y~dӹ8TcX.]n t绮SjٴqlܴItt:Ԗ:P48"ne{ rGʝݺ*ϯ@޺5C[:{441ZPl~\7m$2Y}ƹC)a,bw:2ӝ2~οܰ     @ XsCGs EAIr󩑅盶eYз+Ӎ'4Kack࿽2vܡ],;g!n蒟³RD`͵7NH*U\en,+oAF̐ U#Whj)_̞3=[!@-:>Q~pU"*枍Tr.-Z\\e}T8$WUpyg6Uǚ'*чt)miDc@]@@@@(~+&7z2fggV#,`EZ3mTi\7) KF. O/+6  c󳢺&*2/>aX˅Η{L۶:Wf(*Urźqχd` ҹӝv]JA7\w} GcM{~yM9U߹isNyO\(8rzru+EQG{ddwۖ3cGJڵQGsFp Ǐ3Fyk &8E sY}߇㟷SzOrч'<_Vk# _7\,rG:Xwޙ'cyٌM2fx{V7i$ͯZcgC6B.aaG6&ﮇz? ﻷOX4dYf] PϗɀOz'    *soL!GaWUG~Q| j [5ğRܣ*Ks$;bL\ wɑo d{$Ҳ_Rs?@дrq~_ی7 Klx\ xmyIi"}mo'009 ,]nsꪖv^᭧O{Y^ye]- _GO^qݷmJ6q/߷ҧO?PjiD)o|eҤeםE2r(=cgLI/.U!5MQd޼K%ȷvOdЧbZԗ䥗f`7A~ɸkTC\'O<ʟ-3I+TCrK EmiXsf8JJJ^Ytxu5xfDwءAI'8zAO>9R֯ v)c]צA(N㪗F݂vB:s=gF~Xw"|d+C5+j~1Z{i-j̩!#,t\pL}񥨂5k1_pMU3.GzݨFW\y;d51zD$>@xPЄDPt 0u."    c6,}J_Xѵ{N[&|M+V5sk Hp9_YU$go~=o,𙣂mxk{ ;F@Q:C.]h֞y-yF, ѣ˼wU~%WUX{G1`ѧK'YsvIZ^qiH 6oK:U}I|6Jz14!#СG jW[a#7ҸO<^jXo{t|!7i$#Y:r8UXadҼqGNRyE=_/G`^7*kL={~lں}d )3tƍUW_!zxxif<@ѣG7k /L~G3U& 6@@@@@"97 p+[,gA/YQ9?wnwj/iߐް=;-tgEܘwm PnѢ? ;ѓ8䐺2vSyޓ]yE#YWP5z9uUǺö#} D}b2xxf O8Y^--/ VJr ۽fXh]J:ڌA~ih\otUF,w?Kc4F'8sErϾsSmYO陧;u]ុp*(Y}|'DSE>Pc4 ?5Oe RVMy.G 92 cT9f=?ժUG@]gN[}}ܑB@@@@@ ȏcsw"k3ΐm]-VHIJާg(Ped::{vgݼ1[1'*m ?OYA~{pb={-=G[w)ծּr)M5C;IKڵ"^{qv7y1]eϜo:!;Ν^̏ʕ?G o۶M^'-R|J#K!v,R~]^On}+XYoݶ>syH&'IժUds frwȃ>vh~WeF {%fQ!u]?8X {ھNo1G3ؚ!fvzufNW;}⒋Ϫ/m A @@@@(b|㏡">Npn68UwW!Iu}?el}7lk_{VeOƃy,޶ [E\սZ?y~xc?KKF'HŊf7HNw4P˻<ùB>O1C:vx8`;w|A^%@ΖὤYg7޽{FoJr煪oY^}!rw#icY?._u:w؈g?e45U!nݺ%6^XY~X%FlP_8~C 7Z=yI( ڪ%z|=UG_A;nY\9篸2s>oN22u+ ޼equ{ uq>T/<Ş^Nؑra[梣;tΑH\p|KW@@@@(|y'q5QS/!ȏi*+6.$!?9ALYsLO- _%wν}/6ml lٲeR|9d1츧s=P1_\m\w]kWwp޽GnVcƌz=dD%5!ﻷ} : fE _O ƐEqQRJegq3[Mz+D{iGՠ~At\7`G@/8cc}ޝ~\a77幉Sm5o*E;Gz9kST}N?~y& gS>'5ak8 -^@@@@@8 }.g l~ٴȵ'V/=w˔xMfɫ˶fmݮ'>'oUo w|oХCM^ʕ+i_%K,V Ckw`x %i}8^Jw5:tRRA q};״20j#wq\vy̔njsDfAOuڀkf o=zA٬,y͹2gz;\b"iwC !#zUG7u8z _Z}A>. ͚r{׽9ty 1X:u9kZ3Ae^miܤ Uxy2v&A+    A>A~qwa9^yZ寳5zkCQڰGFQs)_$A~qO ?_nkld亮1zKAwAe^+}O6C#onH2P?ؐnj$wu3gM5uB>5 {Hq cʆhB|ݷ ulk|gحo뮿 Z{VCI@Bo+ުܘA}xo߽{Oч%{3"Ӎk) )e9a͇: cʋ*'N_{\ב B-a9d䆶U/b[P#Y 0~t!ID!    @A1Giiaacm'Mg}^ \Meg=;۰N9q:?o˸Ev] d<0ϽNJʊ"߰at\UTdMǟph8G'kg(EߏozǺpݍ.6ne?6_~SEX4\|޻?I2kyť#JEЅ ߃&    @A~:/ӎV*$eJ+i˲d}@NdۚT-d+Y2}mvr ?JV/ \[C]Pѹ # 5Tio/UXZ~WۥE*!_}zGO?5"-,iA宣8Ӟ5;^/H}ӧIծϗ˾6kUN;waycAp fjJ .8WwPT{'ɢO4i>9_ ֎:=?ifӦұCW^A ;*GYYd>[./ '}hN3f߹kӦdsQ#.c=-Z\Z_f>Szϻ=o2z8s ?$     PDF̧G~q&%74*jF̖?دgJ X6 ;0zwtM2Ajժ* ,ލ7^/mohE{Q?Z_̿Rz5sw%Ž˄ y] }7nS{#0J"\)iAISe]!•X|.C!=5\e`/_Qy6O>h$V(o$?ߋz{woڵk9enE2dk|&ګ\e΍޳L۞5{TʈC ?1\>t]GWt$nhN~_ҥ\As˘1]utdu+/ϖ_WAZ^v=?V9@(tU.tc ҹӝfy.Z_}Gd?ASu@@@@(j|<޿} vߠ;(*jIyzkH{GP,=wz䇥)7 ; ( rHV} -;n~U2{>ͫT֭OxW|jhWZ+]w]ki{?B~lٲn;$]9իW.7k#vsjjpn,Zy=ӘZttui\k)gXnR9ԓ"U5姟~c:/j^C堃>PreaQ{_]{}]%[33g?v[Ծԭ{Ovv oC短^ZY&Hƍ6W[ZcH.{D ! UV\=ӣXXx_ z:_m /<㼪#L?W-ꫯGF}Yoۯ'ty-~6~S<zv5t  XwfoUQ&mmo6p>%ZiҤe=g!gƎTe޻M=G?ku1JGctkڗW@@@@@1F(돯=_CcE!12wJrGCZavUa<8{`0]v7wvc=e |HWqkorU1r4l- ߮Yѐk[]w]1[5PZ!)/<+\R.>o i]B8n7nH-6gΜ#/Lnv%ϊߟ%WS٦s.ZWw PqQ4|6E5}Ryl:үר uX=wWoʰG}ECGgjrc*r׊9Z7mͳU~{{28gLs3w=ݤ~5DG-=5s}agukݻ~ƩF?L3c-     P1Fig⸮iJYUڽo9Tt^MIIq6z3XEڝ] 뮀 e]GWp 3we؉}moGi=`=}N?>\A~IηslЕB ŋ?Á_r{;*^Cw ߣY=ߵ7ʯw|wOǜRu\o;s_5LPdK~pg=50.A#3:ȱm7CGpJ ^?Hw5־: TL^kF֏=41Mƕ闾 C+7t9lw?za kw롒!w5jlȇ :uWWu{1ҭ[saFtfG@lĀ)Sɬ{x 2ڴ_uԋK/k!aH    A>A~qw3-{vl}lCOl7KS6dd'\]NNM3cXs5ۅrm;5W>oL0|gpױ>$֦MeRԩ-*-8 GIBU-2E|c[PcVEzEq0BjYږx~ŊdgSRSd5VZRRb|Y~kqXǜ 999 WA?X#Nm&4{*C` ÝGI.1*NirxzrI$[W˺VrG9CIv@@@@@t 0 |z;'"C'f>svڳ3jhVeu6捔F>^i fv29s.Vm%a)A\o9W75N|%,oˢO=[4͗Jorۍ@@@@@N EwH3 d=5ONN3/{ f_|Ws_տ;̳{kM [O7?JQ#[@@@@@@ QbDpIp2#PJǏ.㕙/F=\D S @@@@@@_7De%?9y뭹q sQե      @ '/w(g@ry!E:3cGJjj @@@@@@R ?!o\Nl _?匌e֌xŊVa @@@@@@ 'O3.e)/6      @9 &%%%4Y__l/CW1-ЂLhN2A.D@@@@@@%`M)SRR$99Y|>VH ??=ν, OkG@@@@@J@A ??Aο OF@@@@@ʆ@A>=7.e  C 0Ti@@@@@@XsC#-@rHio@@@@@@(! :~NNdggKVV~Ew,ٰ-g(!%@x:U|ҹij       @ )_[,X@h0YK.'"      @Aу=dqķ~ #_蕟7OD@@@@@(@A'8V _%!5Rz_)C@@@@@@ih};wXGhA?jUɱuN?8"     $@A~vvv099^YYY)CW1?ؾ-@@@@@@@K䧧Kjjh>?>^/B"/q       @ oh}1F0{~#t\       PR Y%--쑟"IIIvoP}0AȋEC|D$9w@@@@@@@[9}  la]'=,$ 4O~^!?!N@@@@@@([9AdtY;f2k!XO3(J*        ,a[P&.ɒ+;a5'<_i葯!h|grlOKf :       "`U,-GNq_P!,-F __^YYY6'N3JB§Y@@@@@@@[ꍯn;{1|/eh|W_]^X+ROiqs       @lٺ+(i^+KNfh}H ggg\YA~Kk9uV%$"       @N@d󎠬0ݏ)]bho|+ϫ7[*|+з _3_/@@@@@@@ОK4 ?Ԑz*IfVo%o$?PR1@a6       @^I>Tj业YrP;?TW8 Wgn_׭@@@@@@@@^_u|އN/!J] u cgm       @(g֏3з֭~5u\޺,} V=n        J[V`U۰jY3z#1֭>ԫUf]w*@@@@@@@Pެ 5T;޲R[ í[uyE@@@@@@@ Z+­GڦK]jPmP       % 2} WnLN{       (Hx p        /A       =@@@@@@@(A/A       A>       %H }        `RR        Pgv ù5IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/operation_description.png000066400000000000000000001303131515660254400256270ustar00rootroot00000000000000PNG  IHDRij{iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i@IDATx|շPB{DT@PQTP"ņ>Q" RDXT&[ڻgLf[ !l}OӾY97СCIbJddNaϦϽ1m[g7 tNuK9     &}O@@@@@@ C3N     '@ >8'j!     !bc'@@@@@ @@@@@Ȑ       ΉZ     dH@| @@@@@D-@@@@@2$@ >Cl     @ps      !6vB@@@@@ 89Q @@@@@ ;!          @2W&4ct-"""#}^v@@@@@}_Ry퐺.@@@@@8tP^RddJL>"³xjܷ潏znu=g@@@@@Rb     dH@| @@@@@`.3)ʘwsbbYms>"    d@vIAR@@eF0LϾ     pwvǎC9(x7V?@@@@@7܁w ۱ePsal {Y{t93 31E@@@@8z6Gv׮c/J ,o|eةcz+|ff1     @fhݻ7yy-ƓC%|Nv@]v]heꃲ3/3_     ;ȑÊ3:j,t*p KB '&o6(C;c?     :ՠN5^e-kIGL,^F@@@@fUU[YW=WqHƠ혴==WxI5yf`V-&VE@@@@@o.ufV^vpWs2%xY7nObmҜ@@@@@2"аH keG8x;me4KoRu'Zu`V      SmoMrx@|bR:*\}IL@@@@@@TDLَ?͙es ߾a     QgY ~)     g"=}YO@@@@@A \ܤFعv!-H5=%)2"=թ@X  cbAҺa}    !`šM8GI Loxlj2xptי@ě,֙'߳JzWi%%s@@@@2A [! OC @@N      ^lnOS>`$FA@@@@3v?9     d@c{9)ZDT@@@@@ (lA%) p[;Ɯ@@@@vp     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ ` ̘6G ٫"0lp1b&{+ϼ)[n?nE@@@ Dӳs(:yH%)S`T9q֣Gy,gϜ&{[Μ⤤DumfqSe*gZ3,3+0_ ,S@@@̉dr (v Oub[MyWިXuy'2:yLL"֧qeE~&jȓUn.ck˓F{/h@|zղ{?zY=Q?A#Hᢅ2V~=_R(U\.U-S}.߅w}vnI >2fxnh챜 ;픕+h"Rb)Ud5He彄¹m]wa7TVQW(#QQYi# a(|/@@=Z7W%P(*F^ |eV*5FOTn-u TV~s1E :]XޯstX>"1sRs~d&{TӸ,]c]v[HOȨ Z}5rq[X|l,)r˯?z#>-]=(:6Dv(ng},wE^嫥k̀Stl*/??~\cRBJƳrR  dCzgÇKw|7g1E^R$gj޵2pU`Qko]`w#_&_F7rag%죥TBR8::_[yLjWK W䄏!q źruyz>nOc|ֱ"4&^Vrh\^[r$ /&9rxd_z͙3|z?Rob/I0n!=ړ>ʲ+d˝* {,ϝ.*&M ٻ{,s5 (4A T5L/.Y&"k8y6gl&O=G^.T^IN%ȚUed?K/a&y} RDټ<   @@|p[x>uUFw箷۳AMG#G#V|Ill3i C[Č^._'3dCjM`gM`~ɓ'o8/>!=eRDEY޵co> ߸~*]\b"ڻg# pkYmvjrgn;; ;J<#4iv==dǶ]׋h<|ipIn0ÒEKSt-_YiqSS)`֞}Ukf]u2eJyWuyV3na(;n5 Ogbk9lցh)   @vbfǻT䔤82GNuJXd9$:6ܺXGڛf0X,ݿQڔh`/Z!q=-V#Xo~`4J }7 DoOL/ϯF~(R?o}_j42f79U/YaM=6ݦ3'%ֽػI1agwKWQ ~i'ܥ][܋~7?^wPA/=~ixܧoOY63|_={eke=o`C fZ3cM5O{LpO?2yOO}F ϋ Oϡia}lLGwد}]bW^{[$Ίf_|s*mHT\|i-Yj(Ƕ-;׽ɍ:}_zT]fm׆!w}#~^}SRZ%{FFOÅiG;-=w& mA a?ۘg[۫i7"F}cKjMm&Mt3 Z@u.idy7f|?W>zgU Qc;w=;[@-X120vkrɈ=4J-qo;3O Ay@@W@|>۠|^w:kII'3xs4]Ax4]0,ڳF٤Qp YkH g5S EDjpl,<֤Y*Kɡ(otсUy (V4|6='P箯ow2IoѪĚt ۹WjU|2zG\7:un-_%ߌ6shtM?7ZMM ݥ)b1{^D߬з)?S->>1mvny6Va? vl)O<~@dǯ[q &98qIemzN^uF.=:GڸtNz]voGU &v9vs/`L79SMy׍vcٿ:ug2j׼ )6lH}@Zs  P}2|]ёQu֥ _JuMeE*՝c{ ?3^fӉ vZ{VēYəjj֧SFV`~2m_2eߞyg/fE;u.1ڤ@?55Iudu7NJh&V\i{O&YgҠl43:dX`wy텷Ot'W^{sM~8LnX^д/࠿kPڻ |i\hy/YtM~@!ݥ~Ô^^H{gF^/y|n^ˤŦ7gAUmXPyq@247}nc}^:8]fϘg:7l\l}5>d9r惙;-k7R;UEʬb}Q|YNM+[͞{2%ߩk;h.6ݓh6M~a5=\YXe[2?˯s~ߚ7Cg )\ 0뿥+e ^kio~.77e%|ѷ{^4ڽ]sҶ͗Ƥsms17|s=ft\lrAE)Yif ePZesE>p2|2&Q>7SX:>7t-^XM@@@P *O,_Ged}:ˏ&୥+po>{6}W+*)yGi]{+c}+b]/z7NEAؠ^~|1<TMO\}w<.܁xp@eI.-o^z k :oFr׻3NPY_y^q쩕cPQ^+׾U}^~fGSN=lSݴi~\t6=za rɋ>kbi 7ªAIS֬(o]ًg'⻉3|&Nu͟-vfĔys~3clUR ~ @.. sah#ãO=$54/ӀSLn5hO.F74E:|r{KyO4+-[5wOsy'ntv{efMS4Ҧ[gá#S2|:CްL4 35MAsy7rjYs{5׭_۩3Lڽnw3^CFL~ &m˦4":+S!!LM"m.ϙ7jg w?7R+՗ipv43e >   @vH d+:Ϫ6˜@dєwI kϦ:͟;]1JNj$排^/j)+^)r峫5)t^EsdJ^h]Z@cf: N+jr`U^OMmw^+.[B^toGm?|Omŝ=:H;;U4ϼ\V虮;~ Pk~&wz߀s34]4X46)/Kg3;W,]ǽߑn;Z[w={d3}g'孽V"l'$v! czlVXwJ.VhN{{AL~@߰7_-iɤĽVZIr-ohs=g''ɬwj ]>UW,+ML[zO+vzT>bΔ7J.ZMO-:w [[xwS41ɋ=Kfya޸,#  @ -ٹ腻WJ_?BA%RR}g,7 ݗ6@nKHN>EL UrUJR㕷>.rUL@@PACmoδOƈt*hͮ ЬE#@5)qo'L׾4yqq)zzڗe;XhӼ͚ĝ=MO뵫6xnsC}Fث|{pS vvnVoxu6;5y;@T3oi|73XմMSpS3ti7~9xnZse洌iQhYI7 ݸ~sb%jWtg)W7;4͋66Ī=wleW2o1nxg)fnؼ9Ʀ4P[1ͿE ;kC\z״KZUWɆu)@fWl  g6eeJ%7J@@@ gdFṆ 'eI!.ߏ~KLw-ǒNɩxiۥR=׷Dr+p$d#GS4W~ҮRc5q0wѺ͢`e $L݌)bҶ+1yc|V1A(Vb(7:^Q]WtNkWʔMuiUwH6AK*WY˕\)cUО޹Km]tߪ.Z8]Ax=VëI7wͿf,Cy#2ۙo Ըh .e])t0`ٿUx&h0l_̌a]l1Mp6f>b{ TfƒVkgwHxF睽K)]ݺe{ꕽݓ./kmsyAȻ>CecVP@@@p..w{CRȑvDF'J<uӽl"ocRrQi `rALJ~UǶ{$T$ޓ랐jSQQ&}O_@FDնSr~M~a>[4xhXT{n۲ 8.CA[[蠱YQOl^uM/JA3'ڮzS+{vnOjk8m4(TqS{׸w5w*:Zz&eD=79o*ϾXKпq_N12i|Ŕ썦&+Ce?o_.1KD{)y!&}iȨ|:x]wzipBr& U ּ׮hzp_JZxw쒦a.MÕD3ow{Ќa:k`!]*7]2   "@ >\da`#:"wXˮ$[o8#^FZ쑈ӁKWyS\R0GF(;^K˫'eMxJ 9߃)kM 1.p挩?I;zշvgZ)@nB&h<:wkԑ5ϸ_rLiќEf:>; LP. ~{_(\+O=z9V9x{ȑSJBMznZEVgׂ}K<7{{:k/O&Ul>OV{ `XҺ'}ApfN^tbywU.,$ֿD2_Q\Jk7N>G0S푮}o2q֡U0ʄ1zի̧5StTO{}V-@@Fݘs0A"y=>Qb19}.` 4AqW(yrIi򵻋wW4,;EbOK^.W<{5}\(w]=@wy텷Esc=xi ď9^֭Jpfut /Gz6`+8/ 7_Q:|hlL_N=',C_qFZAW5x7:i;vic߽ٞo*#>ݏ&`6n+ٳ>ᅴ) {{?u5Ы;_L!ӰbOzu=zM5_|6ws֘77 6:vy\v?l   @68{] θC7zT$iYsll;OJ,(Ubt՜taƖ?e-j_i]5oϵE/+ʂkeѝm* V]j5|O_-4ivygT锞゙*׽fVO%oM_'{wuH3X| تha},=w7Ke^ݳf̓~+{/OVX_|#?YWpA kFNpL;n ٣N]oY?HmԽMmn0Z]-Sfycu0]w3q笻 jʘvwjHw*T U{;[uᅴὫ5=]z;Ӎ11cN=ۮ0׿<h~5s27  ~](^f\;pfʙ|v*}`7:˱YI󟕩|oZu.R頭#Qpva3t-l6PN#/ |*a^s=mНjծ MVq^+4;\'=QSUVUBd3P꤯83g4O}tM}݋+ϼaYVRQ<]س>1^):F\} +g>Ӿ^6 ^fRz%)ToIóXt]ڙ:CEи2Čo=z)[u}ۡy.wHyJNjO{˟Wti~5Y?fY.6#4 zzusr{~_.EC6ӘUI*W+/4Z-_B0͹dmJoL6e ܾKf͘+ufjM%smI\3gu f@@@l%@ >[=XMU0<4g iR.oJ.޴fCaa>&W GIKIɁ۵$NH f_ꄞ3<֫N$֜ɏ@_LOa&Mwߞ9x&V>yHI @H?:§ w7E&{xqtgozM#.F_zLQkb) ޽4ڻ-Zj>uZұm6YyqU~fzWԑ;w0%'F *M=9[79 }BStmhCթSSMy݀XL)oϜMTo   @ DuqYg*4nj4N:*~'C|#i A+gSuH4(?9cm_,7NyF^#9JOND}l2_q&eJFJɳ{'[@>]K=ze7IFW+/HV4ЈqLzckOt=~EW7z{(+ݼm5=w|齺{l< =zv,5/NN4 =5ݏ]"#=S뵧du(4p'{lM/6o>{dӺgj &OA@@E СCֿ=MmٽŽfU|{''O]7|g?=|o 9 Iw8;Mpў@~¡p">T)XRj(5 yceb&YoڿU̹#sEKt<"9[<.OYS!qh9\W\N%ɺ;d9ֲESw*ڤqw/:u% ʺ4,ܻ3dR[SgR4Mʦ[erQ)SZ'WtZx=v_4&pP5ecǎK]b;I:fMyk"E])Y2@bͲ~&)brWYUgi 4j ^eҸ)V٫=)h X2SQ\[!   O]8?0%tDsg*^<.A [rMuMsl|mwOqoc@@@BC@|h*"]rf?3@%̜@@@@<vQ1c8g    @ _[5< B\A!~\    C o)qT[<{rdSo[     d@r節Ɵ |*nc%    _ *=J.$׺S&CY-[sa\T@f՜𚎆!r    !+-V@IDATfW~2R"L      }9>     y-@ ~<      9>     y-@ ~<      9>     y-@ ~<      9>     y-@ ~<      9>     y-*wiA_JDDUVL̄<:@@@@@HG<@@@@@΢@#Afd&f "hp*"    @A!yDCpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     "@ >\$     CpQ     ".7}  d$ Xf@@7D@@ 4IHHdbYh0|>8. @@2E@|0r@@ow=11QzD|?Ky$"Qf}dd$xo@@@@ lğܸq,]\֬Z/VmIlŲRBiq}i3< # 'IbRT4^ ̏6cٹcϟ_Zk6wsnl~j\_*/pq1uu#֪*/o;y kݞ&+I30["mr?)*JJ% 0  a$@ >3))QƌV>yo:,۶nL[ycp7-VԧnvXA/c9%si%>j5iv5473v^F @ueć-T`ϧߑP=7?k.f9ܽߵ7 Iy9_0yPioxS?GޛYF@@F@|G o_]JE9|ٹ6ǟ?_v]>:ru/ 'zֹ/f@`Χߑ^y wI=h ϒٿIQӘJPV$tT @@3@@@l"@ >j<=!m;lFz)OҥG{uɅ%"_d0yjsG]@@P{=~n$3irs}   @&Ob|||nr^mݭM][S=¥u/;n7V-H5n![7o*T>:[6m}Je`>u8xl5{@ /Lb3-/kFM زel߲S#TE tߵcٿS9&%c3"hǶu~[r:q)[T\^O`o6)%˖&iyن@v]?uJ#2'O֋7irYJ@@@ l~u̙o j[NlSS:k֬w:'-oj}ѭi,YZ{Jv-P~{V{CJ劫JY 5|9o{7gZH!i<w9utfɉ䆇~mG}4TaCZ^d쨉q&m[֣}j^\J%iBve5Եf{U<{R9L2n.FZE\#Y3e2{;#kYH~g3i!o|$ˍҢiqO;t~{3۟1GqL8fwܙ˗#zΝK: O7UN!npyդqӫidJdߑ-Q2oo>,e˗_ |{m3}ٿϱ[i)*11y| m\ߥ ckIZr϶@+v+?ibU2p苁<k>a:|7ygΓ3E /4vFZ S@@@p 'nMJ@WVeLP3MN'ތv޺1ȫMP^} ]YxS>=n.}z=w_=F #Wϑ# >!!⓯ צ&߾W4:!f*yoOU=k@֮Z'^z[/jQĉֲ~Y*j6LE"L0gLc;PLCKg^yܼuȩˬso:3wS߿ث|ˈGlvyѻ=ަ89q&c2#Yg֙z/H8פ`X_'8o3'͛ʩ)KR~#thQ~9 vx{99}5\&K[jяq<;1cA=.}^|To$L9 T&}=gT6ocZ˽ޞ׆7 {nȵ{O>{ܾڤ m/]DnOL#MҌf9vc+2ᓃ3"  @ O#ٲiSB{:k"p/k Z4Hh7_gdkd3|uS2bP7.x7 ,-^T֮ K˖K4/O> F:^W.m$"2ʕ9kӞv^{iJ.s4ą,?:*4?fwh#i 9䒕KW9=\?yoI/tTҏ[dUٿLӛxMܹp=l.RDJk[+3+2.t2}_V㸃ykH²5-fM#ok3Z)㿜dUѾػzL ҮqQu)[@ z/#ĉS:Wy*M&)`r~kaY',ӢGMw5#UR˭ ؼ7^ﻳ陌>;2dγ2iqcSxlKgɕ捤`UA]W6!dҕVP\ a t~ ٲu wERS&M_n]7?J*f-i'񥵬*wleww[O4io#W"MZUN/mZ~{^i2   pħC^vI-aIT*OTqbvv3W@KsџKzXl7'jTo%W,+^5:lUŲUV ^skJ ؁&w3LҤNWniP@)4mX{ҕrIckl?Ҥ#ҢӖI~ӨgT{z #xUd'c/.}&wD{ bz' c7!KL#hC oZң4E_Po)|;~ӳ}%?K{'./w~KM`m1Mx o7hk\/K|^MXMٿIod1o%|D*( IR`R՘?8iD4LMcw޽kL}y}e@@@ !r6n||̫v~Kχ9[ZQݝdkCUӾ ?vDNYW*UI1U;kӁ"gxf-逪_X{se 0|c 3yn&ᄒ!.:8%yw:,5@>RO>t?L}_xOO'o_6Ҵ0S~W9 5kqGޮTtzy~} ߷ cfw6=Oǎ\ vw.o58;dL*}إG;}BǴ5m`8|Ocٽ45}wg}P9rӘL\]:ti- V r`/E..^PW'/m;̸ѓjK{C{3?&@=ߺs挶4Lx [I%b\ܞ䬺M3 $y Ey'O ڛO1`cM^LG#IyLT y]^S@@hql:v MwYj& }ƺ سdrgZ2eჇM^uAϟUHicR4ZF%+c{ͷx jNSfyo<@ R N H*|A7nHc dJ8nv#L#\Ʃ֬VohgkFe׬ZԺUμL:7w7;lz^v_!M tRFDDeuk;KnNgtKێسSFtM%3CwD"|}|GuVҴNf[w }ӭ‹.pm6o9eԪ]әw4l\W~ZU8{5}uN)gȶNw3EO%r 1lQ"4m͑kFhI1p+$j||@3|m;_f9R{+b%O@>π=@@8ħ3yׯ`EY)*ʖ )A͹(2b473d}vxn3_\1E?driظ4r/pJݴ3e# }W4-u[64bФV48f߼aO >EԴKy} Tʔ?а{!>l=s}{; pK|f|g  cMuJٲ^O*ھu5qo[2 >΁Nd3>feR?SSB?a]iب\n4֍)ʹq#P)gR %15V8%.hWjc TrMp_(d~{?K@{'7>54It^$|dt?|H[^y@@%@ >\\Mn߶+{<-3:@Jmiz2i7cFMQ|wFzi^.󙓏پO #MS}/|ۻ(lBo $^)@P<`==YSTDEj7EZM2-ɦ,eg޼i]7o~ 4G3-N]4URElۥfdww?~%e㺜6jr*^'XYAnwVRB|+lacIM cgZ#{ ̕LyՓGzST_~%&iS 9NU+ݩV}ioISO>ȭ!/x "g^r67z}3sRp?L4vvx7g  񅸊 \>rhXkB{{YۘgKݤCtv}/S&Ai~ 4IJKs=-4oDVds6G{{' f/VOpMR&<|ɗN[ hu;45d7o+Sޑ]W:#8QBYgwMڑ0 7::ulV*ܹ;%gg=S5O?3_ܙH~f;A*jO|.Ӌ2Reon^  ĻB\ƍ8-ΐ9&׸\YPӝ&] i7J!Ҧ] zY~-Ibs/"W]wI@gޏy%m8=6>[/h2yﭩ匙VM`o]pmUw}䎠 =N'^ kPidy)K{jcƼ7Nwz}\@g6cn`neS>SS;ElWd]r[F9Yo4ss*Xڽ<$Go;%#7Os~'_t2k6l  :DVnwOgBx=kS  {bry*K&;՚qAiQ*vn+x\W!e,fK_O Pt}X/٦CCV'.7kAgnerr @)"  @ /@Ykhgj3kW=TӠ.s/ VV#Z:w;Z~f9t'͈ dF`,αX%7^}فgln\B_m;^ak&xNX™kݮU 6[sv6^ w:/ϒt+˖ Pidj~1kqРOhn,O7);^^4aSWe?]LO /ulܸ% 7s iF `ԛEy֧tPPw@x8駖ڡt3]њLs|WҵvrWFL&f1|(9wveݤSrZUAXvi_߀Gob9=:4i?݌3iY_~/ G}"My˪?<Mݴ'X."izD6)rk=)=|e4]μrѺFzs:դOR nόpXG5ǐesYO1[ebفz [t$]vn<-vž13mU%IIfWjWF鱜u2dl~@@O 07qXў _Ȩou9g> MEX- ~^(f}~⿭ulcIu+ָr&T03ȍ,V0=-ݥ8V/s3>;`vIQݞ N;?$'yȝqAͭNr7[4ٜ. f&w5c[eFy\0qj[>|SٶuhoWd5מ-۴Wƽ`Y4u dݰn'jg͍GeqMS*w=1o+(y Hby'V-;MG'ɪkz<0qO|mz:gM3<ꋝO40h@9gB]ݟq=%mYzc\u<ܽݣ;N>Ѫ^W]2ƞ+uS G\8\M7voX%-\}pguMq;ˬ~nN'ӰڵtZ?D' t~?L#= 6˫f܃zY QO|- 77?d;iP4 }Y=Q$~GvhpX=oo-s:w{ sէ}ul}e1zuw9w^;igƹDc*cn4P?9^nzch~ڳwN2r+` k0>7 _jUn'Guf.6A R`^o)Pj5lZh;ZyL^:XyU3_ͼ+ش]`{M&x=#%`{  n={X&LſO~ݽ>KSߵށD{;_m-ot{|}@T(O,k1Vo ioA 42݋i NqC&eHNYdIx6y UCW?xIquAT{X`y 톚yҴYP=/'^o\m> 7-uqn/~G&S?@w zkDo%sjn_Hx=Ќ.p;'^~ ֲf:v~Nʙ.>˓ L3t L_F!r[Ϳ MZ".-\{L^f״/zG3c]w]A庲i]iw{3m6v=V@@bNczUR\937v][}^4/_~B4y~Es`4:؟I2gd׍~כaWw2d?5QO^u7Ɏ=/{E=ns/u=n96 =8+]{^_x$ 7lcoI)-w_/md`]MY-c0T兹1^OK.7PE{z׶~^48 +mcO>HעݥOɀ='W~QO^vִ[RϬ} E~:Ý;96=ۓ y:X/<,d/$'YK/e/޼ Vtα XTnmIi ͻ1\ws|O:g :ڵkdK-79e/w}Z enEڬ  /πvFMH3#A]+P]p6)B.Z.˖,7OZkl̄ubӋw[CV40.KVjV/\S@{M8_jԪ!L/E=6}B_Ke=f 2R?(IkX_: \[6n-ZNvt]OdrٷOW4-͕2M!|*095-$hѲ .9~6ʌ53&gHKr3n ԩSS5Ed~.ߖJImжc+iҴA]wf0f&Bw'5:o~&IAt6 ~^dRBS$G{EDfn5n0ᜫ>dT[57@?oKfKM󛬟gI<c8^ K~}(fן{uHrt~)hxG@@#'= {B,,_䍱" B{ָSטؚ mMcsȤ67S7Oj~?Oʛ_-D*4mhP{[x0@@@ @Qv! z x/;7O)Kr˕OJiK~%_@/u& k[9A@@HH y9i@@ ;(y)yL^2& ˕տ1dIO7LJ%3i4o}D,A@@[@||_?@p{[k_M/܀^7@|Iq@@@ |= @-3HrztiJY6 @ yh{w4Ȧ!_/}$G<@@(K@wᙢ/   vP^:aW+3N Ֆ?/r9q    @$GRm# X)%_6d>䒷f^KvNrױR>gkU   PJė i! GRK gffYj>%%Y:Q@@@*@ ^Y @]̴vNx]L > ׉]"   d  0vPK^ˮ% '   '@ >.9' Yw Z~?G@@@#'@ Y'@@ 젻   @B,9I@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >Jq,IDAT@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$@ >J@@@@@ 1'u,@@@@@$6;;;.TEVV%|%wGK@@@@@@ {&&-IIȟF@@@@JOM2f_~7R5V '/).F4D@@@@+/DD]ˋ{P c(=%G@@@@8kN ? ; I#@@@@@6X8-|L . ǀ     P8eT!bQxG@@@@LKr17}*r     *F=.@~8.@@@@@4Cc     .@ >ޯ Ǐ     cpp     .@ >ޯ Ǐ     cpp     .@ >ޯ Ǐ     cpp     .@ >ޯ Ǐ     cpp     .@ >ޯ Ǐ     cpp     .'#    J +;;"@_RR-Xph    {vV^ >|\\?2I{+ A]cm@@@@_b̞=[VȐ];vIVVV )@l |>I*M6ݻKM$ɗ$"_kF v    C(|e S@pzjǶ5u5?O'_8O5x[w@@@@YY$cYFܞ @, ];wW])>I&_ċS-    Qpy]Qt -n.}Ds #p^F@@@%xYre@:HvmL2t 1)p!Y"駲ag|n]Yfd'3o@@@@bP Dn;=GAcn;u$azJ3wLkVx+^t~a    @ zk`pc՞0@wLkUrm.@ >     1.`βrWܹsĚEwos/+y@@@@ tH땕92z{8Aߡ,oX@ >?>    PL D^Zь ͍@@@@b@@sUȈH}ē'>ι$N@|I( @@@@@BC5     %!@ $     !ć@@@@@ _l@@@@@CP     @I/ E     @!`F@@@@@$RJb#^O3ST4h&IC     /+y@MI=Q1奷d ή%=N3@/3{N;ʘ1#}ۖaC lܸE֯TNMn8L    @ Lxbr^L ~eԩ[/Mql?o]:uj')), ,@ >O%_#&<(':6{KͿk8'?os@@@@MsʿyWAZ]O3)@#tٽ{A@@@@zJtY2-eַ?9?9u:{ xA@@@@-01r!w5Oy7o*g5S3 E1WݻݷhęfD _̫ݴIC9uI\r9pRk<+3V+e歒ZԭSKv$]9|8S,Xb.ʕ6mKff|7t T |Nd,_ik͚bVImFWqپcGIjcuP]FT˒2owҸI#ֵ5gҥҼYci߮ #80sϵ?So)IR#gf~ݲz-5kװ)cKŊɢuzaXTee&]lLڶi)j? Ⴧ6mr*;:^xrҼyc./FecbT˗= Ym#1GElIU9:cGY{3ڵ8M~Q|U7kZi@'|)}\ȁfW(/\ty]?9NݨQWY>ة'z!W֘1и!'[o8_}+2뛩Rɬ(;yu*!gnriN ~߾?%oJ^n%'%`    @q6 }vgW/]MgJwYb e6Y;z3X#/W\$ݸ_0Gj/cgerキ9]%w6m,3Yt uÆ]o\iUEL'q>8/C.7m1ZV w:Ax20q1A'h\^xI}`:m, 4CO rMsat G/ ׶z|?|~ݺruZwg@@@(IP ̙u}OPWu=><o$#n0NPۧtuܶm5)IܥRJ~9 Lh#s-T uy&X(/f"adYuM WT=6ױWeOZ)~j6R}eO/Y4M~.fnj1t2)j".];    PbG tǭJ͇'! (e>dќVK{Oy-¤fZw>Y~w5݉Q73kKܳ!5۩sGyo< ٗoc7xў_DyqӏXw>"y塇,W*fs9ot;iV{Q̙! =^z0U4-Mqp&ZnHfϞiخߛ"W_=̳_߃4b@@@(!`2v촋vy>(HOzO0f)͇?q⤀fw}D1z$9p0tgT׫[NJE͜a@Z6+QX/4-RoZU\ ʔQpr7:xywMlܸٙ5cݺu]S1]:X g4ylrIz bl3~}_̔;n p3nvy+}۶5I㤅]2rZOEh*fV-=[ViO,ٽW*WY@@@@ŎG]4(/zU7gϞeXO]QfMAqq&O3g1P|dOfAy< sF')H$3P}anfT@:X{RKuff^fAV\+Y _}8˯$ +~7}uu7"iݺǣI]:9:ѪESϼ0wSu5k{jB.=g^4q|91H A֫W3E7*Fg}RrIt91   DR Tf^3g{+S&Zm/'7`Zg1 ֵyG #K.IIr_XMYaTmC'|i Mu5k4^ER\Ygz͚UfO][Z}OP* vsC~KiѪ\1B߿&G@@@J\ +iMìqZO-4%yrM&wi޲$ikּ̛7Yrg "-@ zIn~p{SU~zf^f޿"6z"Wn);AGJ;cuQZ-):UqT6lIr}rC[ͯ)@@@@b %g}kJ4g]4vllLo-4ʡJT2AAH /)No+\@}-ru^K㺚|dm;2e?˫WLvҥrèy6e֠;ߪuKiڴqkѼ6H\r W^4#)sOsKw5    @ Nt>~Oٱs4E{&-wyKĠvgvmo 3[l RK ϩD[}-YTG 47S+|m< k|TCs:s+~ƽ=Jj'9iNu:Φ&g^G5'_d2뛩Rp?Դw-4L4̼6I=    pN?d ~puYA7j9FW^}[}'}]͊ojMT.?5s1L 3_bktm]߾=HS]]W^N-Abwq|lDs3X۾kQaСCo{oo6w/l؅Ҷ7-{9    8[6-LHp:{QWY~ˤWμN{ҩsGOɯ@'tb&flAJb //W/9[1qA#.7x>`ħ_R|-%q6CwҮ]yOCy}23Z7vrow|P~jJۓeԨڪĉL^tKzr뭣%/}{|6?Yīu zLӾ}kiѼI@$bɋE&StQ48kEG^nF0رqM-JZz]23d?$9'ʕM+> {^Y`/[RgflGՑ6&wFA@@@ di>,oλ<yf 5kOé&M<#%ܸN8ǰiVXJeNKuY[1#clܴETFi) Sv-۶JYV8㱌7aDǦLII+qV ON$˫ͯ *X1Bx5flw^/䈏pء+ҥFjU+WzSWPNڷmi - l7lVjGw5Ёb{zD@@@bV`ַ{MӵD:; 793u}-DSLuf+j=^ϊ% _=E@@@@ ,\j*I22V˴Ng 3E _47B@@@@T|3KRfu9>T @HR]x3@@@@@ \{ ;@l?iN #>Bl@@@@HNr|ҨQCd>N= P<cm@@@@Z`.A* @ /yS    @\ ơ9q     #@ >~G     q     #@ >~G     q    >7uСF @!XxA@@@@ NW9-3 nM >?g   ĵ@RR$ަ6ˌO? @Hw];ewh    &0ةc'mذA?A~ y 3~g!w~(H)*    @L\}7j t"uN/M3E~[Ѷk#>q=g   ĵOr$%K^$͚75Nww.'%ýVÕ    @l <>III/:V8~1O~xa_URӄMEC@@@@X^Yirv]-)ْ-O=Uڷ( "W;wJVVV>ǃ@ |>^4j7H3߫=͋l o    "=rEW wi HZz}+0-cq+झѱL o)&=MU _H P\4F@@@5 kx$ZJ΀&)ٙY&z]\v$+nF^0ssݭ~Vox;`?q7c @@@@pGof5ijL>ˤI2xEpbR@+6xNi ^V:3O藌@|X@@@@ `3>;Mx- h]~45xZ _h2V@@@@U+oLek܃<prfvP^nǚ    1(jxh` KE`⃩P    P*$I {q.     1'0='!ι:/"0I24Wi9@@@@R%@Ru99@@@@@X kWA@@@@(UKd@@@@@bM@|]@@@@@T /UA@@@@5vE8@@@@@R%@ T]NN@@@@@ Rb"u<7ELYs|1 &W+jx 7H))SL>zD$Y     i+n{R7bQ ;z|@ OxLj @@@@@@Nwt65/Mk%xFQrbY!mqK, )>     & 8 c#x"NE޼ K3?QAt     ĵ;қqě\zIKW}\:9x@@@@@#"P/G0      )@ >>G     'Bq     )@ >>G     'Bq     )@ >>G     'Bq     )@ >>G     'Bq     )@ >>G     'Bq     )@ >>G     'Bq     )P IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/operation_description_docstring.png000066400000000000000000001513531515660254400277120ustar00rootroot00000000000000PNG  IHDR7cp aiCCPICC ProfileHWXS?wd(2aE)JH #Ƅ ⦖*XhUĢ HXgQpǁJPNo<<=9s"EbT{JzP2B }{%#X)Ʉ8[B ^&+ C"K 6V!ƹZJxF'9q3d@ba.xL$o qP"A ™jbg/xĜ| wk9\?[Saj8#dDf5A'ˎWRT*:EZx1<@9y@ig"(@.wd"M3#$P H #vaY1(#Rhf51ą *l$Z*x%E\ -BIN$FÉH nx,|B9p: ݄[3e/rH]ٟW;B>xC8 77C`d(Voೞ(2JqҒ=U̗yYǘ/5! v;Ś;5ccj<ipDM>Џ_N*==z=>@Hx3s\I b6_&;}Mdi߲ [~-s{uBX+|epy_BAA2Ha%p=+l0,& { hGI .k6\?= $03q@O#H,#YH."CT<+YlB#uȏ$rDn!^/=4Dq(1h2: EgtZ֢F$zv `z 1 ,S` O_>Nę8wk8O,|߄v ~? !'L!f U]Äp7^Dщwc:18J$>$H$3)OH复}.R-YlM$G32r|E~BP(x2BD R N j25ZMmޡӳכ'[Ww@}w4#+Gˤh+hi[t:ݑJϠWoLX!b,d0]}}tR*C (<#7  5S{ 絆cQF)"EFFGGD͍j&DD u~Ol$lymN8i;qqxϏ_7)aVϓ&L~8>q^$fҌIÒW&NqNQf֥I O[=eܔS.Kӛ3H2FL]?''<4i%M7^0 YiY{>l~~!OAL*Z'׈y6W"IyMyy*H+_H.*<"3gZ,)w˻gZ?_إDӔE~QZu8هJ Kd%Y6Iids¹ml-w>wȂm .Yس(jў-([SꫴZX.YQ_ח37 fR|ti2e}U\㿭vhEΊ+":d5kJ<\;im:uXʻjՆWmIZMXm~Ekkֆm*NQkkvwx3u92Un={Z]Y֫{eC WT~1cj͇+9M#yϻ9frlq%LJNh=mFSSN]mq:_"9u{٠G;rsƋ>ߎK~/_ny++\_p-Z7od)V6x{wYܫwv~⃤ >{|gc'Oz>={H?|lPА\hd4'v@Oyj|BT  5 @u^+ ;BCVՓC5:Rxyj}vh%>* }wTwM5;o5b|_Y_@< eXIfMM*>F(iNxASCIIScreenshot, pHYs%%IR$iTXtXML:com.adobe.xmp 1518 Screenshot 392 CiDOT(eW@IDATxTnA@D0PnDQ)@JP) E@FYXttFO?.<!    '1v[)! ~޽2h[}#     as^}nm3~' m(o{6dX     9WhCz}̓'چvTKHp 5-۹^~ٺXm[%wm{#    sRI"䌢BR^xۑ6?X,q m`omX7̓o-8XE@@@@@@+]E9͛` ݲ8SW}.n^]VKVJJAC@@@@@ Qɦ׍eۜ\Q"ކt u>ю֨wC{qgyoHV/KE;/#     wEFS]G_[˗uo{}5>}DK1p[W>D@@@@E@Q fy}5RQ!q:^Gky ]]hy"     9)r]^p̱}B7j@@@@@,*XBx}Hp'OLuޭoݻ?e)߽zS&ͲK7B@@@@HK@'3oΕ[9ϟ/s'$er44ϦWi@@@@@,x=v?r9Mpo'QYzmf     H+5R965Tή]#3pհ      @lp@~[ކ ;[,F@@@@Ȗ9*wKdf5 e@ cye ӏ$TA @@@@L Zq~-2}ѧb2 p.%+_"% ;'     pk4O7ӭņ.}*7ƾ#{     p ܧ38,0(dO*ԤlNj8+@@@@, Ogph,"y/    xt}Md"@V脵ݫ7͊=@@@@Ȗ -T9)3^<>6@@@@Oя__/哼yJ@@@@y4}BEٌ 8 r@@@@CVQB e3V#@!@@@@YGG -TXq "@@@@8dlMp+PQ6c5A>@@@@y4}BEٌ 8 r@@@@CVQB e3V#@Cp?ڌw䌳NMJ޼yCLorʕW_|xX>]/Z"/$e% ԑ2eJ{_6D@@@ <>`l,8@1ٸk3V$oAٖ38uEOѾcC>~gևd޽rK7/O{kQ/=%)IHNN^h=@@@@ mGܧ$*f9~uy#y,߾NlY#Ls[2o_ `wٴ{Z߰(աpT(;,8 p'[oPM:'|]~.T|0Sѻ/6n/G8)/' :ƷsݟuLr2b+^WRO] (TL}玀v贿?^Wu}~󜭲麵eѢߦR#|r)$n+n)\T<}tɓ'>>vJjߚC&ge=  <GG-TrX{ /+~/[-;'?K&A*)]μt.?PMG\/]@p]`S&Δ)f'yUC'[6oۆ#hь_tx\~OPZH?̆Y|Bp }Ӽ_ѮO K>RLeȨ&7_ ;v/ֲMc櫘~^~ÔT6Npʩ'zŮplmrG]W\r@@@ <>7blWg4:}MDm-+^/bľ׌ϝ+<ߐ6(ݡqW(ն@Gpˠ_^U(>,ƒo߾C 9@T!Z_kk$w?kpoGJ|d+x!!^t6@0_;_' >ӻD |Ds!eVzYrɕ-\]S=)ZHip;$Œ8  6&[(~ҟ|҅JHҕXԥf]L'% q[Wh7\>_l޵M/$*zy]G?kV@qyZg-2O dDbrEkMߎrAS|GΜe>=.SCUsKޓGLZ5GCM%o>|9S"\36|kQw$ǚ5Ug")R=E^B&2$.~=_jt|o1W=Y*U>VI/E>+5hc &9+:R "=M--wR`)V֬^+'T9Cwf 7L>yԿfu"r;Ltwvͽ|_F/_[uwHo n^ǣ~,Κ= UϨ 0׀mlX   lMp۱PQ6+韦.:WCI2ڎf}޶]h G.O|h(VXr˓2 ǓMk9irY7ev8om/eu J)iخo>x}LρZ^f/NM(/9eB<`Isφ<7}'McYr0L}zڏ')ߙ Z#{u~Miؤ7=x<-{k$%yuuzSi2qtv-UϭU]҈,S[37?|$_<3xɒYz+$SCGbkyfBN849byC{'۟#czCJ 7])k3d7Ϡmﯙ>yg?o/?y^@W~7?2c,smWDϫJ}m!XJZ)dxΩr0/fx>8=Nj̈́IGyo,Xj˛7:7F'%%yjf&4kv$ߋve36l:c  dͣ [(թU2\}P6!])mm9%5w&>+Kilo>rf#9ЁRzNnt dupePi%$@[-3~LШzzCz)UN!/{|L_h@ן S- &wmNB#^CVmm&7&ϛЭDZvT64Ў*V#C6[1A#ޛ2`; A@@/`h(*f9~uz2KJ׳:E6R$oA[ߔhK;;zvM!npwt3$l/֭]o: ?97 9v0w?ӡcpRHÛmLY봞_~k=7^ˎi-okڂ}F 4x;MwQ@@LQ-Tr`plZǁѝe LGTSX_#/--5J$MO.?_\R!dE5ekȵj,׻2"`Cr\r!ý ͺeΪ_Cp2H2/^GY;vG.vc#fmKgZ9mfSbH2&8v[}@N&Q@0e5tTvm(~ 7zn'䐣= Y2[.ƮaFj L|g|4r,U_!fǞoh-3bW[0qnQ;<Ϊvm8R^3_~ŅҡK[p^㧧:"wa #Ox?dAOwS5˔v{)flpTcy%ډC-˄?f&n+/7v{vy֩ިop; t-qu9gy%tRFF7Vԧ^{ӏyn+ה6;]0XoviTzG{H^Spwb3}G֜uy=9hwAݔRKnpo7`+˹74S.QӺR|9Yj^Awޞ s^u)Sh)0   6&nlWX@^?K~ٶLJ{9]g|אe^(aT -ү?)+6n=첝fqNUN'1}P$㯳2oµ'hS9yah5 XQj}k~MlQGDfSA=k׵ST!n7ܝXRe&&ť] DRîWk/l$Ox>UCZ tԬmZ[^#_yhx ڵ{0DkJs\t }E/4p};"ueZq= Ph}ҴV3OY/:tnum6T; ZS 0ƒ?O=+\.#'y-zZRqZGA֮1zT86jp&uמK^Gk%Ns]|0S}?joL>R:>n{lveۭ)ZC2Qw6yл.ݑ꺳{c=Z|NLymz:mQ7D,@wuyӣGaǙּ"zL=mn).=A{HQ3ymڙжegnpD;v_u{<"  y4}i e:ͫeS$_rjc)m-sG"3l]3 3޿m;%ynKcϒ F|#8I6q41^Gm۶k.Z%zZ30i 7y)yRSzH!n0בϏ!\Ɉt 5pl>?0BoBHZv;#kM'lctJa=V7N 6a97n1вC!|p\CǾ3ٔ[jaYuN.|w<:I=X3Z' 6@ѐ1extRe)n&H5|=a2v`9"E63jUqY Õڲe4- =oNz$e`\_R+EsNVp_G9!a'։{]u˸εҪmh?nLSfw;Xs׼?tN Me}f ߒ,lF@@TQ e:#}UrMoont~h--JeOY5엙p*%y﵎rQ'HbC&wdՎ2Tp=}P$㯳*װ]kۦD3j4u)-iG}Z ,6w]wIGCu1^~٦eAtZ-ɔ!(YpE|”a!rr7levD{Hw0?{0װU˂}Sz.^YB|KI -M#JSf%z޹pW!F)ޯQǟwgF܇ǂ=hz,5\ m &L;@M'QzɚOHop5]oy%E(VGKtW{0q}s>MΪZ7ߝr=א^ 3k`K=yD@@RQ-Tr`pO=;C\Ɲ[d _sdMHE z5u|uoH U7_RFօ,Jb51Tr&MڵG=I!G(Q\t\5bTt%K#Cw_ܻ{US'?Y-qG[i=.$ MkBGj~t@'Nۢ!Sj?9#rwDjJDz/c֮ >>ƔJҚȵ.mntTmmWg1\y=P0īNRGOJi~"Þo場,TVŋ00ٞټyR#ϟOޝs䩁/ؗz|nft޶ڡev^1RM!rnyw;cs<MMf.&')k&0Қc]{U+d@@@ .6&ilWEVs po&>՚IڝB/+,k-LKΓ[TP*>-۾Vf.\I| u[z^R)v`{]5i$>#S/"_rj1I;y:핵qG*MHwߎ`X);tl۴c)Z EVsG1L>vNt صauiMN|kֱ}A@@,`h(*f9~u0_Jͤ\sI.kP@5ۜxT)u\~n]-:#duEO3HJyѢwئ{Lk gUcJ{W#sϳ"bq'vnu7\!Ӿyz{ NʔI3eęIzjy#io](XjOcndEاeC 5ۚC6k\ІmX{~wM C 6Nޙ88^W<6)%grD?Gpu6pgu7\.EW 3a%+?F=s>+O/oQ]!ډ 㾽N2wx{߷HsW>w'x֑荛{?t!;=Zg}>jubx+c?r]:SegU27$ɔtHSӎ u3߾,Kn6vv7 ȸf,:z_y(HoG9T,Z-`OJ24 oܬ4l\'d?-p!j끴N'3Y{ʑ7 Wj® 7=}AakOmp%Z4ޫ+~=Ηz%D mf%_2tHM upNwY-N Cߘ|dύ|"Ug+'/HH!KSL㑁~HkWΚkkNlߥ[;&Y?J;n #M^G/g7ty0΁z`{LJvhEs>[uWzwz]6oE'^֦FN7-'V/\KڴgYo;;wچ =wqa{][BpJ@@ͣ |*f9~uwǞ+7X;idYcߵYJ/*G*e&M |wbkW.PFݲgyhb IB%$Ofe.0%5!Z{^U XmsK8ei=XJZ)d qjP|l^2cڬ0X]W% y!޿DNIODQӟ~_i?C%\s`>hh&õC66/X 체}m14P:WOnd.BХ=i>vаek6!om-kڢ4hx*#1k׬;>?'kT>O?K>~5葓c:N;ʹUϳOJ u^u v]qsp7uҲQet5wئ h-w*n&]pW_G֨i]id:lvz3Fxh]G'6N:ɪz>$.=w iؤhν_t,jM/\ם xS_ܵ7o^YlWfJӿS=ϨݽLw|5;]-tOzM;L疚[M+ +h3?-tḢ vPop76Hѻls[Q@@@ ;<>ʷalW+W{DKtH*|`l4ͻɳsʚ-ЁR7*ظEz_J.Z:aډ0i}D %utr'*[n'NKĜw~j]kpP[iYԽNwQ0>n& 6-2lkeFi(4-2ꅉFG:R'))InE].s+îӅZ֣ᾫ;_zWf>?tN٭_5EG6;Gܻ"=ޏ8\z[=qbWޒ/RW 7\NOpcC5^K90\w[ ۑ{8D=7kqhMrA:߽cC;+J>oX}=jh߭'Zp WJmmڡa;E^eԀ^h   ]lMpPQ69Ca][KҮ=r IS.MU=(~#3OrI (ٱ[vo!s~R@mN:y5؟fɶ]RȌrZ3J%{핎sSFb y.D̈Q lLoG:oA^9)lu襗_ #Ow?ߙ2Yv KR3bw ^wILEnDjL7=O8)'rGr2@ֻ. '\t&^3eRt4υJib:*΃4=_+֠w u] ^z*l{ Y_m gt*(u]G woW(^FN,YA+QNJQwn76- -$rwLm:rrLRȑ'9IVl]'K[-l\&vBNɝHkgqu=¥Gڜi$2w'iMk4N/dtXiիSl2.zx {PNyv~xgˆR q;- ud51ZSTaþi~l )aj(HzW̍ K(n>oq)[T&jv$f,EL5ur^nƾTR\j»괷dܘPT~妌O±.yOzΝLz^J%t>X(kusNdJ4cu (`cr8vviN^QһoOc<vrdXy w2s-|<%xdKe)o'r|'OA>#A@@ <>B9xF` 5l-=N 4gHM&[ _M{M{NS'_pWД1ϣT8(|$}4p/]BtVzi>]]{=??MYJڶk1 hpWflj@N jӦͲi㦈j2eJG\ @@@@OQ[ e3V#@rRp.    p <>klj}9    !+`h(_@ q@    ͣ |*fF8C    6&Z( @pD    p <>WgDI޷7VF ɕ[Woð?    }F-%+O׶l(_rc     笙/,9}UjJ2Ur    $H>3>AW!E`@@@@!!߸kL_)%sA ׯ|,P,G    :1kղ9nX,wldZ#ЉW$IDATh*)Y8c@@@@S>y)@@@@@=}v9@@@@@1     d#{lt9r*          d#{lt9r*          d#{lt9r*          d#{lt9r*     9>@@@@@@ ; qWGF@@@@Y>拆@@@@@'@pOp##    ,@pOpE      'Oő@@@@@b 'a@@@@@ '     1 |Ѱ     @ wuqd@@@@@ ch@@@@@ q82     @1_4     8{]]@@@@@ f{/v@@@@@H=}.     =} ;     $N>qWGF@@@@Y>拆@@@@@'@pOp##    ,@pOpE      'Oő@@@@@b 'a@@@@@ '     1 |Ѱ     @ wuqd@@@@@ ch@@@@@ q82     @1_4     8{]]@@@@@ f{/v@@@@@H=}.     =} ;     $N>qWGF@@@@Y>拆@@@@@'@pOp##    ,@pOpE      'Oő@@@@@b 'a@@@@@ '     1 |Ѱ     @ wuqd@@@@@ ch@@@@@ q82     @1_4     8{]]@@@@@ f{/v@@@@@H=}.     =} ;     $N>qWGF@@@@Y>拆@@@@@'@pOp##    ,@p̓_~]VZkw(TԾGy{ʬ7>JJUd?,7lV]#(.^s;wٷO+ͩ s޽GtwnL:[gFNK_v5{RF>7>Ő 'Vk@@@l'@pOp.ʃ}B̈f N㢋ϓ`;<=   @ypxS:㿰_nGJJ>m/_Nz}c:6(+}:Բn杲^?o]IٲGt@@@ȶɲ|JYr褵V7f3׬YM[ iӦ6J!*]vZsu6xvGH)swBm'z:mc*y2IϷn[?NRr%%wM|LVʜ1%KmzWzReKWH sV0lzm*Tȿ.b qڊuoҕy9ʉywoUiRMrr7UDqѿLn&0M6>%=6 њ-^V֬^' c-/%J~hT 'C OPzK^3GEz[NeʔgH֮Yo_B~5}"    ;D&穮 |r:v<5:TրYrI:7^Z:Sz2Eởe:ѨN8jn?i«)Am4<,iAN%o>?2^*n uŖ-[mmmO^{\H5b|ON&Y낚Rf<ä_.iS;1~nZn{mlb9ixw>NeװIu.2z=xt=W\Q[&&|;|pKL!~}ESԻit=a3j?ѫ].W^}\vEmup>G{#LӃ^:tc˗k-o3~2qC-uMU.߃ v`?=xRe;{рmGjZe+oz{vuQ oSNGރm﹯)ZX^xn\unD r[,ߵ3;3e;!cevyy)V}2ioݦ,<5y?u6cߣ~g[M4E?5һ#xw2t7+U<=5#   @~\&htMp!XZ uqݛ6u~MYxiȹ9?wDG:ؽu*U$))I:?q1虞ިah&oG\8o  d ?^7vyl=N۹[m䅗i#~Cķ}K_q}l(I)_ʆ; m~ZC7^{ 6u6=yʣ]v+Y잞^;NNĪq~Tȁ8V y!;H7 {6ڱ=l/rf9̧ӏ=YgܹK+8sG"?=u M7nrTw;^0\3si5[ޫ"k$:ti+_qGզw^OkrZ;E?=iXo;8zoÏ']R+i @@@ @po%K{q:ʽ ԅrwGMΪ~z/aώ^C(𳪝.'?y)OSR_ih[cDSO;Il4|:YëO>2$7iHHw$XUC9r^ॣuD HW-y%ot6= n\4FHk)M?瘑W^s+V ~C3BG{_΁'ZrkHq 3o6%My%.eF.]u;Za5zFtL蹹ngO白P_;t1p_nv _qELN Yoap[0jwt&٦{uslu|:ٶ[]'-[7/ sNywFR ;:'npoӎkהMfq;B^I]ho٦^+ ?e옩Qo6܍3[4=zowл:?{a-Rp%j`H0%LWzwϫ "WY   Y#@pZ٧GyWiLmZcܘWEN5Un|ڵ/4>~x?iZ+y>o^˃wo``_Gצo Zv\On('xE>]!~3a67`>kfdvE1ƿaI'wGj;Fx [)dfcLw4nPt޵4}ӾJUCI軛Ba=鯏7L>u?Byra:^ }t UoO@{)A3vtJrɩk\/5wֹ۹|u4L5^koF-XBqѩkČwڴAKhpwxhMo 9[Ae%{aZ23oۻ;{ӻ9 $X'<エݮKQ;D49իCZnhw;GNc-Y {{IOni ::Z!ϼ-˽{!/mn swqkԳ=SMЬקUaKL2\#gAa/?/0'Lwtل)R%jqę2eLvhG|zm.sN]3B^-4jzwJKwp^|>+/>ѿ[~4@@@aܻWNfh'bjF |MS"4loq 3^qk߸?vKHTrү=>dRV}SQᚖ^ݻ >YBm4eLzu s4Mh|<ȥj~5Ldm&,%ls{Z=xg˹K5SƝYnȴ$=޿5]&;.nہƹx7q;Nɮgڋ掇B!O~,].tgXHNwVnE:'#   @ip%T65#^Nk۶ިN}Rid5εyͭ (2ƄޫFC-Ū-ޭ6:83 BVjnE uN{…yh!xMJ#7wKD/ܽ0λ7OAO_9RΜq*R3B V*.v td,Y[ZP m,1wVh%J^W$Zq:7w'C,=[3߃͵ow0._5ry~`ph[g&&|o}ہVz&n?uiv_}Iuh z~:r^I1rLJgfrsmKwKIQҨi]{(1\pvuI @@@@5䮦)5ϭUCzqCẅ;o$ Oo>[&v1w港m7o9V}:>0nL{Mo;SGoϭAKpάE\hu#SzyQضĎzZ#=x7[=Zںiudd}6w, gٿwҥkEkGG }t+z^SwR3w'*einp|ڑ:"ո4KݎPZMl_7ƈCyp9n\:^KZzf̨yܻߺ݉OT|I8=h'vfiTf{ v-i]DSis^1Ws;o-wֵ^: ~']qy!wh{C+KB6:LD<>e"]ˀI).߽{n;nPN`s]xnρ    E@IDAT MUМBdVDJ$JfyYf2'4(H&4x+ d&),no=g~>c&9IO;tT~oQ)].;.y[ޮ*\*dYt{jMrɾ}HG[5pHWB:m_-}oǕ+U3eάy`׮[ER.zmd-rYgy̛+#֪m#[ Οl{jת~ooFZ-۶mwwcJ >n?3)ɐܐÿqJ<9>+F:wx?Zpِc0cyu˯(,'&}z :4AҤIc2:7I·۶@_=,^ĭOפI#Yd3lfZ6&~XcW8~i eg:]ѻM?ծ˘<6kQpd/.6*+ uf۶ҤaOI__XF ƞ+/>o8_~i~[A*;Voi27%.O).YfoZuB }s1v>ݟ-ݞ3%~   $@ϧwZNN;MҧO/ҥI.SJ+|4&$l=Vpe6_UH9mȧ.M~\vy`9[5W֣KnL2W/[aO+wvt۰od.I{]^x ^u0UYk̗d6 5+q~\ۜ ֝%gsm=X=^i ɞ#(x΢e-t{vHsϑ?mD?̄rgcӾu x jV& [fRckM3?P(OmǪMŋHw߭DŽ|w~p`B9.f->X G,z:bB^0?uCQe&=M&E/ݔ>oJԮyy])^F󻕫lH^gKY5w_kxA5T囯' m]:IƢI%Wsnޭǜƒ{=VAF=5)h+]?|qkxry[c7x@b{kws&߅6p}I I\eϛ Ϛ+m{]u"4Yb1    T޶5*#+$Q~\v e ^yKƍ>dȩ"x:Rܿ^O½kBv-o 6Dnpo׾$gJ%6%s&8Η _[ضoemګBM9>$H^?dSB#5JpoWU~[ V8^C-g;'0']{bF'U{bnuovmgƊ4n>& ܹs 6̈́aZӑ6=9k}ѣˠD+~}3ψxo<5d|-LB~{[N   $}SL ,iIAO zhް'2iYASbEa{{gv73VLKر.ΗW %J=j6h\H0;pT7=?3{uf^ʽM?w!NrdFFA-k#&|᪖ч S&͖N3yp6vf۴\n'ڞk'J~&z\h%Md{Wiڢhyg?!,h5Li<4߰TT:d{R^۶(Ȝ9-q>ZC{f}k'?oW.CCh5В4~V:&TKxЫkةkd%/hK0NfR_#ZCyeL!Բs6?:\ZjmgΎ>¯DH񝁽@@@@-@pOp[(W@ ܧ̗Ep2|    :{SdL>ePqS@@@@ ܟ'#g)ܧ3   NԵ>>8XmY`vH޼S#MS2r]%RDžq    @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ Ԕ8      @4 ю8     @ ԔRin.-~}/#T [R$Fkəg,3    =}JSY~X#-v kB$ -cFN ͘=F2fgR Q@@@@bH>_j䓏? 9F6nbXK!    7 -NfcN{g28u="/'DV|,zq:)R*> g@@@@<{{9lj7%i:wk,'6s`.ӧ͛/쒫,͛߹W9 %Kfܒ&Mt!9C?GW?3]׫uׯhKΓS8ǭ8xl1e6I6dʜQwn?^Zӆ ]KaӸL2J\قkoy,䢋ruCXD@@@@  c'v:oAϐݴ}K.C ˨'M&ٲg~^biKe֌drq2j\?O6dŗ+\KZm쪉Oϔ7^{'5郀۸Cg=oWJz?z6&Vٟ_&O%;d.1e#5jW 7JK#/>І$z7,OMmto%yt۟O:WZz]Gz    (@pOp:'V4͛KLp&9C^z ?*w4%ʈauC~^a :nXH~7ή^Mr-&йif4_lED#}(0e9ܳap:&C%w6@@@@ '|6elڸUikƌU\.Y^ VKrpȌ '- 6qW dyH˟4X|!jx}uWڞV u3{=wyey}@i/}OEnF^|Zf+矟ܫﯿrxnckIS-sgwK \,?^yd@@@@8 'OfzZ5s|W ZV  KkyB*-Z7 >kႷe)rB=*\6~x=Dž2qP1Y^{uQ<ّLv_ҥG` ^j`ki4n!8sM )K3e۫]7Θ<฾;ʵn=[IbED{ͷiw4&j{K.Z_ڿ=S?OKw 0F-&CG +A@@@@  Skh߮uoA_I0h'Wx^m?+ Jd3 %h"<թfe)TW8KA@^M~p=gc?Mۋ{.Tz,طص|WҵӀ`}F5K:@Е:@ǪۙA@@@@  S1L>yu5 #OW;}G ;R>Jl4 wSRJ mkI9Ow(X{]. Y5Gq%wtA%^'_TM;}(5%X3f? k?/    {m=u+ϸŨFp _v^݇U=|j5*J_vyTtf΢u.24 Y6Ppo<9si>uJ(2iܡCdK㏖}t~аA2H/[\Zbre-[nJ^ feLPB3p_;z@@@@bR>En,ʉ4u]*0,T(|vodEe`{U*rj <(\;n [^W{ν!9{W^C7Nh)mڴn?@@@@u{mñ<8m^C-{e#-Rzv,?ZpYW\y -DgZ6&~XcOj-[Izm^M=jMN^n=[IbE?8mq[A|yenr:5ת$U?      @pOpXY3e?pMZA ̗l^f@\-daݻwhRٸaKNruW'u )_.: 5dpH y d_ӥ{K)vvhj֡sS{Nz+riQ2fѱ@@@@'{xj Kr=bů[H4i.b=ٞ'ܧON?MCmPU*V.c%GpIcΐ _hڢQXF@@@ {hǺ ?ۤy!XFx&X8ehwr6S^{G{c>unH={?k# Voݲ];]~yd6-zw߮tEK{yTI.m 4N?ÆFMjI2)~z_Up>o<5d|pȱ$_vrjr߾?dάW9}܌~7m;4Bf\&@@@@Q>)ɦe Z{9gY2I\sI44Ikzk1 ֯(l3HLoy-1y'oNc9xk!уو    @ hӍ~nlYMvF@@@@)@pOp:[3Ie(Zt*    b{T<4@@@@@'@pOpk1      Sq@@@@@=s     @* 'O͓KC@@@@{V#    X>7O. @@@@ }ϿGg,3    &{Z>L<'8FKL)5o؏˙+/qCJ}4    1$@pOpC.5k#7l7QҥG!B@@@@ '7Gp_17    @\ Ut3I w267mݿ&g,8Fk<]Jxg"z|o~9ݕWCuK_{S7_ﯖsg"ZWS^(IMfxq-)̖~IB9ϐ,     )ެWZ+fΓ/>~v"WK@|r- 6ר8L 5fwT09.S1Y^{uQ<ّLv99j܇w{4o6Hk@vy!eia{S瞝׷Gvٿw]ѭg+)Zh6{غ;əsDmtoۥYkUGze˞U;<`,[;L7     g)ڤ5o׺05I4hz'GxPpg^Y7ehηaqӃm+URF|ˍ~dqz>7kJ_ыkWښګ~PW fP]#_.>tBțz71{]:6[o/nEfum.@{ݿʿ[? S~pˎ]ҫjZRf`ur]^@?#<2p` M6}Bz;$O@n>hz L- ooH j@@@@bZ>Epj uvz-$\%.Dƌ zCdK㏖O8hX}j {t$˗.U~-yk1ܷ1o*pSr/L7}.sd2.ȒI+}GBY    @\ܧhCNMrzEMvλn uZV'4u]*اPvٵkˊ/ ɖۂV˩%?xT~^p: 츉l{]:n]{}xԳo;kܢ&/@@@@x 'O6 /#3uH:{ ۶-4jR;X^KuphGe_q2ph`iٴa=R{7i]7 :':xl%E'S*7ouZH&gsů_V%Z`f@@@@G{oϚ9O+م\m R`dj?;EyvƋgP|6o\2f ZB::޽GK [}tk.?ѨSHM8g̉W2c I}Zg_ҽz{{5й=nΔ+ZӆE.@@@@g{xn \N7SN& AX:AK-$M4vHl ӧOgk/yӄ.=d}Ub2v]rO4 ;v -Q>e@@@@ 'ˆs拆n1{dx]|eI!Uwg=N*RSԳwןZGg޺e<=v,`mZ]m\Cŋ©.]:^:hhi҇ Ԓ:5=_Up&Qষ|_2-ȱ$_vrjr߾?D*|m;4oc@@@@x 'v}\=Kْtd6e=眳m˹瞓944Ikzk1 ֯(l3HLoy-PiL3o-$z0@@@@{8iʱ{#~ \-q     R*3IMD[VIݝ@@@@@  cr     @ +@@@@@ 'ʥ"    /@pOp;D@@@@bH>+    Ŀ=}r@@@@!{j\*     S~g-7~}ٲy/cl{Cdg\{y-<_jaUmٿ.{\W/2g+"o_PgVfNQn.sgLl޼UHtsV2[n^    @ T-#$oy-Ҫ]ck_r.OOlK1^_M~n"7\#ӧߋE޼d̄2@@@<{{9097z,x孀`3unHN2ΝJOlب`6Jdһ_{)|1GԐo[*6Ow|rUd)| b={ 51FieKF=ZTzL^u*E{rW~ԩW%E?;>c>!Ϛ̜Wiڢ^6@@@H]&5i=s=GN7CgiLR[ҦM^O%a\{- >u6I020sK4Xx^(l657"w&reܦ<84}ҽ`S-Xfܫᆟ7mY2ENMs!ٸa!/dglٲz\,P kO"gr/M{nz)!Imz.=N >c߾?d ^%btTמ+U+.+o`'5;xy֙GVZ՚5K{\N +K~ӿas=;.}h1)*mOm 䥟~! 9%B.@@@(@pOpĦۻiwdo`ݍw{7_|Ԗ} ^߆CwUϚ;{|WlPtS]QԸi?vrep]nFkרUYJV̮p2yj 1#A9cMXv)SNd GGwK]&Axˎ]Ҩ~ۈ֨]9 ͛tM&,t/U=`{Mh`?}\k2]{Һ}cɜ9c^Gk[UF^.zg,~{5%ئ'-_H(Sر5ZA^ MNGf43Νîٶmԭ"|Z#n]zx6lTZ/|WCթώo}FlC`].u~1}%y[@'}{Av;nwo/m4\~EAhCL7_7Xwߩ?8Yȴ)sn//rogɌ{;obp: o%~X 2c}CUK8}?[O^RCK᪫/Klt\:)| }Z6e+"Wu&ߓ>Hh֛Co(>'=[,U*6{wIe0Ї,SM/q}#Ÿ"GK(O(c4=Ôb ~>Pn=%3ϐE![ҺSWkkmxjlhks5fz_)Z jo!v?4P[[ëe)԰W6'M8J3ot`P}H&W_|&g0o|l:p8-u4kY_gWMoA:}E k%}Kwݷյ|ʬAN}ؾ<g_<9ޞ[R:g= ,WdwvҶeO;Q+ U߯%5ߝa#=|B~WuTa)2'v RMcFNAGC ^:UYQ{vzs -/ZKtU^{c-qS:ՖTҷl^2o :4R],=tҷ+|@@@R=}M g͜gK3.rT^A ̗,ע἖^ЀٹBwkUA]?;ely~3#uǃHOa 3{?X{Z5M3=N'ZM6T'1h9 _uҚٽM)mV7tYmtlm=|ﱦ{=.i庯hoq}Xvk=6HtAoJ= wKun킷¿Gw~=mB4PMz׫>8r5N'Βj;jozVi2褡x=lxSݟ҂)ШIm)[{zxkЮo3h UK:ogiİZZުB:v)o{ʗe+,}AZ08<>XpwDx^ WmCt9݃?iuanwsڟFբo|O.׵Gq'a^!6k7+y@@@|{{=$L&'$VțM[m^+\nmݼ )+=\V,?Tǽ\o ̊O-awlr~(oF[$Glhӡ]L^Tk?`)wi~{G 捉U?}B˭hݠC\@ Fۨ^[rACXu)OSZ3IZ6f;Vhz'׵Uގ4mXP_\-h?7S Tpq>\&z ܛ ~.`Ʀ?m6 mmW>{^vK}1:m |{~eWFiѤ=o fK Nچ^IDATMϯ%rsuRWu_ZSynԐ񶬘53ʼ5@+yo,Ï@ύO~"wZH{@@@H)>{^^LYGZD~<$˗})XkC%-ݷ&O9A]ʖЃ?3zJ-5xk]/>ڮKAyl`W?{6;x3ZE{.'a~~޵ t u>{-%?u\]vu̺*y7߫~Ӄ-^cꇃk]>ih~)sٻBB— tG,Nڕ_{ԭ@;^#Bjq纬%N{HP? K G؟c m}S@I ?p'H7|ҷ}Mi,lן ]Vᯋ4Uk߮[wP[CkANW֭]ozwN7ezmwBSֿ`J'}#D :?QGʔs=yC'q%\gJ^M/Qv+@@@HE)+{To{wWqQu5\`Iu? '%A1~{'VÕHLm!!ngx ? sXpHe4t u{בJSK|y$<ć k{s.xcJ뼎пψDۥ&ZEۣ?;Z] }S…[Or7czZGb{9=\>4u[f {q1:Iq=t_7Tk`D}9~tyeXX=oXH?T%AZ1 -?[-n?[{4!%7h\Hi#OsmIбN{7#tKn3/ӟf$3`W{uJv1    'OѶw*{}jo)j즮yދrہUxB a2O~{Wb ct ę~Xt|R{v7O$ZCKqITVmӟ:O^?C]-_BW5ih:m֨Q;x+\ok]©G54 *}/h_|w:c]9\ڣ {=@ru\\ɞH=Mj5]ղ=:YCRvXώTN&ұ?3p~})~B4،^ /.U|\yeG<9#SGourߵ_ Hdw22H6-3WPBvJGz~7iVלC}t `Vw1ܛ!(6`{K.ZC}B~ҷt<-ki(Kc'=.x[ƌ=҇[O7TtKkrD:hrg^Z]P?e@@@N=}vf3PeUF}<ӏ?=ZHeG;\&~N,:Ӳ_JϮ/u0^~4f\Vr4} vҔ(S XtYúYkZ!^f^nrFrmzbDu Qqmܠ _KD,V(S}QSe'EƵ܋ w!#g(:6Maz?i!uFqt|5!_:Or]Bބ 9 Z_{W~ԩW{nkGz߿aH@~I!Q^Ri_=y[KڮnԳ>ش?V¤f`e   ]>ۨf3~e?pүk&k4KڋT{jhD>1j/]TMM-7ڛ[(4ҁf7nb+9A 5%KkZ\k뤽_zatl/x`'3JqZKhO]43~@P%9{w~,$ÿg-ӓ7@t{:qs^`iiXh"f$ .^?YN?4뙮2-0~u-J9ydSd9I]Oˢ>ΡA߯ BQ ]`낝 X=wƌlݮgh(&[@T{cFzpofL8IWr½\M`f\nc%gMv=|ܻA? PObz-em7N=w@t [^xMG`zP)>{|=Aw]mM{Vi ̙3ޯjV}"wJu.P67-@pœ;O>7<~{FX2)C%8_HשO ̻kLsp߶sc<q}~t{Ze͚^[?WO^wno9D:ށ{.k2s-~;;'\L   =}JSY'kO@lگ ]ƌz˃2nncJP˭oب0a`t#V XN~~]ݢ{c>unH={M>Th3Zi-g`JJp;kC'$Xd=uHohx"=y&yA;.o6h{uNAۡh˄   @J[=A7:hlBkڛSK~[Kd?쯿5?+mOwljOs;^iͲ}Ne=眳,l({$xݵk-5ՄI 5޺ehpjɕS1mm)͓V;/5C|mƅZ'~s̼6n1/wr՜+wN9ýz~όc.s3Z~j 9kkZiyfׯ%\A)A ?kE.4oʝO~Y/b<#diX'J fO?K7!G露cNlJiܶ\~O{}wgybjه;x]:oe5=?   ))@pOpBd7=jTil?esXў|I/:–lKk@@@8{i?P@V֞ZwͰ5K8iq:2G'@@@(Gq HM_|t4@j[6f-uDr*IEǾӥKs2@@@RB>%)(۶i[e| /=B }=`}pH;@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)@pOp F@@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)@pOp F@@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)@pOp F@@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)@pOp F@@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)@pOp F@@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)@pOp F@@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)@pOp F@@@@U>^6    Ĥ=}L6\.@@@@W{xm     1ph@@@@@ ^ ms_     @L d@@@@@x '׶}!    1)_     =foSON;MҧO/ҥ4iݧL'z ߡC_Ɂߚb6J7?7h8ُx@@@@@,`x&O?܋ )'     \'cmgqoC7>_     h[%^}Wϑ[xY@@@@@S.Q&mZ\a[^u{ m{mnizʿ.@@@@@'bHIkN&R9 KܻO@@@@@S/ܧS6;W     z]eJ:$ e@@@@@HE5ON:!OEKA@@@@q4f@@@@@N=o\     @ ZYIENDB`vitalik-django-ninja-0b67d47/docs/docs/img/operation_summary.png000066400000000000000000000675021515660254400250120ustar00rootroot00000000000000PNG  IHDR4ZiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i4Ŧ1|@IDATx|E'{EA@ADŮv`C{y"b}UXi{补ٰk\.o>vgggg{dB     xX mi      %@@     x^ D@@@@@|@@@@@@4      yD4@@@@@h@@@@@@ #      @@     x^ D@@@@@|@@@@@@4      yD4@@@@@h@@@@@@ #      @@     x^ D@@@@@|@@@@@@4      yD4@@@@@h@@@@@@ #      @@     x^ D@@@@@|@@@@@@4      yD4@@@@@h@@@@@@ #      @@     x^ D@@@@@|@@@@@@4     C ФԲo!}e xB+oQq6돐Sy<yKV:O@@@@@׮&iWޓTvWvH@@@@@4x67;{8?+;Z;o=۶zL@@@@@ (xrW^zX T0CK|MB@@@@HD(ӿ6Q     P1֭['s)굵  Q~1]y5akڴ8hae9    T $瞦ϳ=:Mk굵 5 kh(k׮k=h/7^o"    QhaW_}lذA(jW\!O[3w]-iRPX(M4*WJJJ\do~+WIv̐iԨ46=.]:IZ.Ϊժ=䇟go޴E6l$y&Xϴ4j@ڴi%tq[w%EKYJUYk?rWJGP 1RI]" ؾ9Z_´_enF@@@@( ~ʒn A.FW'tIi=+-h3N 8`" ѕ~vf}[ ,`CtU!fj(     h\SÞ~ QZ=?4SpGb؈6-X8HwuWVicG<26|*|#    wP`FiFbMqQZ❹Vj|k@EEPN<վR    D%,Ѯ];Y.p:PkY=C y'?iްZ"Z]Fj2oH,ᇟ8}Ӿl-֝M>ӦN~}{eʊmdԘgBg!ܛthow?mEGK|M5i߶F'I-}]tm    /PGwI 6PZVϱNeei hz7TzԩS*mvy"_Wr_zyrC?rĹSc^_4;@_[ hrqҶM+_y?s9w]ۭ[ =)jt8K2|FHv} H.1d좼#    Px$A |%4))k {\u\q`V\ɕ_`̝vE^GɈ v3t뚇vHj<d銐ǣ=wϙ:1xi {no}߸is|2@@@@@D O?e5M?E0#O&~J˖ +ҹsG9! ;L 3gn2f?˵՗ws9Liղi1A ; 8?%5EN; l&     "A0ӏ0l"tyƠEHKK;oVHhmF4i[4]b}~OH{#jYEKe2mt_":B     5}ᅧ["ly:DIUd%w/…ާ; B֬uN?32Luǻ=ԇ    K TPCgx)'h .4mZ"ږ͚ɼ #)*7o [.\"쉻nذ1bQٸqLz}yduMn'     qpV=j(8@R4VrIn*Ɩ_4DGbkoMY;vED@@@@"`,jW f8*NR4֮ a֏4խS;ҢqX rZs9+C     A )G{[N֭?i]zժW+ӑիU yhɵi:MWNJ.eYE|n< ģ@@@@@, jn߾=*T ){i)}cGb媠2WX,;hQV~^H332#-Zb_/d[-}?VQjժigK/BQlD2FĊB     H]&)[c={!l9sÖq]s׵xrU`Ͽ [G̿. .Z!oܴ)1-n@@@@@ R[҄7 w:6a”8 t  ㏿Dy*)m۾]rr}oeaM?Oϐ m?.8Gx ۷o @@@@@T ){Se!do<@]ego;w?*OzqB촘֮Y{yP6P|6Pʝw zx%wqv@@@@@*@R46i$vˠ/f|9kѩI](UV y{|,69M_f32CDZtي?x!끂  {nWf>Ufgn<ˢn^J"_(K-     @ $PR~!,~tQHJ̛PtzXRժY2pi2CeYO֭͛9oK/=иQ[S-[[W2M9Z2w>/[)Ͼ8^{83 ֵH]jܳ,5k6돠;gʆ vZ&v"I     HF.c_Hi5kќ7,yc;aGwoh-:%{_,w˽f˺xe4]"#*#mBЙ;w~׃&>xmc|l     $F )b:ujC;3N8$Ut+>K4 TG/K ɼ6[y]4 @@@@@X Z5o⻋rk|(_8peݺǛh*oNrsԴiȃGUY=%x6Xګ&?2K-[!kdKN6iԤѺj޲ TrҜo> ,2&e+W223̳2,i^RϬBB@@@@H@4@@@@@@,aTWN@@@@@@ JQQ@@@@@/@@#\@@@@@ %@@@@@@ 4o@@@@@@ JQQ@@@@@/@@#\@@@@@ %@@@@@@ 4o@@@@@@ JQQ@@@@@/@@#\@@@@@ %@@@@@@ 4o@@@@@@ JQQ@@@@@/@@#\@@@@@ %@@@@@@ 4o@@@@@@ JQQ@@@@@/@@#\@@@@@ %@@@@@@ 4o@@@@@@ JQQ@@@@@/@@#\@@@@@ %@@@@@@ 4o@@@@@@ JQQ@@@@@/@@#\@@@@@ %@@@@@@ 4o@@@@@@ JQQ@@@@@/KNtF/@@@@@@{]B=      @JI      Pn(7z.      ЈTr      Pn _<ԝ2U(@@@@@@JJJ*K`M(((H B@@@@@ RS'lrWF, r/@@@@@H3 r8ߪȮЀv2>      3pgk`v{? h T }wt*@@@@@MTvBm{Y.+Y hA g"??m; bS3     + ;9iiiF/ n%` } l(} ;     D/`5^hp#==xEi)ҢH:J"    $N /_dF|>hNM Eҩ*M@CGdh˰GgڵK&UQz\|H{`\ @@@@@.([dqdffFih0C2JhD=9ɞvJf=2Z@@@@@@פ}w}RoR4e54S̰(      >zפ}v~T$7k'9kҭCf @@@@@O׾{~[^Heаoy4n-: @@@@@@z>|~kY4a_Nu4 vrҋ      ٗfDt2 hxm4(     >/Y@þ[:yG@@@@@p;˿eE-(Wnv      @HOD5z͏.(EcC\SDJ_CB@@@@FZNH@5[D_,Pښ8T@󤯟CSQMl@@@@@ T)fxD*5g    xY f^ѶdП1Y#!    ^|@C !@ V\@@@@b|@C'!@ V\@@@@b|@C/&!@ V\@@@@b|@#[L@@@@@H$@@@@@XF?\n @@@@@d ,O@@@@@@ h$@@@@@H$@@@@@XF?\n @@@@@d ,O@@@@@@ h$Ӧ~* PV[Hx~iΔw~m._>6@@@H.*{naҲe 9'ɧS?9dz?L4٪sܹr@ҺM^#q@@@,4*˓rU?sth(ҪH"i)" D6oYED~_QH*lC*rQ)UOuެhLY/ 2UW+NA~<Գf"rP(ŇWHaa}a#G$gyOVX+UE|S/<7.\(oL$sM@?լQS{Y۶mIOٕU&==]re?WWvWځ   #^4w_ "dT/zq)2BY!8q{@H,i<G 4^KEudvlc]m''g[@n,ubW3˗jjܤt޷-Wr !ceg+}?Byuߞ hxrZtTZU6o&[4ڵ `9   BFx7KH{畴>5Ez7tP:B/, DG)3rIS\>򘣥YԴX3&6uAg{i$%,k3WR0x]_fcfQtQGʐ}}L|2=kcu1HN*odƍr1֛s-[&ھKSNN #   @ 8 (iG/n@W+W2‹iK[l;vXHڵ}v_d$un=6l7/;_g{*4     P#4J6JRc=5[~c/ҥoZ2Gm؉*"W%r療u8s6n˗oE8"H dRi/[$3=0Xr}vwbe5T1ޝnݤ*FKhGI%5->#4&qƙ$33+5'otr?9ǼG&پc礘Aql/_ _8Rty/6s;3`rKF eㆍxbysқeZ辻-[H{Y&!    hru?ٹr+dL9O^g<5+)͕-fk>[ p9{K^кӲIf-A=kNl:Li9C%n7ܷnɑ-[J&լYS7hPŷ7m$7mf+]P:ԺMkW<Ӽ_~U#?N;߾4T׬Y+yfzMLY_6ܾzܾC6nS=IӔ\z驒7WGrLߺykP?τ:;vmz#w f櫢I&V={s_3E     @z@.&tLÍVKnAT[WRҋ]X/;w"9s9u߉YƬh/+`#5%M2kZ̬@WK ZwJ>B}l޼v{b}L/}n(]0\3^pL,X@ wСcG?ZLmCaϑ*#! 0Sؼ?$/=LZZ\r%ҥv'uI,5jt啴~]~.wU_q&k m/2:͎l~r J7ޒQ,Y,ooQ5o.Z2S}#<ܗFh쬙Yu.g0yNFF;l_@CjYv^/Ԗy U6|3PzFZߧN{eǶjgG@@@ 4X4p:o͹U0RL@"J5Il.JZu|L3dB3 $jtiU"]uT&jOrK³/)\E_c#wq&C>Si ,7Ͽn^t`_[&;dsv˗/\z-Ad9C,Ə 9DGs;]y酗\A g:͓t#GȩOu|<ؓ+/}}wV,<{;Ͽ}~iv0Q%etHrJ 5Aƽ&~@5]Ce޼5`xIiniͪrE#쎝;_w ݳO=/~][4PGDu,}ȗqiX}p68SÆ 傋/vf   @pTWZJqmwPc[%;5eo$*GV8cesIdHFe8b;OYx?toGp:=Уֺ oU,VZ%W_qu]+,pU|Z8<1IydAkc z?SGm<61Q*PP~,=\,/:6-ZQ, 5}Aio Vo}vmrLc:z/eكb ߈AFY ]?֛olUgmF wpᨷ?wp[ 豯̿wWLSE N@@@@49G`kQ-{0quLcǡ={n2L7TvخXRZhagLbAѸAlu:{}O3eo7sJaz\ *PΑ-e˟*&tQ>̨Ubt"LU&ѩs 3{Q ĭ0ӎ;oKzυ cN,`&:x d9ck~Jժ%V|̹g3 -0??1h4zo1&p,1k˷.x^R6#K%rwl8H9SZj2gK/[[^{U^2JJP G^dF,YYUO3ms>gu[y+H`!   X*yMA wdu3콢ޙw h݂TخD?k4Dzu~G$0GʹK_Iեi:t֦q2l0;z_l+t{eqH;glf {!p&5,wrQGέYA+1slޜt ir!) 8{Ntt;@իtkr4k 5VoUI;u3S9߯Qm׌бˮw~X;x񅱾zofR: .n_g^}zF^l    &'C #1@ R̿Y;0+2'6qN&6uϴ::]!v֭g}Sٚǟ ƌ~\i:kkU3.*~eEs;Ot'*嘑"Nyu uGs'z^fjW?szpyH-f}uW儓Np(AhNq&qwz3ẛw# `pRdtdNt#7]w 0Ĭ8QG%?ҋ} g=YY}}BL74_vc&i]_G]8B_[ ]Sh3E2g;(j }:N>, ?%^q @@@dNVl̓5 6&+6 w9w ϰ:}Ksu7|\nхC*NR h߬~ݓvrɾ6tĸD49:h`f#]U,?ߵ_;ŖvHF~_ =*c q&Sv"ןEA:b'Tu1 ;'|:zidtO&HZ/㨇]\km=8m6ё=+oW~u`IU40h {{ hWҦfDSZ,k8L{ JV_{-_ܷ   QF%yָi}Ҿ_w vɗ}*[U[k;f#5%MN]Jj*?ʰdGtyyy胏չ;7U7ėW_ (\BJ `),Z?L$9N*IDAT4ݳtp2VJ頃 OIM:{u(/M;=\K˦ѱ4pm.~|(fQw]?iIfco_@{O>:UiѲ~3M|יq}{[ ݟ>+k-/a>N&3ștRI)3#"ǷlCԴ4ߡj7   Y 2k$h=eFhܦP~XTj:eҫMb xboUhNL >G`Ir*pݶkbD[`Uw[or 3',# >hw0bZIo+Ѷk,vt!7&=,.UbL4tPDSl5`QCvsg:L4s] w1|yX m{i>zh)VUzXC% vj9`ѩ~1S ]oK.\1O hvf@Y !o-q ;n)mAoX}kV;F&:BștF5Du;Y̷]Ͽ8mu%ֺaSK,BxYo+fl]^\[G"j˱={Jzzwأ2 1^+Vo DZ8'5KB+~6*O>   ,decSaIF<\?kSdy4252SκL)Evr3SxDv&*7&GA׬ESH3MN[?wz;`- l~޹>Pg6@6l([l K@ig_g>e4Sݺu弋>~2^s:+:3T?z'7OSju"OkZ+-³/իŢu_2~pyŗuJ:bf֔D̢իU~%]zd4zn}2q2k,ٱ}U&?4;nCvjզ\uRz ;z6S>x 'L/L;E#/=Βf \ ]yg^R~=Yhs.崝N:A7Ri?2cm̳ݧ-0'g|:۶icmorL;,4Ulq:N߱>yfq7?So(Y"i &6lPtj.I6/qVH`NEB@@@2 Ш$O?Eʪ#}-7 kgH1gD qE;Q]b+&l7=}v(?nwxWE=Yo#?}v,^p䁇?u- zz,,}׽v_ uGO]Y;bYtHXֿB3a*MA_i3F`W`]#Zf։9}m  vڹc|2|9uv{u];.<2zu/ z%W]{5Zy8?/?eBmoX<̤23*䷳}v[eΝL[rnG#|/ ]Wby縊cM/kyM@?]8|),7kG5tUW|>Ͽ]W<߯rӷO>{;M͞ gc^t:cЀA(gn.]|03p`9wپg>}\Ӻ=xylt\g? 7jK/]>2&קPE5z }]9~Pw[#VbAND@@@ ]Ũ2jԗU6hmNeL{jL@p>Z+s;őGG?C f 1|_ɮw@@@*@JIqDNÒ+v풝[Mmj]Pm7/ԥ*M~AyHyO5}eҾqlQ 6׳ʲfzɬXvnZ2YU}۳o2ǒҲ͂!UKF͆!J]ZH.c^):U;ǘ$eɒ%| fifjժԮ];jG\0Ҭ0w]-Gyo6tA'ul;\vjNY /^D4Qϼ5o42$+W%S[uVֽFx#fetE+˖,3-jԸ4mT:v(ŝuOYlc~ݜ9s ڵ 8 .鈣 :|"u:|3ӠA=j y<ӦMd?dނRY~x^@@@<~deeYB2M_@;#/Y3Uމrn/;Դ Rle&xYIjZA z~߈u ]f:W9&puWf7uZ}%c9ofy{ҠQCuDK"l[ذH5} &}3ӱXR?st.m_pz;WGZT߶6tϾf}e`l^eyF@@@" 0B"?8]GloFjF d R  /A/RoCOc(mN/ռY|<+Su?PzzN[H:2|y:۸^N{@@@#4hO@Gly𑰑NyO^xwKӔSߍz.H^TzPWv@@@@85FJ!t҈s D.}Y"_0C+$   T:ШtFÎ8L~q4NvATWR^=Yw;9\@@@@p4p R@;Nz-3gWVMi޼Y@ !Ar6   MFe{/X}@@@@@bFxN@@@@@J-Jy@@aaaR d{yq @@@\Fs@F Tgxp/"-Mc_0?_R̫0?OR@$wwo2&pW֧h\s':'ה3#3tۺ^W5 vmŔ}Bs^ɾ5[m6XcjJI'JڠA.V߂}@@@Qt3B^fqHg=!@i~sC^;MyDNz//NvWvuk/Xk9o:M'~Qsڶ:w:}SWuv__p<& N2ZVMP Ng1Իe•?y* '$֊   I'F:"6$;7gE~ϟ:M >@dƢokGmG@awrk"}*Nx [Y>cɺ]ǒ Tz   [а@`ƮߗQ}ﶚ@^ZN#qZT   GR=Ҏ!EZ y ӟ5xW@;udFNykwJ"G#vh$   x@ 5y(A |VhB h0CH m{~+p6o7֕@Afl>vev *F@@@rJO|wDd.½]A@53t)FfT'F[yݺJiB0%E SS^ii"f@u[m[eRw;L~rEYbwk=v9s} |s,Ekk=Noթus1W{s~Z,IYKT.5vK1/   A !TC<lkkp Б[%kI3 kwkG;ͭ~mu֛}7vǼ}^kf**}ڬ#!   o\k@n  PmvYP4_][C/i?X og,fv u{W}`u+`he2;   R`N(c;Q`\̠\; Aovy+f n}gա1 hYEw,s WHFZ.wsG@@@ Zפ}ݗ_i@Ƕn k"lH 5 xYj j؁ ]~B;ێHFZο=9׍d?Q׉-A@@@ Rפ}ڇֹ]T|[& IcEL@#]_J@|=WGTB?krZOYD\@@@Hvפ}ξ|2_NfͶ[wBY]>7U@_~@@@]@赯^k=JC 47Iu, A }"h     @ h0C5ikw:Jx)fʊKG.((^\OUES䐖"-Px<D@@@@@@tp]3CGftjR w_/KGh3.كB6g4ʗ ҼbA;@@@@@4:2c4t=JCg]T }( ]ذoȔVT9keV2/Ri>(     fY553itD2^ f͔ 24SΠA wd     1 |-쀅3 t28f;8a.t_|ͳ};  7y\o @@@ο)4ذ5^y7$#4赃/羖3$@@Kj:]]m1WG@@*Pk pr^KOTCV T856i @@!`eǻʮߗ=Zj)i=M+=~= mo@@@*3wo4jJȔS7 ^8Ga8a@@4M ݵKpK@Rj֐6MpHoGZ_qY*%@@@ nο V̏\Q4{p9첼# ͕]&L;{u"+WG֨5Fq5 Hoz舌R   @i g]!a\v#=TpYm@@p4v)۷o̓o9tkc6;БިkD]~Ɏك@@@TԿ<H3  hȮ_K'/E!N5JGrd[jyog   I~  @t$==zz+8ٺU-;H 23;ED@@D4*V@@d hh0###C$vywiyn(+!8  T 1s  @|쀆24QjUZly֫%GwtR   PqhTgG@@ 8Gih@J*EA dӥHaFz\ڔGkqpqJ@@@* h8  P>A QZ5اlP_XX]nꆮ$ @^C? q{ͩ!@ɣGR,,,\N Wmt:&|zw٩ Ql @ ;o=1 @ tCNʝ?W/?{Y4:U!IK  @ @`A-c%@TIXFI~Q?}[bq̭ Ko5e1{ϯnw“ Ql @ sTh윹 @Mȥ2daqq37n}Ͻ5*O?{|WLᾨga cˣ13]J @@cL!@l@ 5Foqycų,%?r v߶/&v?O^h]tAvPC @N@ @V/{wcIJ<c;yrgbǮȧyۙ+yɪ5vݝ @.0j @(UTgvX#GbᬷHcjD4h47N>>P<\FjjSNsϊ=1y1޽T;"@ @AԠΜq @j.FiGEkБh5B9e٩QѮ1_:* ѺhTpƺ @J@1Pe @(Fi>_n"F[@9G>vlsKaGgcr]1ubheSuݗb7v{km @ 0;#'@ @ (2({Y=3r|eU 6:l|2Z?ILb֣ 0?>hNTkqD @h ܔ0 @`rNd3gFVP@#Tw[׋ixwgj*޺ @ @Z 4j==G>Ld%\(z`#Ë<χ|8Z7\w{./~&3{Fo @ @@!@loN>eeFw˹Yݑ{i^*5Jȑߍ*ظ=F9{3Ѻ 1yy%ʽk @ @:Ί1 @@m$H*sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*iРj@IDATx|g]z)" ]QPbADbkk^{oT{ÆzXDzlγa63f7g̜9swV{<.4!p*w*ꚁ{M8     zx9p     m      P"@7@@@@@t@@@@@ @;      E     @@@@@@A"@@@@@      @B     |@@@@@pp(KBٽ{}gggIFF19ss%o[dgg˶RFM9ҬiIHAA5nбB@@@@@,Kq {Ͽvly 徻otkvyԓy<JcN yK=#]:8@@@@@PMxY&M~W{xNB[M~I@@@@?{&=Dx(ya +Үmkc"    @jyί>%Az8 <'~=E@@@@ WTΟwt%.    lذA͛ɩQ9G}`z,cu\oڴ x;t괏k]"    @t4n׮ucF0Zk굵aY9Äjw9Wkr WTe6    )-֭[}\slڴIJ1=z\#?ΐwޛVV5#     ++˯N.2*(]6?_|mO_eߋi_D'@*(!   $S޾}{ٰ!xPZWᅡbWssSš5WU?T?P:w(G~yy;/q=G&t8ebYjo;oӡ##F#-{3ݻ2NСCNn)Y֘'|o~t+}aN<8iШkc<ǞtV*ymnXqqL껐C2:_|B*w=F4d[ݗ}@@@@_ MKN}9A"-g ):Kywj9!Oyק8_ft=v27+ =B_f< 깞s˭ʬ?*('zY- ;@@@@@ @W댗v^pt7 ڵo# .n%ZlrƩkCا+vlToϓ_S^|{5*svvNVXPZ{#Y{+V3/wk(x=Z8n;rߏڵƜϚX x%ٴiԩ[[23E=     @='}>\S<< %:z~gkS̺i+_~Mz~XbߐQ.]noapޱc2_:y^/ B w#?ڿ    $@BOb>kG47+e]nyT~IrGI9e ϵQ ϩ8.ڴv m\vN!    @ $EުUs醫"Fѣ[s!r.yN'q!ru;P?"j̧cÆx޽h\u@S@@@@RK )t}dC:YnS9BLDOԓ'qy߱w!#.']Hc.5uU߿o=%S+/29xFF}i۶M11w[ay0 "    @R$MOɔ/^ZөS<:^5< Y=;ő:'h5mDv(c:j2Yb*Y.Wv^Mޭ[>[6t`xI}=*"    ĿNVr     @YqU[o:vY9@@@@@ ^fl-{ݼ7h@D O@@@@@b'`}W|W?YY܏]oJ[yn֏[;ͥ2oB@@@@RI@Gۚ-fɕ4@7CqkX7Z@=_fi @@@@H5kk }.,@zcṮ [dEҭ]Ŋ^v8@@@@@ fk uyFFo_f-ײ c+9\khx e,[)!eOfA@@@@H4#mTS^rP|٧nnޅ5D7byviֱr \kp^PP 'U_^ܮEne@@@@HMyehM癙0]GkͯCe:}9_ȟkKF&[[,9:'ͮݻdz jxCI??/+QzdZ     @\OBx(C :?=MZA@@@HF uF'W{' ?= }A@@@ usޘ+    $@PY=2W@@@@HH e, {Y1W@@@@HL ^#    $z!6R=Sr#}'OƧ=!  $@F2-fy|7hBiٲ2I'g|*ޢ"(~)S&O`|9giݦuTAc#ʑ*   ^=qwNDZ[M$#HdkȺm"o.Ǫb׾<#s\ۯD9odfVoMH^z%KHvO?ΐw~WVZ寗#>ԭ[_V/I'|VZr߃Hڵ9رC^xE?ewn[ +kmlxq   DC :iN4zB"3OC,cB5J>w/tG~],69w"#xd@|zv]zN#@wKk6'~l1'N^ގ.o߾U3~Wʪ+-5nD:u׍ktgžA`kd_ʕc})oVȶ+.d|@@@@ =Z$]֠#=x#[YS<Ҫ^$Wt?8:(:xcT[GG5kj+KoaaP҃"-x۩C>1se)2dcNU}} }¹>?sJu~_wŊr6@@@*{RU18 'e^ ZyfVCC\ROa`4'ؾ} uדz\rrrV͚nֿ:Stssmxs׿6\ya1gp4!זk\)rQ"~܆d|D=eѺ,V6ʰ^Aacѿ/x֚l^7ޙ-;gOiߡ}"t>X)2ڢs玒_>?3$++;?'tn'$_|jhל9E3/7 :oS9Bʕ/?kpvnVj??sPye+!Ghw#/>-46Ӧ>F)ONo<R_r~Xs忮if=܎o]Ə(<|~}_"_Hto?9娣JG#s^KFK/k-f@@@ X Eq(жfou^VK.q)Srs9nonwi.fy̺~gun=d>k[8#z>WG[y߼Nj:mZg5rkB:y,'ٚ?~t5(<ң<&BDUNM>x(vB5^tKa׆"@Xdvm|r[o;`u \8v;NL>4cn"Jȱa @@@R^=ɿm˶=讙ƵK11fV_%]v JH˺{7(6rJRG`QC)3̔{,C9CW2ߘ|Io35[zh_vS|Acq&ұs'aLo޻{2hÏ8LޞA̟tNE 6m(ζwȣ ٶS59_Ѵvr߽GwMw2{ku/]pcx#XfM㇟Afg^0Dwj'ZeϜUfS78v?oN}뽄G` @@@\Al;Wڸ3Ә+Y;P与2 ^E?*>ʶd4N!?l]~=9~a #4&H5#W̘{nAu(@@@@Ks [K{0ޮg-J^ukc/kgv0j]Pf}*$nJruquulFA۶n *E4nw}fee65R-'ym[>3iߩhGe-ӧTe1/,ZP.qru{Y|t-vZb @@@*"@^8w:HR򉝋hX[뿣.IVMly%{ 3,[L!Eu 6w뎝;KwcDuN%Zhh6}/W scґSrm.nXOwZnۮ>WLhScu=ƋsUC6^hri`Vq[Ѻi3Uև<P֒UV۶lIC-iT     Ɍb꒩=>c@?M052L1*8y4n[Ɖiפ$&dm[4gY`1z[c'7vLw2FF2bӏ> .n{y7e򛺲-{mkۏŎssωťl}}=찦n8YSm>teE^jżO_bu,uEvie4*֘tqp6{zn#խ簍   @YC: #mW|97xZȠ'#[2kU_⫑09:a|Qfw>gYzSn" Ϋl6mVټ)yms|-bޚLhXzUboE_h.:GeV꺽C|]|؎;M㇇3O=SN<$Jo$iWtu)Y>_@X4|ϞX+7g:?9|1k~jn9<~kn9_   0=:%=Kd־dLY#1^u=Zf ;eaLj%ISl>꘣<WMm;o-uד,[7oΖ|+h.񯎓\q04w#=C5j$۶m jK;6 P/iutY(jͥ^zr%#d}GwkC!grt٦u=FȷcO), >EOMyYv =l9: ˈF/ѿ6dhRkZctg~毧N&/=_z5kvqRvma6kGK5e1d_y' _uE/uۧY$#/T} }ЗRΟO4/K,}/]zρ'AKEA QA^/AS Y_/yQ{ߨq#gY2/K/4+/tu    zPZͣdו>͕06d{G ޳Elh'giٲo5gxf4}DGw3Kg . 2ȗ /::;TZ.?L~e`ʤ_aF~훫>^C?梡0b]=UB#g=DŋEυl[r/U|+.׋{ЫwOߏU:RMnskeQW}'wʊ+֛n3xy$##ʓr@@@ ,_[ԎSjwmSIAaxß<1ZX ѺT});/Wt^n>s)%+oP::9X8}'/菱B޼yc&8Lymvwwm.;wmݶ_!wG?HY8:/ γUQɑ.[P26G^(guF`q}qCP/w?@[}(y#x rI%zV-+GE{N.q 79wȹW^2``É    $~f<2f]\(RU[d"XOlyr0|?E9t*ہ2v;xI|ӫ8UW]}{/.z!֢;Knf91٪SFh`a?(~K!ڈ":z6r#wSa p'8S[ (ZMb:GǘY[9w#yl#H۱(7x_}7#Tֽ{)ekxYuQ!CuuO=)萎\q~oB-jߍ S&Jc}￵hlxi-/N׿l,\8BNM2"/=hЏOfiiuc)p:1sx}nF@@'//7͇9?f-U?϶+.. XJAAڽKv-?m;3ϳ۞4\޾js?!y duRl bآt߻tl%vɊMeͪXvm)>!Oˮ].Rg#=d6&\SC2k5 Q fY5?d_CvƯ60KG(Q*q$pգUc<#Ug:BXO2.:GM,oMyKH"_69y+㚕} ܬYS'kGI*kK}E,@'סm@@@T)=_ 8<-3΍М%b9= ut_~-ѫ|QkixYivuru   #SWt1>UU+_>x)eꔩ·{Zdž)D@@@HXHGG@˗/E ]    )@ϕBÎ8̡4q&_|UJ@@@@M? 3Íwޔ7Fڵyf!sD(..y;y䡮E9   *@O~#@D 6 l[?zyy[=+rS}nǪ]5F@@H.z  @ ~6wx%Rl|=Fw~q}ЗOkc_מ4=f22~Ji+fi}=_oѵ_n@@@* & ν^)XF/L<7smSu۬ktۜ$\VpXEw̗n{|} =F? #nZQSf7@@@ @; @ -JoH'1OAAP5keXYkk].8Qv_wd>@@@IoP q-` нWu_s<+k+>I@@@T n s8Ypq_֒s+`^cza{13R=4  $@&3@ 4៵}8 04DO~$8**__ jMc"   @@΁ޫMe- @ 0eٲkhl1^(kH1xaxyҥX{$(+6Ӵố"b+42_[Tl{%8wWf1u_g={>Fos)"Lrm\E@@D nD~^F #- |I 632$33Krrr| :tMMRd[}߱:fe:OCkfPp- m~Ih }? 5FxoSu&-ZP?,   8 mu;=8%4##PKg#u킂ںm;,p_G.u˪xuhLjcV7R?33S /V?Bt?   qUK"U2}f/у8EPP\may(%H3ܷmL墡y!s1ںρZױ! ֝sjϩ^`Y~Y8y@@@@@Uݕ     *@OF@@@@p @w      @ @@@@@\]y8     o@@@@@WtW"    z>y@@@@@Uݕ     *@OF@@@@p @w      @ @@@@@\]y8     o@@@@@WtW"    z>y@@@@@Uݕ     *@OF@@@@p @w      @ @@@@@\]y8     o@@@@@WtW"    z>y@@@@@Uݕ     *@OF@@@@p @w      @ @@@@@\]y8     o@@@@@WtW"    z>y@@@@@Uݕ     *@OF@@@@p @w      @ @@@@@\]y8     o@@@@@WtW"    z>y@@@@@Uݕ     *@OF@@@@p @w      @ @@@@@\]y8     o@@@@@WO2moIENDB`vitalik-django-ninja-0b67d47/docs/docs/img/operation_tags.png000066400000000000000000001363421515660254400242520ustar00rootroot00000000000000PNG  IHDR͂iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i* @IDATxT3ۗޛQ(T@P "* XPlO{ vET]l`D@AD./ ,[`ۗ3!333OC/s4˓;&OxMZ:~v      D` 1ZH)S~.?| \#?/\A"    @ _~UP#MKK'Xэ;]rs6ҬiD@@@@eQz}(,_AxсPv     )#Nx3@@@@)k.Y|y8Oo=z7wד=Γ%-[-;@@@@@ o֬k)cƌ ɼs{*a9K;$m'A /8S+mdDfHRW`<aԩ]K<ؾMc9({3=s?gT\{m;߸?v̍DQ@@@@>|s:#^_| O6͹401u,C#{ʳϽ*_~5çw&Tr| t'NX^=)d76UT{_ C\+^Os}ʢE9Ƭvr\!Wcv-Aǟ~-o=ARfuq~WyҪesM/GyH^{/?&ÆIBB'},ߛIʕ]UU     p p3BؤQy<랇 twʫc.p.[!7v6fZyƿ7Yf|7S}>p[1`w.m|m;䆡w37n^ׄI:?=/8_6}ΨU |3_K rslߣE @@@@| ;O1#[O` juʕo *oH\wm2߭!_ 5n :>;B# @@@@`5g&$%ܵ1cV5kML!_ʘx&xQc|l?E~@@@@bU xeM@S _s 7WnJڍx}JC]VX+gn}A >t    3ނ͛7]3pUи6m\?ʵmE_گrQ$99IygΜ-歹:;>Dn%5kp mW\+}&M۵=ε     %pzjܹ̝;Wjժk k[=,Ӭc^ ď7H5/jժ:fegkp;Žʶ}Mdu:Zyq~rόLz'Mljo]Y|uӶޤIcXRK._z[ƽ3Voc/OucE?f^Ҫes)K@@@@B*`g ‡JM'~7ɰ[sqT{W;k3emAx'11yN=[:aݡ/U]w _ߋ=9rug>T"    @`ij`453-V15#~ӆ~]۴i-^}6\f|7K/_鳍EvmsͶm7L_;˼qk;??_:vhcOqٻ_#@@@@{MXT ~4F~@KjUm*-N%KWu7s?;@@@@@ ܃#h>G؃Qj|+w]iݫ|nWX!3+V͓y84OZHI۶m+|l(fff@@@@@ h0{hѢEh ud#|pm^Unݲ[: ow=w@+mZd?s=+ݻ#Nh-UT6߯ \X $R!JS@@@@h w8M4y'rsdٲҪ1>4˗ƺj*MZinla~g.ͿnZﯲBTsc^kg    @\YĘL}'~\dk~K,MSTΖ,e3_*uFt>^k@@@@@ Rb*T/.k֮yl&&s:Vh׺ɧΧ_G_z;Xu;wy\ӣWXX(3g׎j~~-|?_#F#r]@@@@J.SH_Tp7ʟz.YB7D4M0%%5!^oݶC{Q۴4WKLLo~-> |^5jV{>&Zfks 7Wƾ[$]7X@@@@@ 1#^9f8Vhf-ҦMki(CV^+F8%55Y^voß2^z%H#ǟoQN"sm14M6_ t4fw?,I/`yVy c/LӾ]kWY#eSK+ʱRZILڷ@@@@@ 'gswZhླྀwՠWȔ?;~)>pG0͋l{MnCOcOƯ v7l#?3_Әߢ1Ev?E?e] ~rjyhS!>IngYA@@@@4mssTժUl(˥^(g~r(N'/? D`کVz:"l8"Š@@@@@ b2߸rn/i=C 8o~Zg*QZ+.)VE{^bx;ءEtNN =@@@@@@^x+.ߩACJnu⋺ɗMN-Lv QmӧW:    Ķ(MpWWf|7K֭[/۷eUԭWGN;STk\Yet7'mZ=x(;_?˦M[d4̒:jQM9?G4j ^9WI7k׬3L={0W{l2׈     Pfˌ#    ĂX\#     @ /3zN      c.s     e&@ 91     @,5"    2      @ >2׈     Pfˌ#    ĂX\#     @ /3zN      c.s     e&@ 91     @,5"    2      @ >2׈     Pfˌ#    ĂX\#     @ /3zN      c.s     e&@ 91     @,5"    2      @ >2׈     Pf ev"N>7*1/k5f^f^yyyy53Y"    Ėץtנ|BBs[Zu{֥֙Dž[+bzAx AI2oK,ߑ ;m MC     I Θ_H:yҩA]+o^5oօ{iɃu '77&>     Eg6˗~ҝAy%3AҘQx3΂ ~^ZPC]Z8F" $?.@@@@(@^Ȧ="ma*+[; GSԘijb&3൘K9g׬O9fo=     D4~I,U=Ax k CS\gk1h0^s›h—      @9Љ[֢f9kLflZY""sfUa&@@@@@زƘhLnƣDM4k ]     @qƜ4p2 ěfH]Y;ګ/f      P3Ƭ1g=ǣgDD y {p(Wل%      1f9[cwe/d! @@@@@((u{fXO,@@@@@(5lI@@|      M !O O$;)D n;DC\$8D/LXGKc    @90Ǘ J#*_#C_ eSzI{xP}OYP:A@@@@`*5 A`n=mN@7FA@@@@&h ͧ5 ߘQ@@@@@ p kNx _s@@@@@o-Ɯ@@@@ &/ @[ 1g@@@@. Gmj@@@@@E@|I@@@@@ "GmaP     "@ >Z$ׁ     #0(@@@@@h -w@@@@@Hy[     @;u     D- 1;/NJ40nZ$ %ӿ6sc.oYC޿Tn< AylٲyI-\ۺ21}6[n]9{cGTLxog޼y0w?ʧ}⳯K@|4~}v    E䈏Kрg8D@ob vHɡ CRJ'Tśyg?e1t ^|%W/ "JgzvӦM|zV@@@4{$&FxLNr{hkɞT̩>N5BQ")뉵>ϐi_4~垡ZR%%%E*WdnhE9RŘ1ޣWwsӵ?}\.+dc<3QGFz,3KNN10/ٮRdUNHǐm|̒<)6,@@@RD]1TMvE-=i$3=M4r*J* ҽm׹X)")w}XkdUFʚIFx IJ=O-̞[[[ ˃gOOl^Ӽ< 1yq\J _jBC3#~{^~$%%{‹zJ {9w)Nl'ly~bM~g/Hvgl   B@|(8{.ir{[䀾U6#m_LyY_^p-\B̕<_&8BO)o~k dsZF׾+HR^#lꚫlEmaa(+Wj{}{I}#E8ɑMD?,VRg_|Emt5w)yFzqoo[dHՏ>Q愄8sKoӗߗ!5j,wzP|   +PQ鎑@-#Fݪ:ީ% IRWG¡ٴRp3sȉMR\j^#v>An&iy'L׫RRe[]Q9F\srϛͯCr]Ͽg^/@]gxjz4k~rUjU-sss)yeÆ[q4nH CN?b][q:Y)a]5# h__Yᅭ-jRk6   @ _>Si_Ζ}I\[;@z|JK:Bl4n:%$ƴ)f RCDA h*)ڎgÿ[2i=56wcڃߓ&LYZftҽh~f{Dөx+?Y>]κe/+Q ~-ӏ3m_2v #{k.''9_ggoۂ5~k2tۺ\e}a큌u[6o6wϭz^y|$.c^{ 3{yQ'.%g}FHҞ{j,3^v2ϵV   @,Ӱˑ@Z:d$T᭗s*ʭgHJM#w3٭G e./Y1Y֣X&39ugY3 [{9gpk~f[麷 maw Tk.pغ֣3 2/=?V}== _z^_(͗O>~9>ύoЯ |} v_^F?B6nh~̇bWt@`7<1qi_le#"kT"   C@X>g ~CF+%9nJqc7퍗mגҨ{Q5 @g=5#0}8KLL&G)]:9ҡC{YiOboM %n`wN:y-u7zw/*Cy'c=[`}^Fu֣[@c^|HTTQ:AF ,Ohʀ*r˦-@|#(Ķ5ml\pa/W^rرVb*[`]w49aeTXQ.unm;#dC_ ?Q ?.}=֦@qhQ#rLjD:wL/_fq MK݌o{?m[➳kuF |… =NOzHߝ.{jժjRKS5fMEofY~zԳ_DxdviZ3/|udƍFڇ_b-Ƌҥkscy1qo0RmwG*@@@PIFI?kF{Z#o޾xC4oضص?_~_YT3IRIg(= G`{lӻ%\ҶJ~/?{K^]F5TX>c_G]8*t& m]m;؍^3))wS%-)GyKC%{ug>o$oN:UfΜd,kV^on\ƍ\7*{kM]    P-}a٪ҫU6w4וn*'4d%/58xF[ 7HZ.?6//O{YsӵlѪ5fxhBRRSDo{FWWn=-0?3wGhYԀ7Ke c=gkۃ}lkOrECU/޽/}zfUFZ`JF 3oO]m+EvyOt F>@{ :sӹ>נz{} LG>s}lCAU+/t/}a r9gȸ9mt&!z41Z,}h\S< .qwo羭ЏY4FŁ䣏M|.W5ft[i˯+ b횵v><󿱡=qe5 xG:w>_<Ӯ ץ!7 u[*?h!6m@@@ 4{RRO+ȈwHn^`еճ=_RK/l:Ӿrt'o/͏iԀ4]1f ƻw-/.v}Qk|YgMNj˽)5rvof/9+ݶewh0'y.͛>`5:KeowlA{~urWև$P|}<v45ޗpCWv/ z{\r%_,(Hߨq#֡ywe^w\jWCҽ>"   @b]bLY߫ߺ'OnY~XO-{4)]keg~$W]s8EmG]c ic5 M}3ME֢SNlX䱑r]ΑfL[M? >SCxDNtV{_S+e@Nvck|`K/rmr嗺w[!4>~1i3>HҬr.5(cs/6c{ƎO0'm~HbZԿo?OGko/إ3o&?aWQ#nLpt=>&1[ z;"x n<<M)a}ayΗ^~!E\ź냠L5rgAw^aeMh"@IDAT,C'~"Ԗ4l9nРSs_11V˓΢w< y@@@̈>ΐ/4~PPph|Ĕ@8gG6ǟd1v7߸f5  &'I'ISN3@@@@3-FΐC= g.o\H?Ͼ,t7^;@@@@ u BP lܸ1֬^p["   Ėغ\-!pԺnzr\h 4B@@@H^A!@$f?#ٹsTRY8@@@@@@<@@Z5E?@@@@+@jq     &     W@|q8@@@@@D@@@@@+5Gq 8o--"    5zո P2@@@@& whMkA r[{@@@@"S j=Z:aDfTD@@@@@^S~i@p׿1     '\n]C; em{D #{̌HjNxMGLHS @@@@ "*'GgjGHfgl     e!1hEf)ݳq.@@@@@"@ b' @@@@@ gkL:C,@|i^l1@@@@@| F[bq.Kom:      18#lAC[FD s]ڕ]ܦ=%Hz@@@@@M3Ƭ1g=ǣKCLE<48     @4 1f9gsi^ni za өAs e]%     -e1kјƞY[Gx3.fĿ5@@@@@ h^cZ4֬1g=k >": Sݻ:?/-!o;K Ha5     @Y5'1gW@n[off1'[(O^^x OZV]~ZC=_G@@@@I@gk k ^gě͙񥑢&"zcYR7ӓdޖTY#Av)(yuZ@@@@@/gsv%}17 x 3K3ik0^`Os@@@@@0gRf|w+y\"&j̀nk6Zuf13Y"    Ć5n|wțy3@2-QxX3nu vn 6@@@@@ 64n3K3nVKD\ ^/n[&AxS%     ` ws]f;`#֡Yz      *` wҖ1l#    Ď5njk`Z_"oa@@@@@ v"!nOnH,f@@@@@N@@@@@ZQ{k0@@@@@H  w1     D\     @$@@@@@V@|Z. @@@@@ G]`      Q+@ >jo-      #.0@@@@@  C@@@@p     @ [˅!    DH @@@@@ jG@@@@@"A@|$ƀ     ra      @ >c@@@@@ZQ{k0@@@@@H  w1     D\     @$@@@@@V@|Z. @@@@@ G]`      Q+@ >jo-      #.0@@@@@  C@@@@p     @ [˅!    DH @@@@@ jG@@@@@"A@|$ƀ     ra      @ >c@@@@@ZQ{k0@@@@@H  w1     D@:đ Dq8:s~       ]cF dCOȎ~I?+$//YgwE-      hO~~$v y6ko}&Hz wgd@@@@@#~( \9dd?toJc$))IrrKU>:T0d~9+^sk      *P@bh0 ;$~%Y_Kh     PJ:vMW#98KJUkxl:NIkvѠ"AIrs^I6 i!      @hyQs2yyycʒLڱC % -VJb~Gu-6FW q?y=Q ΗGu      h`U5kJ%S{k䃏[AR.e+%uFqFY0{E;upg̊wmq_|}BA@@@@@: 3O5ۉF7U ;hsaϔO^ĥJ{;ӡ]=!     P% k\fNxg>99ٙFgW7*HAr'oIݾS,܅%٨      m%+)j 3?y]j9s>覒غ$8J> ׃    1&k.O-ʗ/_.jr~dQ|՜xii4MM\OMM ,+JJrRJR봍7@@@@5 7kLZl)cƌ)su :JhJ4#: [:Y֏yc^@@@@@ 4o>q.#G,aÆK/;$m'AھO_*W(tGfٵ+ysW8 }ԩi]VV,\aE֯(cmLT^m_s-[-;3O@@@@ >y/pM?sE:(@P̀t_?Ulڴپcs˸w&HU#tzsz[98+>[[so\X6>| }f~z#}e/jsP&NX^= Z]:Z~2?fm8;1> o3I2v/4Hg >x(ɧ_ˋ/!{Kk6~% Á4ڦt2Zf ~]A {hs~ϧ}arϽ5 W:EEAA@@@@4B'_w9b2?iAͪNg`Ͼl p+S 0|6ӗ~^O󶇳?Yhq?9m@@@@ x 7o\vemw]1/SXwZzEEto_~"Zw\+i{|kiҤlٶC\/q\ڧ:QZgu_J*(-WߋWZl!IRR%33Kgh3ϔmeoO(`=n&>r^3|g    `WΝ;ܹsVZ~OAxmǘEϛ}u,+s>sCYʽ{>O?ql͛5&MKNV{l3MvZ<\RVIVv})Uo$/F@,C\+//՗*n))fR^m;'5kTsNR_g![KM7RY?z_}@%  wU]O*JW)Rł&HUذ|"v(* XAQAPl6DDTR,fo ܄>׳g@@8N0 |E Ġt/Kn.%K& ?}RFuIH5P3v|ݭ{w٣MRr]7Irra6MmY,Z,/n.7ӧ==+Es+:*~ Rb9ֵƞRRykDw㵦`)6nj{[Ҁ[N[d'{@@@@N0 ;Ğޜ8Jb@jRi>uN!-[63|]]ڧ>XvyH[16P~] {uo͔E.ϟw}[ C. ^w3w~:]!>?xd9b/c2+-F=|4kX5~:Ax4T"   @(xp#y<_Ay#v{}{ 6lG9D L{~;+?ztxD.#p Z*RƤ VW(+ŊNf?m[>tmJ&Ve„E?Z>}VC9Q@uFvg;    'E X0^O'=h k`s VN-R,8NG-4k~AAxmn]=utwV57lrWX%-Z_Z௿6WS/!A*T(/֭~ҨQC6-m|#    pdk!    ph5o}T 1?rr[mQB|YRj%=5=1ñ!==#[$'ֻye ޛi>1X6R@@@@$`miUד@6!n(|Znϟ(w~Ld\ I.C@>`ٶij@@@@`k} ?a;*Ɏ]Cs-/%%pOV s͈`eGO DƎtƺ&hHjj$$1:p8ݵ?>D*zTSOӵK{i텶[XЇ0Q|95,Yp@@@@@oT֧zXٱ%f%7 x.Z*3f|pn8׌ΉRr@)_Kݤz6l?S;\ۣO(O>~_[7rOKumpnYn݋;@(AnޛYG@@@@-=NbLZn;{(ofKͮlѼ)S^ w2;3ԕd}6+=c7n"w]壏? :~~S~4V ;G^z}>$.SFF ڋ|#    Y 4FQmCJifjrm7.޳' wuF@@@@@-'+ڵw#eGIcS8a^RyINCϗ8Cz״ryʍ}˹@t    Q%'z;otʕ+FHs[ȃdG.k2۷)ޗ&HvQKOJbbqCvv.?m*;m/$$lN~=D@@@@l ^ L^{IjUBW3-uJ4aJ6)d[̆WGYk|ru?sɗ/_ЮZG F^}YP!;@1ˣOjY?66{p+ ƫS/ =xQF*e˔ʪ9@@@@@ъɏ?͑-;vɮݻ%@(^L4[iҴyRNM3##,^R6SVZ-7ozΥMX`㹎4Yr,_Rҥe/_%KI^jJٸi۰Q6,6nt)cʗ-c}3իU"`    x`@@@@@ 4ᥤ7@@@@@|P     @ć@@@@@ kB      a 6J:B@@@@@W@ 5     M@|(@@@@@_&      6a#@@@@@|P     @ć@@@@@ kB      a 6J:B@@@@@W@ 5     M@|(@@@@@_&      6a#@@@@@|P     @ć@@@@@ kB      a 6J:B@@@@@W@ 5     M@|(@@@@@_&      6a#@@@@@|P     @ć@@@@@ kB      a 6J:B@@@@@W@ 5     M >l= st     ڶnqR.'"    䕋:@@@@@mF8C@@@@Sb@@@@@r[ b'k A&@2#    @LLLDA@d@@@@@N@llfwL9=Ytwן[Q@@@@@"Qxw}v^o{ن|#    -w]\v)qx;Юv;u2xU     yOAv֏nuwҊ@\wӝ .yw/8     @dh.{\\OV0>b&kv^ ~φ@@@@@ o x5Zg:{֊@^w^v~MEϾunI?6     p J|RPiZ_ ۗu9iɃe '55 ď|@@@@@(h[MifOHH:J^GG1*>v:Ax豼1ǒmF@@@@@ T;Ƭ1gw :s+~8@@@@@ r#F}-s_{;     ;IH1PN6     jtDxm9˶%6I/~eXTB+QS:>7/Sp    Q"`牏˽I#*qӡ2tYˉv `A>GnUɟ     dC RƝ)`Q@@@@@ {Qt4ͧ51]     @Q״y~rޘ#    D@ubV k9o@@@@K j:$r^ߵ7    %5-\      @;u     D-     @;u     D-     @;u     D-     @;u     D-d%0˙rS!oKjjjVnF %z#> .a< ~F@@@@|'<K-HpkdwܛݢI`-2KZdTT^:tc'/ iB}S^ό?>\hqV=RbXAg@ZZ]zYV\# ,Gʣz#   #l/v_!Y,ٳA޻6h[{cbLiI"xBK6H{eu)?[Xw*- $9MӐ#&K\;Mfo[GJͤF>V8"jsڝG8}t΂i?YAx{˾E@@@@ *gڔ< =Rc[wWL.ؼiZi@l>m z|ŬObu奕ˍ%k};I { k}R25N1veKzv4O >j~ilզOP|ߞ}RhX.~ #˖K'YxețOa!ѢUf빹ifYhܾ[,&˄Tn^K$KveVk,$kTJK||?}Ȩ%66FbbȆ ?  qPMR\iSm%#-cpD\sUT2}<.s~c4|JҪMwn%/=u:m7_#zv4c`okce7dϞ~Y׬&\v\JQ{꒞VWw\ٱM8@@@_%CWN,s |c#)TzB߿K4']),^=K))蔾ykϫrm^ʍ)?}K {ҫsC eOY\hRu-fB)zB:kCG>/ʑs)$+)w6(:]<󬤛}WTR Ȗ;>.iR"TyG&'|Blf+jKylוIw|H;SGEdLG9gH"N,^|i+-Q$5$.xk4Uflbb,~t3:~Mҷ 9CYE ].X5gy5]RnW&Miپuo?fPl?X=8S0ium4iX۹Μ\Xf*ky~aZ2sBg8qn_>O;Cۈ8r$U&~pA}:ً!}˾ IN8)k7r*D?,Ksp`kΗ;.;pra)P w8Ci/w\{:ޤ?S{˦&7p:S_r-WJ &"}N)T@-6SaF[q=]𝺵wN. 歚Ƚ.IRdq]y{@1vv3]/ z />us"C/o!=1ڶz9}чZ@@@ sD1q1_43 q OʁCfyfЭTdL, i>8(IDAT=YV,E $ƙ.w'nn}7.|Xs4HĤBp,q8M-%k4#3sW4L|?ڙ-f?d~ڣ&OM61^J;H{SLkwϳWK?yVZ܏+ %U.3XX^'~Z)/.~qC =Eן&|4*Yi ,=6ݦ/C]߻I1# ^rB7p=t]5 >+̓|N{lzёPƽ9*[k_~o?6ѣ&h?7`];g[/t1n?gwo@?}FMϋд0߳P&ctϿ>/{/Wծ{+\4Es(}`Uuzuߨ,wy(֟ 67{sw~gFXAǰ7q<{k/yi`jQֽƾσ mӪM og-];v !M@.C Cߖ{t4vy+&ES-JuH8mCYxC!g5pL`؛pS%o@n }їʲ+< a=*VQ^>:^w}W/ݷ>,o4Gۿ '>::~_w}Qv>'n@(eO4KKKuL~_;I= qSV1~ 6l?ⳟ>;{ {Yw<5ݤp2}ˡCXvч@ \~(سo#}[n_Nz]}c7 \۷7Lr`ZFr?hT_1_7#g}{x 7bAʚUk[OH}L@@@-@ d߁|x]*%Ε&)ۺpkb۬NM/PfId%7,4T79?`9ӽ|S+0|&reIhtujZ`5A92hK>i,4I Yy9&u<ֽW4@Wt4rR%|.=>TN7K)ljBi~ݼh 4>?sQ(: wg}9L)m/3]>Xyihn/H{ggurR|7{~~&N}]|3[g{b|r( zqQfR V E)U/*T Ϩc׾2{u MܿhcNSxuz 甞~EjLdfζŸ7Cϼ, ^kbVeޔx,勾t=޴r՗JB~L:VcF}$ 'I E\58Mׯͼ7NYA3Z~ kʤktJʛ@jy#}r8 }wL[l,}#  -@ >#x IYM3o-E]{{ǵw؋A鳽J2[Hl\2eҁR<v *TT#'}˧o;j4Dv-C!>)f̖BIrgz#{.܁xpG].kN]Xx &7@z}=\ '=Xtܗ>)TzK;=A y[xNnZ: .:[}]cMrɋ׾8OJC~{W']Li[l<˲|(zLNy8o3..qkl-/3_|@㇙?VK  ;OG8} nf7ݢ4<))M6䓷ˎmGc͛?ע:{ӥo[iV.m=o=iFޝ/ ֬ j8c+3;G;x< UUyjŤN 駴h j-?>ÚeDg7nӅ&pϟi4]54S( 79}ѩ aI$҇@8՚~o(sNz#uic6AY> |ra@@4@QZ+3.43G'\pvxo"V&#tr\_RP),wAB:=߆#{cé){=NSK^+)ŋZ]sm6H;*[vFz[ eᵍw>٥. 3u@WΪ>& 6(W<ҧ˭Akv>7phy,Y12]w >C$״o9YL.Dlll5)/K3;#o{]F{q'_p\eʗ{n}zuTiK=s6VJ;Hda/?=Nb[|TRA-\i_Ŗ͙o-W:Pf$!ƇD;Y6AxmT}49ASg_G{p x'Axo\@@@ G퉌uH-z,`Gf + mdcՂA?wd楍/_R3Ϳ>L ]uzrYI[o_GS]wh=iluېLG~#N%P'G ɣY >hզO ~ٲ̟qNr`峉xY?@^jjG=-kEѽj@uYӀۼzU޻t0 1PҳvϷTݯާm._hSJ}K rm#n 孬Ӆ g T,csJWd+̓7U7f#+;ݗ,]Rr;B@١i^aGD:|ӆ-&}͏V ?vJ통k3ϽO(V,]oJgw}5?fdՊм>۵fger3 @@ȦlE[s :9&̚}[d̿dOMw-#ihۥj]V$f$S%qxp~+,W?W:Wm擾RbC3*:tB4JN\nMw3˱T zmGU 瘔1\ɡ_{i<=OAn!+5rTٽ{{{߾rJ&j N׬X'=kf>e7=cOIsMrm@V{ `/guMvnᵾNhJU'}5 WYMz]5n zvOQbZ7 >F(:"]^zcʧU]ۅLhs:Y-65R~>9es *@@@')堀 '+/dMJ g܂f@w+ɰ}%kwtr~Q+Lr{ :#@ ʗ*UJZ{ H=+63qNV.]^ K)Ub֧ Mq=O{Lɸ)ntv}pW|/v:r7Pf[eDsc>HE(\wY- 4zXBӾUwfjmtF{>p7y0Xtz`yNɟ|#9V&|0I>l=pBync2V}G^w'Ǿ{^nB5YӜM:lC4].^a/|tydKm<'^AxtUNP+(`s 5}O^>xczٟg\5-C =z^. `}IQ  D@ 티 t+9u\P2,{P$҉R=I'YMh+S&Y':A)ʝg-x}iظ{޿Y4M夒rViͪ)|q [5$-9_uS5s3;g[wHf\`tkW4KݱRkT?ȷ_ϒwڧ'K-su?gԥ$טo\}8zV\sU [ޫzGj=>]o;5Z--Sfx஻̜Lru:r]F q25v\f {^uruA@ϧzjݏ${^%ֶw|49b6iOZ_RJ{k`2;Q%-.nbUC1ƋN*yg"ܯWf}Hߌ?{Z>5 =[O7&%8t_.n/?;}[ \2hq|1Cy}ҟ;9ssAN:?Su ǽ?Izn/]!+ \+{'+q 9Z%ϓrtXBai[ s-++e'_yyl֠;2G3#4l䙇ڻhDHHo ^{' nf-n@=>U(" ӌʣÇ?^ޫ{A^OL'J͹ndм:Y7G/QPE?Yz OwL6Nx'M46N-Zew^|y˲J*qia/|⩫y(OaБzOcۗ}#m.o%5jUœeMD٥ϯ;Z ^"[Ǟ *з1o}إS7ר⤦9bx[O)T_Nr…36}RI)l4󹣷GCO#gzռ S8AxM{r}e]Yv*0TQI22dyhE/S]}8Ӯcko7nSgIr"RLVzd9k! \`@@Hy["4EL|r}p6X03oVgc&>1&W_HKJ%Yuaoʮ$^2/m"O`S=9'HVg91y!>{{fT4SZK3+@ZNإSǕ&F }s><Z |+]w2׸gg w*'{H~lhw9FR'Pb \@_ѡ4oJW[DT9rgIh٦OGc}ַ?ZS>J~ͤery.ԐGDPլ]i#_9WzbVzا4p}0o'~<9Ptto '~z?7cF~tW ?~8sp<_Sk^?jk?@,W߷gr Ų@@8'>[9Ě\/]~Z-DҲ(UV.*W|8M zgР||r3]fa_rٔdeW(_>93siН٘k?Μq&e񔖗4o񷿎V{ɤcEpy/hzgyȀ3iCլ (8hYttwѴ$n5w 9rg= ^y\yV06;OL|SnZ8:]S}z*T*jWVyמ 8jz֌_3[u[_Rqݫ j˨Nϵ>X2 ljou#\n᫚78=عFwD d@@@T1:C RSSQju׬|: 鬺:$vy&qIc=%Py>F'zūH픊R` rp,ڱFٱJ\/ر$H ةJ#VU¥Z2RP)9*+nMqM0)nܣikOE4=whR4m؟ gPp (xw6@@@@ wwɭ@Iz=I_c&ތ3yj{?U`_ţ6c_-:I'Sd;ݍߎD@@@:JN B5BvXdUmi    "@64 -K鲥^ӳ3M@@@@iZ@ [4o,xWopBE Ieng    @("     p9^9C@@@@@ ! @@@@@ r     @C@      +5㽗@+@@@@ &z])D.w-r g    Q?D2~עr9    9.5ϕjK8@ / Q@@@@@ t %U=-Ȗw    ^n]&<[Lx-sw$RKtw@@@@@Y1k04@u+'e%[0\&]     E;Ƭ18{GI {_۟*X?{Ǣp     Q(`ǘ5lǟoru='I Ļ/̾p}"9ymmq,ۿݔe@@@@@زƘhYcO."v2|֋ZHے sl x]c@@@@@ 5EcsسƠ1頝icQSqwa}E?Sݫ({_TI*)1q}Usk:{$U$!!x;3=8<%"*yY kP~#    D k ^Gۣ񹑢&"z_Q5 o/>I~ؿHٷN6-G3ǁKA@@@@8QX)/YtbV oGf^)zBu;ooumV     @G@;W${@^TAw{k^@@@@@ ovw*/"*k໮ہw{NAy]       tum˹Y".ƻ݁x -7     7x~mr;o nKkVܧ#9@@@@@(w=w}n^DFxwa@@@@@ >xiu_JIENDB`vitalik-django-ninja-0b67d47/docs/docs/img/servers.png000066400000000000000000000616211515660254400227220ustar00rootroot00000000000000PNG  IHDRRe1qPLTE;AQBDNI̐CDNAEN@DN:AQBDO;API̒JˑG̐K̐;@RH͐K˒CDOACMG͒@DOUZhpuDJZ;@P{НKQ_JˏafsQUbZ_mhmzy{fҞ٭OΔデHˏXϘܴ߹vר>==bFօaIDATxAN$1 8ʶ6#1?*qšWK*=X#Og~^b9w7*#8sƟ}UzsyW/bލs9]|W[aoAv8sȟ2=iwsl#*~}FBsλJ!sjsp9缓q}ͲY9sşunwZgp9缋k_Şfy~^ 9w2?Op9缋sgPsy'>qs9#?sy'8o?fp9缓A Q9u~sp9缑ٛ|js9^i__sy']S\Qp9缏#_)E"sY}8sş2gH9wqq|~5]bBDxĢ1-(88>/jW7G*"G8,2GZGqq|~G[hCX|bjpq߿-ߛfe5YTu{8~.^,{+}c Eq\gHl }qq|~?6FH?`_$T88]=GЯ1q&pqCzqn4z+8K<|Qh88~$Ͽ匕%@ 86z1{YK88>_ P|kr$ 8{$㑗]+q{=qq|~5H__ejߕ 88>f٫kD' 8{WBv+u,XD%=qq|~o ^#x?h<+<q?7Jx8ػwaT8&vi]%oaPNsI|kDݏ+V<˧QQEpq)A{s%M=Qpq~WB(c?'z.?pq7?Xw%D7ս8xcO)գ88m>Z{blMp؛8x՟RsGArqqq|Hk̇ţ8xO 3 KĄV8|?fKuy=7j\8?%T{/UT88w?p63Ẓ+_<8x?}a|DyRGqq{lqqgJXy >3Q88pl12M88}aPWqEqq $ֵto+$WWpqէ5Ū́0i#JuqqoǬ4"] "9\=qq1o|V^#%dxN&88w+[CAU8խ~WBL3\88X}-nWL qnnQt8q6q%$:88ߏ*շQYEqng@2( ZW<"881J>yPmqnUƴol1e#8xGglHޮb R<88c?fi % 窣z6qݮ(gC_Ub #8x3Z}Il T5ŽqqcV~Et!"c8xW ו|8_%T}.Q*Q88wJ8{9X3QǷpq~g1[j#Ϲ88,_*JWrh88wcPf v*pmyt88߳$r :c q{J8{vRyL88}cpvk>2]"P="88wTߒ^߮? :qӆb]@088i\=K֢\^4 cv( cNu&#}X=C|O]T"1Ife/,T0lݻo߻9y#m6H#diUu%Rtp8nWw ʵgQ"% ﻴWqOv47 _|`*8hO&%OgyNwBtp8_}P"x£>c !s5M$rЧ:o8z*S)Vcpx8չNW1P J.Q^nL41 ۿh}`kn%Mw,,:-HZH -]F%[ER{p8>]qexax` wWFKS鑺'ܲCDJb{D[&1o.f8 nߓ)|GR~p8W WMp ܕ>{.x_'2Ʌk lIabr2$;%8p8{XהVZHkrA{D ] 6/ܺUZ)؍O5/nbd0tU0l,?8]-̆kam i32\XOCHOY G\]%Pq |{U/ tZ?Hm%W*te7w۶ٴ45[YW8_5ULŬ?8QL87ِ?L6ŎavxsZOܿ {Ӟ1п:g[tŀkFO+| ]n^5逆|"KI8`MI_ {&quťaU~;ah1;Wx -O/E=.疯l銤uĥbaiiR?6,;]~˰9߉I5&Y<%Їuvߏ爍&!=L ;0F(C zܿ݌6.{{QP10trrF ,q-ܰY񞝀J?t2>d/q`3 G4]^A8b:N`.a c_6Sy,MT"ʼn7.bgggg]F0u3;9.8bLci;׊q$Ļ]@ZQ$≌%,KO@Kvvwz]bg sI@g9:/)ޕ`痗XZ$2e 2 RQj{_ц.Uª. -a$M`qU`,MU a080=co1m';;[qGR?v]1f|w![͔O]~ëN&O%\%n:e-<;CnۡāUW[w)"[݌{PbɠqE}CLqϨK=iz.uSw>{NgU۹;uSw溓2T.;;[a8޶񉳀 `ӫ?j|`ڢzQ ZMt)}x-DΩpNg*NqI32h:ޕPlr~grgsW)bz4qTw^3ުK'Bw3;o5SZLp鏏ϦSwN&( Ӕ?q,e]cgoE94sf|v^o*?(qEh.qSQ˩ :t`= w69~?m۱6zv_F!6}}ԁ[O]\OǢBO )_G|K]iݽ|H2Hq44d '<9*_t~viE֩*8NOa?v="IU:WyE٬7YV@ov/dH4bߓx%A+s3)[J=9FH >u^^񤬫(1HҢuēf[NB̗E\>,ӌ&FO tW1BN=Ã]Lu.[w"u`^\>>I]cgo.3C /B/߮(nݙdN;9{Y}vp7pt n`׸ˎA$;{{n1H!O_7|y ׾M C-F/Xu(;{GI)zvvw1cP Ku)*@Ot 8bPDߓ߯h+C"Lc̝ B[5&ZˎPWh7ַ?Ty營OZ9sCF[ iLʇӏG1p'g.mNh4k|>fggәIJ粜c@{4_-0 ϧ%ê(ʷ+6?J0]P82^`8uݥ>w1~ #u෣k|>ugzĠ;߀J),>ϖl)$Y벥Ϗ߹|$1GO%CGt}U|<|Θь*lF=9Xo;@!;;{;?XO;{{.}|ZysOH2O o$/[(.wF M^U+ZdFܺOYCÝTk|>uf8bȺޢz0 ,>͓ ~"{KI]Q;eЈl&T^Yz\QNr>ܟMfA2- tWc;;;{to%?vc;$IeP?Q nw.r9qL|Fy%/\Ws Wz?k=sX?v:E/{gVv•jI(NVT֑JnG(\jpx?|G8_ az뚿A5E"c0ǃwG/{oGhȻDy}A]g߿Ki{91,Wn&77hg]΋frq(yϋXͽݐpb[wrOwx?{LFKjP{f\ڢ> ?Ϻہq!0c(i)riɇh@޾{Q?wE {?IW{ʗ '?fq"0g\ȄSի{cU-+ܔn㮼fY#)xʲFsV%vd*wѿT7xMKA_wqד'tG2 %li~i_P\z mgl&pg𖜇 @{0sCHoQ9C|ҰOn v|0p^wN6\1xB N6=z N7줤 ar!/Y##۟L+GGz8nZ&[˪5BHgM:bpYɇvuxnXv>tGiOG]P}|Trt8z0nӾM?Qq | z /wiG)97;ӾC<S'.'w-'n?e(iΏ`^%E7"V fZgkj(“z0}@|?k+ʷ@>~ރcGCZ}:wa"*;꿐jn|Qث,8PHx>}zj>t ͔x&u$7?_p{?T< ̞-}[b@}?yw蕙 I7C?ۢ?}Sއ)ɐL>tս<+AޣuJ_3gOcЃi)1apǥzbn_QKTLsE £>Sſ"y ط@>f> YS;k <@O쟥G¥񩩩C ؇?G/3&?w[i{aI<3)x·ȭy1p|'}UΡҲ]E5CYW3>Ϟ590O#f=nA22JqkBp(ܲ(oUIeu >gI|d£#CƀUf7s5 GGF7=p)978r;xWwfplJz]m~3v@j ϜR8Bx_E?W :T~`'Dio4a 1-1u)3qVB[ʗg%8QֲzKd-'e3V%-<3ۿø4VJIpB[ް?'_D+_j%?L2x|m Ovhߘ !C/Vt3AO1M]Jzf璕/;_+'k7 J~.!v/7| 4 *pb <صd7˯kaξz9 7Ԥe&_6g1^U U1܈gP }r={+b(5~tşH{/crO~?Œ=n z#v?OIF3uRHCE~MgO򒨟mO)S'@Aè– :mڇs#j/ o;a~/ Mܨ$,\,E)&eĂ51nX-S ڏn*[eg=,3(ϯ R3-oBx^#ղGz[ bPX ?65 ̸GƯJ R"9[*nT%<qL~*,H F~=c?Cn;_ً̟?r(;078<OHn/mH8V%Hyw_p +3{2ǀ} CL´/ }ʾpD:u|}S|p;W{ʗW^8cC˂֜qVGJUᮏ`JT+٪dx¯QK[ >嫏8䫊 ϮKE8dU%XӘiK~[4"ǰJ c+nP_g?|^ٯ%xÒdY2O_a|ȏ7XeU+V#5SdGɍ/)Ű9O:YGơDɟ$Voϋ|1UZJONP J @:J=7y򟛿R8~ɏfϿ3w+miþݔ?Om)_%t;8RӦz (Dv>g=| [#cT J׼yFU$|v/Z D P 'y p H3 5 lsh$jqer?A«%O/W^v5:n4Ǐ0Ly#}6_hF|q(CDÿyc',ɗad z W)y+Ϳo[_'sJc~/QME_m}KӔOJnP%0 ;)sc0eC'{Ӕn4}[Xda+Y[j5OISqA‹T9ijC?æ>}O1_)?y~^a~PM ;xLUN Em;g| 7cE_!Q[xo6&:QI~|s XE'[MǤ1 - O~H}HPsUBwsGc@Km{lAݠO~@o|؞W 7Rvr^7sP@@pVSL1y~a:OLg|r/1zmC#eg?^qQy&b?;*b `fQ <2WGˢ4^͞"R#건 ."S'OJXoC D>c>x4?l3ˊg$Qp4 ?^D#Ǭ;7Oнrj[>^뙬E>.FGy7}9Kӿ6/d2Cb-t='ëZ~ ,jt<%bPFĿc@SoΈ[ǟ{SKX. 5qrg"ؗuGϱV=nlܲZv"G S"(%a%APErkTO漐C^uʬ@KL+ZH/>!|Pw{2+?.YQp7MS( [RF /C+Ègȣ_pCQ_JK2x|]xubJ엠?F90i<2i=m9k|vl>>Lfm!):r1aS#y1g!9Yy%?/\ %7=x|HWK1YQ-ȗ oK|'2=>7%SK+vq\=O(ux!Jfpwy{_d|~#b {Gg} OMAp3GàɿMNTz}xzF1 B"xOm\_-giVJ-|kĹ~S/i s />J.ZmqHKm| _('mߖ>_u!ϡ6/Dv~R\!.78R7وpr]ɇ?=}NW=nq? mE|O,} ^Ŕ*yӻ kb)0g)/^z^jhHW!/L /$ /iw_OhE^3B~0SzcʰH6Fg&'Q<|t|r;IW2ayQ_`}ʮy\UnjL'1ONbTQE 6a|t1@dFOS+vN"_6r O ~|1n7ɇ rI_R~}>C.ρWg6V,P%}oY_C_j{§/oM}m֟u!ɇ)I.'~~>a2!fv>|S +j˓OH %׸׫BJ>{P  ;П~.g`tԢ^nS+/XhpuϢj$0C}p4'):s pm? < G\P1z\1767 y @!aX3M o[rWܚD!B>82ވd|ѱ* 9e J߅*pq.F|ш*0>sU!~~R;j.yzt7>ǻc0iן^)O?) >sN"jϜ!/=-Ep&q |.IþC?F|["|9{Fc.:D)hy'f=,WR=ʃ><qx1'$4&զyF3)jy.1pIxiҩC5OŜ )O&FkIǫM(1 dDN_U 5#^03 |WEUQȧLS$M {('47Sm|KNT$|pJ* C>F^w'ķO؏Ŀ"(dàM?vEK18kH!Seo%Oo+W-.lp4-s Z}:w~;0o(/m??,Ⰻ /qX>u]/={}\f4PNI}~KZ?}ÿoONDEI9̻`g/>{u5Ա0٥saƧI:Qϝ͝^ohܪ C>•qGLw&2G?& OO"mobg/-G/~~9ZL$1ӓVOdñq7'7ћ<mí?q(ñ c cN~߹R1wG.H7z~R iΛͼ W%A{r.ξy"I.+z#x%O0Ȭ_7~4%&Fȧs c+NxJ‹ `%ʁGɗkkk/׆Z/,KqQh"'ES~Vo%|Of_M9lMFrm$-`S!)b]rD(]<~bA~}*@^3g㐏A~B/ O#Amȹ\9@HL^ys/i/$%HCR2R"2lEm NI曺]m/y"z \>yV>Lmkدe0iB q*}k nr.J/W1]wp^4A5 C8<+wLc V61pcʇ #j:t-'oC엤.cE=e[A]#-xe/  Rs $yTh߾Eyaq0o܂!U=9Ȁ\/Ô0>?$(/GY$,Ƈ_ֈȳK_0yj/"l+ŀ^.9ysbyzocJժux2awX$hi4!-/oQ=*E?IWȣ‹1$ǽeEMsk/ZZS$_5 (_ %,Es!9t-FN" oJEӆ/}?'/iwioXEU `3yj?}knr"/4z LկԣgY{T7ǫ;KjcIi|;滋V^/T~*\1LQk؁}~ _2y<+yTx|k̬'O#UJ$)b]  O0>Qo-D 'Nr;#,C[g8fV,<:ӿ,|v8Փ|A㏒EB!28!/d<"RYּ菀Doep+lPŀbg1}͒sȗ)|*Fa0j? ̳/?,MƇ]2qυ c~*sA>TPR  QBSn6xLSn$=qny$_,L7G_Uate\mp$[KOIoZ? yB9)~He/]fC s(0pWU1 1EΌ@jc@o,Ɩٿcmxd.P"2SGx=ރU ݭ>ǻ0ӿ{i1D|PcyyOҌ~ʣǠ=c]N䑫|E78jv^Caunz8B.Ii~WѕgςQ|ۇ>>*+o#Q>Oq\V, 0w(5#JA>WW㗿' 0˘/пE_&,?iq"&1R"2)|PxJh?>9P=L1{I9z~A890䃤5 W;*mN| #态i&|?^a`%ɧՃ+yoXoWOl sEAW|?J  ]ٯQ"u3הR Z U4VSW["g)? Ūuŭ/*vP-n=FQPU$ǀ' x2>ӈ6/-gr:7||lNlW$!oV2N-K^E _II1hburciL?C|O\>]ctf|=.?~55NWlJprWc frzUt?[I:,&"|2y?^t,0%>Zn,[B7Mn, qy k/oX/ \wĺOZr3O"ب6,+ ?:I`%WDԿ~XǦwzb*ͅ+nHy俎ۆ}N>FQH*4WB_/6SWgYdL}U@0>;|64u\M;883ή J*2:Y_诂VD~^/P` >b1ʤyhUU 1h?xattttWc*oИ|.u;9yO!fL=*| PW:1L9W;CLQb|h6ܻX%3$?[_Vs^_8?Ylpe|v%'M>4UMR9͗'jnʭkBcY|v2l4Nh֬*  _ WdBWAyl}+j&TŰ9. O +uxG_^<Dou?竦ݸk'͌fRC XeDMÃPԘjq+3[˷/$ sws\+E/i $q.Um r@ mZ@t|1d jx28N#o}sTF~sLO@s5r10k/I1NQ0 c_oTXܺg)´DFaƝ||{5 g"﫹6uȂqhcC7s)>J?1 1F3bc0q n2=)*d^r1 R= Unvxru2\!Xב(\+cn2WEs92#⃑?Xܤ_9)H_D6n(|(]ו sc# DzQ_qEpE +?-8^[ב_\bɌqs9ˬp>m9\ dC }(yX/$Q21OP 4FP7xTuNWS/({sъͥ~-Œ^b'Uysǹ9- o̙ǽa7ml_| tG008^sy?\c(v> WDS5F,=|  3%VԿɾ\ CzOq@w~VA- 14s)$ȇm1g^Q<۠S`ec0n g"'Վݲx/1rgpNXGqI*;}[[ٯ+ջWG?c+2p>&m1g^ 9sJH>s^:&T B@c@U] b`r2qX䏍IXq)3g%9@%cμ>\Bm5s|-攇io(CT" W8JU \Ndtȵ~Д*E8Us-<29Dm1g^C+RiZ̧צ1n<&O`@MֻehD3, v2:at ͦ}R((bΜK9 xa̙ǽζܴk1W' SR%$Mȕ`rq. P!䨞^T sDFtfÿ)U̙3p)]]Nǜym\l߼񵘫T P%$MjapY;ȥbYHPF(dΜ%z=P ķ?O7n'$"+e#,~w?iarhj_h9)By!`K>H !!&&3Q=Q] ywk]_pi Ȏ)#*a3kkgĉk;]^{~]rt%m|\Qv,9|#v4e?B0xT:MA@p-׆{Nrri_)hq폜|ynǺ~%=7NT>(;C³L2]1S1R9^ yO&nI rrXӊvouƵ?r幒']5*߫|Xln|>|3L{[j١(wZH+ଙZ]A@"__'''_ͳ#M;*MN7ɗ9ָj@_\{n^߻Q;>_ ,{V(0V p*䲋TrwZo% \DT`)úV:(x92]̨sCc5DTaq />RvVIhͧ3LaF>TmiQ;DGhYJW >VO6Nɗ9SX7 5 حZU8AR#вld m_*|a'QzME ӝffs _=5ctgkLwɗ/^n5j5xl#O.U5.Rh]1V*7ړO;WrI+*ځVT;TK299>ڙN)q폜|XZllF[7vxw˭'Ya%} +ៀ7mӛ~~4-,AQ\+%rr?qu~3IGN\gNƮu*Fmp (Vku.rqw|7]4M3=whfƟz % 3;^o2~8}<Ր/t=ĵ?re;cNV3$r`޼Hoov g&}}e34,|gT'orn;==[_=LDDU Ai967Y\#'_ r\m@8iH7'}&y"޹ml׷.a̯l8QdG*& =pq198c伫C0P" yBιi2%}񫄜93 O#FO?.E9 ! ''_,؛GN;V8#&6+l.ץMĽ[y_.i/X[l8l#_lK޷Osw'zP V%8*,׭싯5]}ۺm7?tkko{FacmO_6Z/k$[u]2kz[V[5a _/'>cWg\آvl7qÇ6+ެ;Wqq|~We@u1 J88>gJy s^Uqq|~G Ϫ Mm8Au}V 4qq|~zO:3'/[pqϛWZ2~f).h88?6>4gWY޹.qq|~6P^k_Ȗy3qq|~^ uI|Tɔ BUqq|~_z9~h("V<+88vz;cU)ͮ8+V~¹\n̬ppqQB+HZ]q]{%T2_P=88/ZX881cT7+IŴ\1V]Aqw%8GU\xXYuUpqWaQ9'΁izq]ѮvfM3 Wqq|~w Z~[̘ (#;q8laQ lFmwo;.b ,)8Q 8mzu10uۗ+N?eW8x}W 7ZJ88^*!{LQd!8x}ת9a5?GXE{Id|x88^ߵWB>ͺ $RTv88my{9cТg,y88wm|4TqH+8x}rXXWifqf88wВ+Eu88^ߵWBQ(^=88+&h訽f+qqٻ4ٓcwŐqqLJޣKL"hiBqJ"gHaG:88^߷Zʇ&iqq쑰(i7?288٧}(16OuQ8x}Ky~:0-WeWqGgs0ˮqa^rb ijJ\>6mE7?C5!YI{~&r ''[1WMKqq~/_WnI&_1K8x^1Хԍ= Tu#8dK]_Q,kqr)[z)B7M q/%, ?Ѝ/8 O* qq~޹Q7ZguR8z*qE-sqq~gq#J?bsq?ߜ3}?./1O&qmoo=k,7߿?86=8\^n/_8?[Gtַ7OSݘ"8x~p߶OfCⓋy7'uvv|<>ǷPqJ88M{Ub?H|5Զ/͇Mv2fcm>88^4Mᵤ˂n7lOC*tʛ8x7Yy_*IRMEάɖk.7!7Y7Cqݤ!YcKSڨYgC4iSrbj88Isq`YqC}qq|=Svg*"$88T](8}GюÇqe.Xmq8|A~+Us9ʪ>wp9|}CT Ls95wTos9s|_>{ Ys'yQSwdp9| :hnsW!ʹ8s>!IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/simple-routers-swagger.png000066400000000000000000001767501515660254400256720ustar00rootroot00000000000000PNG  IHDRtJMQFiCCPICC Profile(c``I,(aa``+) rwRR` >@% 0|/*1ӎDڞO6cG\)@%000% v-Rt=N7I g -4$Ć <.>> F&&K:(I(E% PJUKQ0202``9D pX2C/a`<!4a{-<m `Rfla30Df`8P -atlVeXIfMM*iDtJASCIIScreenshotiTXtXML:com.adobe.xmp 1140 Screenshot 586 U@IDATxUEwFBJDEARQP@QT%Ni\ݽ{ٻ{=g3g>}}g&,    S:    `   0:9]@@@@ I\\'az$[@@@ g IDDDGHddDE cR?#11&'@@@@,(%!qQ||;qfd @@@8ɓ+މ8˄iqe1r!z   ț'DGE|="L}*>    -t&t9e @@@2Q@@ @Q3   Sc&X;ޑGko#יmN6C*`ra&isk̞3WohVTQ֩-w(|<4J冷f˒N? eM +HF u67Oi    ٦7MV{~OoLq9N@#neɬ9s$66.o6qye𐡞`TF :̙8yjѥO̘>C^|y?hrUWczNn9rYt/P9s3gz =7MeqF9F֔mݺUSiE ޵;zb޽rСT$%ǏoJR'̞# NͻgWvi@@@I??3Gi,LAu:/4_FNVf@Mmw[^L:B؀Ψm:Db$|ihᅲ bŊ\gNyaÆ>yjժU-S΍>b墋.e5xdUկ_?k 7eʕ:;Wnv}ĉlK6@4+fȯɴiӤ\r&K\{oУ~FL"ŋ'|BZl6|p<&+V .@nViܸ=ͮ1iݺ}RlE%_|2ٴGJ-[v۠AۆF[˖-k4ȡpzlʔ)NS۶mes5ǃ~zӷۤ|ztM{9YpYthO;KmoY4sN)]=/^,mڶ۶mEhftM wˁJ*ҩS'O?~ɝ+tEIsjzotH_e j믿hQt:9'O,SL]vIR%mGˑ#GDkVB ]t\'   ptcG&@>cL;zCf*TctN@Kzq ed`u*SgbEY+5gwo/X@4lqwLpBo_^'3_{z i/<̝;qK!ɻg4sΓ[x ;_Kڇ>Xʖ)+Ͽ*Tܷ'coש['!1A~Y4I2~yoĹK^{5Y|λ^Ԯ][5j$Ϙ웲ߛ oGӦMeÆ 2񟉢1cƈ!LƭEFtTw~UXQonwwa?+UA߁:wl۲*E9u-ȕW^)fΒqcsB@@δNoț)}ѹjuU3}N׺z3Fzϐ^ C:3~v+iOZaHf j<0+::*&M^w͞/VɃ:!h@G3])"l >\q a̛7_3Ì *UV@iIg: =Ad_6PN{6D>ݯa;I8~0=O:KN]d P;xхOf65Hj9mۺ{=Ys+_   p40s~?`]IZb9E0fݻ{ z;C],d/i5;G^dəU5KGRq~_Qv>O]9(ӨFt_E5)&6Σgރ}cإ6[fHyйq*9Y3Z?E.9~,)@caCl~0D:ut8K됶3gMmF ڵ hIiW3w4e}LoNժU˞+U ؝txsF^Nڿ^|f賖)SFvI$zr#ol\6xxi& .:)^}v٠Ϋó&MdΜr'   p&4PכN=f9:IF9 7444xA' \d/dVir~#(k'~MnZ#:E2.Oh]gmât\'sD|+:J32j6~ 1˖-9=x6!(W3t2R4cD(N ؂\3 (PPt2,/yx4YYJl9 hΐ<2n4`E'I7o_z\t2o:IÕʘ A/8C㜀fhVg*> \wy\:;=kU=]MK9xN ɛ5)a\F>:RNG [ss;fi>t?}1'  d/ ߏXFz^ CHv du0GCvvIg9kS>+"<"+ZLL׷_| [WHoGȷ~+;]gkԨ ?Kl~d2q=$鋶wOg;22 Y~;{2dр~鿿p̗r hfwa+{kjvǚ5k&z%ntyfC>d*XM^j׭*LNɉ5SwLpχE3$I'R֢mt hٵ{mK3G_={} ^E9_ҎhfhG]b[N%GWUhλ {龮H٧:㽜y.ow=4SGW@/L: ywtϽxDz__ }VM:ٗ>l4x,{gx3^T㡇vrA.̵twY_{^Jtn @@N:J[~?r&G?~}:]t*aKjbZ9íʬլwg+gΜf}g[R18=;ǝO]H?-[4wy7CS-:~OHa<:|yrtU'͎?ۻߞVYj߻yT,sji2蟵^ۻ];DEΰ*_ϥ{v%K}&mWf:*}' ]\z.|5,Fϟ?s0|;nӧym&'?e\p({ڠڦՆO=:L  dG~~vMpND NSgW:"aFQȟ0Mj4ꝩ;SR'@`>7זFI5AfhR*Qf'ߕjY4L֫`E<4bìN7BR 88$9ޟrǂIZCjA hR h W]]'&N賧ɗ@4{F'9 $qì P8 ԩ{j*%뵮>Vk#8   JcGّ/N=wqM9jG]iM&G\\*A( H" AwifYo٪e-Cm|"  /CB@'x됶_>+   .(/o#*WN|V@͓;7n    }?i+;@@[#lGIb 䐗E7@@@@@@ Cʆt13 sd×C@@@@@c 43i#?OcbbOkIt@@@/KjV3,t2Ė=/: fILL̞W   eaaa& '\"#Dr"# #   `RЛsG@@@@ (:Aq1    z:7    @PK.F@@@"֛!   A 0*hB@@@@B+@@' @@@ZNЄ4   VNh     i@@@zs7@@@@ h:A    Z:n    @t&@@@@ tB@@@@MH    @h֛!   A  @@@@  7wC@@@ 4!     Zo   -@@'hB@@@@B+@@' @@@ZNЄ4   VNh     i@@@zs7@@@@ h:A    Z:n    @t&@@@@ tB@@@@MH    @h֛!   A  @@@@  7wC@@@ 4!     Zo   -@@'hB@@@@B+@@' @@@ZNЄ4   VNh     i@@@zs7@@@@ h:A    Z:n    @t&@@@@ tB@@@@MH    @h֛!   A  @@@@  7wC@@@ 4!     Zo   -@@'hB@@@@B+q7B/0gbYllڲM<, !Dxx*_*+#ujW& ;GɖsЉt4!rr9%Krru@@@@ ,є,h&8=n@] h gªMNsgP ҺKv[   p 9[߼˟{ceꌹ)5m,,ZECYJ=}ByK  ̡s  sT\M@Jvh5Ф}   N9tBg͝B ì-ÇJLll=bEȎӬ̗7DGG;KY\4_0+95K\i);AV-v wY"m)_|{lŮQr4fy)g72s[˳Mn$LLQ@TNc>-؈W)8  dCƕVϐM7]{;\RifDFFzݥTitoG}:$O|||럲`2Ωz5}̉{N2feozSK8sgER,_ {l  [|}i9ӝ{w/kZoD'=۾c3­?{9uoҳ   @ ͍x9;-Mg h& i^Fs`Rt:'qt\mK?/g {%|SY:F'c=ӾjY   e[5VռC/)Nzc_-RXF=d߀CC=o&GрSϾch߾g7υȓϼn=ʕ-#7\t MWE^L6{X&O,X@[+*>jTlG=Q&Ni:#-|:|Dy ,͚S9:4wYHOʘYwɞi9}j`fhiVIg2" JMd9xWDIgX3*,,\4'_tIة%Պ'ȻIlmfPP/3K/@@@ KͤGM6w~=YgY_lєj OlٺM>KN>#)dM[ٌ> }l4&EIz,Y(ڸ9}=U*C%ь=C*{U)̂-?zuc=Ul/{^{o/s SϗϦԗɕ'W Ъ]{ =   d@ hj >  CK09ә~N3pyL{NǏ`DZX"ӇGѹ<眍… M7)NШ@|!Љ>j_mg[7tBdJ_hjk3nkƍStȔҒ+-InlvXAo&_~%dHד}D@@\lG7f&M3LW_@!g6vrsԆWS3yk ֍&pY6ZiQYkX6$eƚ㔾Ӛyut÷n=S~n?xtJO%v@@@\ sDSΔsMW5^se60r͛JbE}(_~(wF5.ۭ3^^Wn*ԫ[KׯsOf-úhYҲN|PiNpC=< w4'X̉˜$ZtsΝn|:iR WYI7?;]2zyRF}ݬ]+c=vs~^RQY;N~2wJ'3ëڥu_{t }vxvV5^=i[LA@@zlG/d_9LN}9>]k>5a^믾Vu͛]$LՕdJHy*O *ʶҥU~I^aAt*Z*=Jk|7Ъ٬!_5*UH V^Zj%`e݆ɛ8 0[w$Ͼ_!Vޫ\m=0Otbh92mGv)]ɪI{m:h&+RZd1YFO#D>Uz~hl? Zl2zfIE{j{ZxEN&TǷa$_Tqe=,;   *-:)2~߇|׻S\޶!6/ٹkϱV-.1KWUȢ>[jG>'2insd[td\9v y<=R@>O0gɲU2gb&&iC7I.h0g؟cp- N1;,Ud5Hj x,?k?W)~:*f0,wSmaw>,Iы$ּcۙUU:̳7|UXj @@zlɛ7NMN ɎI^fϓw?-o|Z ؤY~ߓœFNljJPem/\"ƌeLɬvm/CF܋}AdS;.ΊH2%e՚ ǜ;Mî~}\9֬7ö;NUZxI.NNԛMl-e ':ͮ&l6Py}Lag3k}b_[/GMϽk53eR̷@D\ҼAN%+@@@ 4Y:g9G|Gښ=idz3)?Y&OHUu}isF~X3'5k -y K~8Sm?Lҥ2}vi4pN>Yok h?Sq, +wC_ifl7'\{Zz`ӎsݞ6+'y0G}   F [tQ;tu(Qzu&mDI,X;Ƿm)e;-UtR#NQE]''>[ 5kN<1(﷉*+=,Ӄ:GZh0GHi_#A@ E h)   6C4ģ=O<)3dҤqCY+?#'l~NqkCRTs`~֋Һe3sN}P^rt{%w[WVjqiS);Q]|Aزe]ܻѣGmWtJS y3cC%˕xN̸g m9:*̜milF)I^/:g"3' @@H6NCP6'?R~;e} `_ %}>su3BfH^4{EKT$:t8ՀhW?Q};{"٧;$_α&s NtkDtV&}aIZ>3*uis]\W:@w'4p? ;*nʡ[EB2r]\W" u  VbO3 rNȱrY*<Es587ŭ4jS';5oztxOpOJ,t|ꥷc2|E֭9%-/ [S͒vͪg|Htխ*N`'uN`'~   G tʔ)%Mǟ}i9E;uk_Z[oWѬ`ˇgF81Aif˲찤eW:{Μ5WkmIn崧$[2oNWD@@@]@G{E3XTZ)[Gz.'0H^F{ҥY?ޥ_:}}Փ٥F*}q{   nȖyc=^}_ƧR&Ε+Z > hZKu̫3n|W~vӤs3ht50,XTRty& 9ʖoPkG@@@2]V2h"Wn)Ff0GWSԯWGbbL~b"'gQcO+ӵ5ҥ@);@@@F t4{;y4N:otDGG{Ώ7ѳކpһ&,]Y   C ' 9խ%hD ҄D;oamJknHQH=c.3w M]F>@@@ȶ:s=N+09s;BUpt `Pe?ѹmjլm: ?Fސ8@@@@dNjH}pf:I򧙳W{N:|Xlܸs{#>!{WzG{M;9+hѳlW\#L9ٱSO@@@@(M7t!C;wN&?>)iOLK7eW:x?o&ӽS5kכ%9,k_    nfhM Yn0qsB4x̩TRs4r[ȉS紁&8af/ݴF^yy1'9垖vWhNT21G(S8R0l5YDZ 狐W:ۋ7^lP@*@Oђ,5%o^O `i6N%\ڶhyCqioEW2vIYF}o/+LSIMNrV@@@p@::Ib.B3.måtwn9z ht~iPFi`OJҩl!Ɵ2Im]@Ge8[[lί]&GKI3)ٓԞpi5'͊.ۻfټo&f;.qwRISVHI E`Ct@@@/p*j:aSASVmMm ˍCye[9:StHAjQ+=s85z@3tJҼf> :d͙昘.ȧfn72rSѠNymOoӒ^d3iuӧcAidT4#+s HzZIri@@@8kNd#kCft"a-:ߍfo mzfLXF̜0:髊ۉ&<2:S4g#ro-G,N@IDAT>uY|ɼvfȗ*?3Goh' kTq5C;[IڬtE+]):s䓿 tjRP 2k;~V 6#|"   Y&fI%gA昙F'gVhE3!pT+m%uOFfT2;ь_mT` <7eCjsmJ\fHY񶛹td|ѽ˖3H02E"=CR@@@@!IQM9E_ڵ;5L%Т6I&5&}/a=?Զ53)8S{ve/]})ڮwqь"     "ģW3u2VDn5SVEN >>   Cr!O   V SWB< @@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p׿b@@@&@@moA@@@ q+@@@@mtFy@@@p@dN| 7q<]owy+Pg?VSgʶmȑҠ~]um._Xf͞繾m7Jܹ    ~ɊYlz:oO4iD@ǣ   gs(m%[='o;9^   ի4jH֯_M5z]KȲdο xaYpL2C֭h7 ~?~/ڶիםGɊkd2obٴyk:z >>^;Ѡw}}     >*60`.2sZm#l;*.. -V~w6v9|gˌYs.'_"#;{p~ٞ۶}2w"Sb9Eqȿo}W}ߗF y,O{)=+mOkr6}N7oץQsO   Y+Ppa8qlRZj%4l0M hJ*kZe@G[z>̙26}џmD3i!)[퐷_B۟"HGMlݺ]nzZa-'lH@OI[!y͎R{&=@@@8N'9R含1fIr u{NQϥ;{K/Wm\kQ3n65#FIF;͛.NjUfr   KfhW9-&ehP˯O-I|{䦮ɑ#Ge>KyL6s,^ٵA}D /:d]=E3r9j|ny$66N.nq6{v5$Wh{{S'V>~gqEQp!Wd?Sc=9=l    7*'s]@gϞe6ft/X}-6o+=mݺ`n)]k3nfW4C'rϝ$U*WC<, 8   //9s?q l۾çM/j쳯;:_@gSɍikAevjyx߲pR!X]q@@@>Ƀ:ڳ0?lٱcO?kSg_wJ,ؼTf'1r"Ǔf@@@rwPG+a鱜V]@'_>oםU֦8J(.ʕS~:~{ʳ;w.]ٱ7hڔ* A@@@Rv˖-SZtYpZf8̙?gJ>/r^y=h?/og>/g׮=2qtϾ8y;a'jZ4x@@@8]NTTmѧ_zcO" VڶT~lܸVI&r"({ϩԫW;<˖)֍/(u7ڥϽjX$[J\[$|i-QQ>Q_WYzT9v@@@@.CG;w D֭ xgx\^z˸}9z{o$Ƀ#>ܩ[I5Xe>m:n991s"kkS|NNu}jˈ?GKɤ}*   ȖhmR`7maaڵj_K{zmC~F9sr{,LN7OWbrAۻu/s+'_t|sg}CXs^ GZv@@@@3s$M2M{lJ;N횢/={ dRt)jmi@$#%..NtmwJfjaRdÆr,^L\P@.Kg>9r4*^h    @@@8=l9    %@@z<-   @ ^"   g}    :.x<   ]tή"   %    pv 97O   . ゗#    %@@z<-   @ ^"   g}    :.x<   ]tή"   "C S խ    70>%pm*"   q\W@@@@@ِ+햓 |^W   K ,,>Ӆ$'!!h'   M@8n?@3:N '>>^D?G;Z 5Q@@@"dh '""DFFO}F|Zϛ"{sbbbd^kr˒V8   [ :BnPT-*m:ddy@G3q4zw7#t>7L. ;sy:@@@DfmDyQ^<u!Xi=]ttǥܼRdVw8   ]։,/6>*s~ް,]rY::J3s(    4^qYH*K:5 aWfYzYl!   *k +Y*   gOă&It2 JЈ ,v!   pstJЀ[һJ$_=D@@p@H\sQr,g/z   >3aUwF@@@%p:i@@@@ @@@T:Ic    @ zcG`ʁͼCfȾ}j4..N^}5cws%,vy6@@g|+Bi%%$҄KѫDbO=EB"ՋO5{ݟE cnڋm۶ɱǤ'1>{om&M,ӦN [7;THLLիVKbŤhڥfOc   @6  jPFfaKY0H2}cRC]j',V$J S?~6-Ql/Նr `ŗ4ҥKg$$$sΕ}48~tg o{<,uϭ+au)X&Hɒ%^z) =r*F C4(y :^0   {L{yEk&a&(xY<&S'Lz^&&"i>E6Mчd%*"LJz{Im{_ͯJΝ짿_1 ) 2w~ sF+V%-UHSL*+VcGI… ۠-[?#&ѪUK1c?)S\ ;Jk9|谼۲=X{._ ݞ{&/U_˚5kF]w)*V >[s.{Zjr9 Htě>׈a#DihsOUZq2^݁k:ȑ#f(4R~ߩ󙖅O zt:q}f i˷d ]&SL{󑖅O {)U\uu>l7VBD{ y׭q۳gzU;mLSLw޴|+3ϔf6.w}-ZK^SliyG$_޼)~Is7     d.]!=p)cm6JVFtk9^Z犚ٳsΝ2a?6> ^yAzL|{ri:No4l =s6 ɓ+SipGfRH>t֥kg;$ɹF%N0^/~ /J {_ ygJ6HwRn'}j?5!c} ȹε*U(|x vɀtv9 kre_&?,U9ь[oU>Xxq*֬׉Ѽ R t?68[S* 9,ܫGkeuaHPv?Pz]ZFF{af\c뭛C]VZY׮]mcLC֫wOk~ϵ],7=>Ԑ9*_?}eQR&hR- \vm6~;v ՗_|i?o 2THAa>l]qdr&d_OS' $4 ȣ֮][5a  8d׸z8uRl&ySVX7/nl Ex֮ϱЪ8vX ('3S]oۃ Uk~3cL?`߂C0uВ]0m* Ԫ?*:b-CY;v`:tNtR։mbk'#3Pe$)-T@H/X~Vefn\;计MqQ0dlؗ=6qDS}˗b ,5dͯDSyA   @y ЉC7+]:vٽ5"v3#+FNZޅ%l9YnyЬs1ݪTO# yc k~}PG QI=6s QӈQ핞ESXS2bG3Tŗ7nl^ʴ.= >]cȕYt6ږ j*+t;v>' hD7ѣǃg\tɅ6bx8`y V?KՏ>ÛpCvvcg:Wt޻ǐ{RezصWZ:6sЧ3N;F~` Ōb*T뤀/jXR;nt=[ߢ8u}T':vߙ?   @9 \6CTD7ϺpJC{)-L,ݗ)]~ͿV?)vij?.δC\e/uz~UVj߯mQZB*Sص,꜕2Z4i5^72Tk^:>7W(ٖLJJrh'ž(s}+;DmD5ֺ4Juy |>ǣUV泎o{x6@czzzO*>L>**   \QDx:ANr|{y8s@@@@`cV$)׀QdG[gڴdl|阃   5M@9(^'BqShzegg[ff-XfOiޔ-    P=4J9 m]XbbT\Ntxrrr~9Ɠ,@@@@Z e(s :ITೖ@@@@(^ѵs`Oq " |    @M84^ {PC@@@(Z E@@@@  S@@@( >    Pt*!    SZAG@@@*XN;@@@@tJ+    @ Щ`pv   V ({0-ɺE@@@@(L= (rrr"=H!   M@A4y{@'dgg[VVi;jds   E Q '11ѿT,u!P kEs233m27J'Xf&n@@@@j h֩Ynmd:d{@G8 _cCfֶv YfiT ,   V`]٧k$N0+։{@Gì֭[g|Y:4Knmb@@@@%0m=XZZiUqî+eh2sh    y(nRIk@Gvj0*b@@@%5tQ).sA@@@*@I'4Y*"J9Ty#C@@@l9*C U.A8B@@@j,P!Cb\%5Z׋E@@~=0Uk#  T/Щ^     Ptߘ=    e*@@L9    Ptߘ="'Ykؿ+-diJOOghVV~@qΝ{&3   PqeDۚul$ [<צ3[mm8swn6f2ϫNmGmѢEvZkW^wk>{9vBʹgXz[:yq֨q2=,W#G،3]vvCt嵱Lwnnv~!Kۯuv6{df5 \K˵6}P^sٷmVz&999~iGWƼۣ{+C_~.RS'{xe߷ZkG^f. My{v|, ZjjJͭ^ږ$gڵ[4vcw˯Νw{"|3s'7VX:5jXآr ~fͬC>oA|PP~z.;'3?q:K`l@@#<UَG뻅,0sӅ,׮ el\[n$75uNeʐ%'lKtugVji4 >g\آ|xza2X^,[`nb.o͚5KUAטSX'$$gixPQX/~_~nEc/r2ZP~TQ[d5"vU\iz]t%>*z p=d{};w3Ͷ٦E.]w۵\:d yll{؈}@Xk:n` 2bmont'[:  PoԠ (HsKKlun-殰ۏv tuf]9azn֬n|Iiu-tU6 +nw w)x57?s5km-Nm'9mO1r73ݿv5oOѐD7.5 <.[Fv9g$x\,ؔU4fX駟Me-[41//k];;-ܮ\s#s_/s<oϮ9lϽ{fv7vMFë?_ti~m1;ߠ)1 kݺug:o"訡Kj^ed;]O #w}3N,e0c:=sQMC=/ȴy~e  @ ǥmY?iؒ6do||r,vCKLIlVr]qH݅.3g\S;IL gh47?l0n?O:!)a0jo۶<3>`?cf}T7&h?KK/^ʾˠK:W@YOo^}e=nPFz'aÆhHMz3<+e\gk^ px.XqR L_e^>/Ltwo,L!c \-7WvNC_|6|0{q6!v@py7wl^|Ad=6F|ѓQS`Fэh< nǟx@I̹嶛ms>3N^|`pu֦Mk;]r?Z6~a=oh/"immeO=try>q{eva2mן GQ~:~]}Uֽ1>o@A I&ы\`SQG_ )6҉,<oe={BH`vιgkVM{w,X t;cH&Vg R1}/TH}7|A6k?zLo:v=.Xpubͷ2Я #e-{@6zkkݾx޽| xӦMuXԊ.hZp=n6uH nvt!CwcPg+@@"@N3-цRFQTvn, it[zMct)݌w?68eg႟ >_rT 4L%}"5 )g[l(=zPfc:u!cIII>F7jeuq݄nԭ[/;CUV.K~yihUzi3Mt~uWM:@_i^:O 9ӇXA秞xƎyTT'E&Ej=(@Y-L}.B=juQMzJUᬻ ^Wxog}O<`vտog;9!7 L?1_m[oJ DiOzeۨf^zi ڹkmҥ~[\jnҤ-[ڶkة_o1>tiGgpŢ2 n|ݡ}{.TWK$/Тd R CQ;~?K7;/8{VQ?MM-YW4!y+55;a _ "< 2/zݓfϚ 4 gj*8+GyV Mjt}HQg+ά$^<-0MśУeXijxlӲkjG@IDAT}X2ob5_ïM*k#]m}7TJғ3ݰB|2*ꫯpҼvMj~9w٥}>{^^p1CmƼ:~w}xpwMv]cn  T2:q\a#ʏhֽCreۄ^njxxW?ul 9M7ֳgBO|7'F-Y4o{=*os]DR +\:*x|!GFd , _ׯ>-T_!޻ 9ԬYSy-ʜ)Mo)xWvTYE.>mSE\v%)e3]wS3T}C?I5ntngvb{RS0裏SN=9X.} p~[ܐ-e܋}jo4WpP@zҙ3U4@@@e3[,A/t 4z낉`e2u5r֯'e.-RřwzȒkշnZXӔ#ʵ\\"$MݍR)Sص,꜕ 1ci(Ӛk` Y|!\YK+㋼-}q7))1ɬ,T9V[|m'Rv-LǦaUS櫶ܽW= Xh]eR)vC7D ߿j(8DˢXulE`jd,4~ThE/m Ie$&n.X^zzzO*jEv!ԁZt5pbY k @@@ ];'Q! l`g   D L5ЀNE?@@@@+\,A@@@`: @@@@ ) #   ,@@    PZ:d}@@@@T08C@@@J+@@   T gw    @iJӒK_@@@@ B!J4󫐀8+'''>ރ    P+!!Ogt@Nvveeez)FN<>    P]lr+))OuXr8X6qYt0'33,3{4nqefoFY @@@)fYFf)))>ONt`%96dfm;nuiiVAr     Pme}ٸ9ֿۮICbxt4jݺuȗCD& @@@Y8.c_7\[ RY)3    'x&%yTtth aWfì.@@@@ (^ZA@'r ʱrv鼋m]Hk[omrmA@@->~ifw sgڴyk,;'g\oȚ o(77b˲̎߬ޗΛheHj敱}\"jE.^ FֳW{yH~1ee , :l]ۧVO;( ؖS]xu322oITFկVتydu)8T궫q۝|U*?ɒW3   @ |j+3 ~iέEޛn?[hvMr%sfuCXp?Yk$յP5 ͝}7;k۶9Ϥ߰>ΝkPq'C,{VYct͜vQG!Un\kmlņ={Y眙o?{u}mޏQXnt.5kmM նcj*{O?Hnt\=\PIˆ}oxz #s_w6jh ̱Tk,o^mMw˖/=}xp7 #~SG//Sްd8_~5f0KY}zJQa>   @t@jY?iؒqaE>ғ\%;C!Y,&5K$i47?l0n?O:!٭\~hפii?O?מ?`:͟7?<K|e~|>7/2H4LCWFOͿ{&9g6+ F)أO?b;|H@g;ע'SP'4RmeKM:|J7ٙgaw`_65oU˖vE[&M{{m]wXÆ.Y)ׁvmZnS`{glOcta'g_}6dJ{}?g{甔}\/6mڵ~(יghg@@@@5)+M7s=~S~{v=':ZCfN/^lϼ!ԯ_nF>b8yz;[jwl^|AdK/FiGntѓQS`F9ܳ"cym~'g y?f}O>)y}\ʿS'{m;n jo5g NYvɥoOk;_GG8ˮO|gtݧWOQ_ߦ~oR[oICcۻcx֠Aջ߼ PUTZ6hNRP$sJ}D.s~˭tEۘMNpZk١.#$iW-Ut cR.so G ~Z`@RW3?ϟXw֫kH}摲6 X_oi?>iXF#$kۮ:ZRRiuꚫKz],&] voOS|PMJgk~ a{ߺ!w!^}e-]S @@uU+SXIMtOYarܰ.9 Ex֮ϱЪ<-ev$+S5m{em)㦥3cL?`߂C ydX(i<-JZZ3 +RS-uՂ Oݺu\R8թSUJKKp4\ž}yffMM<9Kk(Nl췹:֧sB8SvC FQ{cwA?0ҿP.)EAm/4*ҥMpHdF1oq2aD+)fBk2L\@ƛo* 4ur>r Aбތ3vmWSGY%j۷`E-:>x=}gkݦVO*ϿVnkc^e? wCDZv^O?>=j -0#֦Mk?{˶Yl &ettzb=j]sվyz){v@@@Љ"ޞoQc;us6y!mnjhw1Y/s:(j={($5FE? c1A0gW}[WOzྼY$DJ_s%XLJrςQTlXu9`k4Yjj@SOI'CT8^'~}Hnk)yuvj4+mG/HJHQSO))`T~^б}dbvj ↇ):7YYnhS8CMɶnud'SQsµƻ'eeeŮFxޙw   PqEj٥cڝZ:.n]3rm-ѸXB̖ :ZЭJN5,FC콗lղs8CӓA)t3&"zbQtSFU? tX~}d_{Fk׮Ze9`RVaG@L-;0J.{wɗԓIvOk ڌ3M/5 +:N;}ꉧ7:iky-ZOiF322|3N;F~YdC4M} ļ;^Ū2{ڹN#Kz"H O_!  M -oW^mNih8傉2VF5ZLۥE8NYrM!VY}vRDkV廦oj UNaײs#3Ԯm*֬]*H\v!v ō}Cpuprd[^KrB))QQc ڟ.r8MzlfVv`qdZx7lRH.GD|qiP..ӧ;*B{l i   @UP|#:~saO@0X k˲ %P^XTe% 7xnQO۶m}@@@% ܈Ħ^e5LTҮ')S/:34@@@j5tj{m7<)Jd`S@@@jp9VDC@@@ 0䪦8@@@r=FPpͪ%@@@ftiYDkpjE@@@*fϏ9reUjpQ0'|j<   l6љ+@зf3`    @!Wph    E $~RLBB$2 |@@@*A'u5::95p    +IЉ'S&))Ɏnɵi 1@@@j2s'QDqOGr]ѦζL[͟ )[d@@@@zh2si JID?ک,r 7:; xr'UY    @5QG/eFt 9g-!   5Q@k<*$DLL@@@@(piЉ    P@|^%    ,@@    PZ:d}@@@@T08C@@@J+@@   T gw    @iV@@@@  S@@@(@Ri7Psss}`Zu   T7P(O){~Q'xD{C@@@8z%$$i9,Nζ,T/v։2@@@@@Nbb%%%1X|C.&.dffڂefof-NM(!   @ %ѬS;:k,%%u)2q̙$dž̬m.-=7\YN@@@,O37'w]c5IA`V/Y[uhh:!   5K`Bg{4]c˃!W0+e@@@@/Qܤ$*׀MA?aU    KTk8ģRD9]   TzO*EiQr} U^E ַs$G   @ sTVp _\:rq   XB\hUKkVG   P6{@aVUK5z׌#F@@^=S89@@@@蔿1{@@@@TNr1@@@@蔿1{(DO> W[Ҳn3ϴ˗ǵѬ,ց67_:U/ ϒ^'@@@*Z`?O4KM4뺭YǦ!Krsm|f{mSpn_a*#);;F -Zdk׭}#ٹc'9LMxիWؾCqǿpCmηs٩QcO`=>kyct풋.&Mxud@@@ hfW(ZogGfڌ_:>"kv)zV6=צo^ `>vڪ\$''o?5-+c^ѽC<\fW*){33ۊW5k~WDemp }/{:wŶn&YC-"_վzUw`}8RSSMֶC,))?pfe6u4~1f{cԔM(k"  `U_&ͮε篵iXvNԹlߐ5Pnn8]e7z-^Y/]7ʼ+c_gEᬉ";lX FֳW{yHCf-X߼ovEv/nZ1>E`[N+ t9~s}bw7Z~,z_M{?0{ms҉Yfvve6}2{lOOaWK<\E}* jժ&^l+##Ö.[bף  /P[d+3 ~iέ㽹+fr%sfuCXp?Yk$յP5 )ݜm6KLz Ï]\5lNm'9?׬ИFYC7on!Un\km,Ⱥ:|+aܫ,3h~guAhYf k_m;v1o_xE}Ҷ۶t<{#e#3ϰQ#Ga\HkƲ]&tl?KWہw.07Ot{'l;:k[}ѣƺc]at?.|=s:S';lϽ4]÷&7m tժU4΁e]|}7~꯹LrͶFbP<-}f2h(ի*w޵Ï8:6sP~0rx{]\믿a#߾b~&Oy/,F@@ЉCepdXFrcKRtǵ\MHOr톖JN+^ fɵAĴp -KLNs}m¸ N<|rJ_E3uٶm[yg|Gk)jSg~Y]z%~U_F4n(7` EE?|HDS^{g|IΙ*%?w||s#y\ע'SP'4Rm5 a)u}32™/j>i^`oLz vnvGKPY (CCI'v;:]ly5i<㏦lS%&:Ҵv5=㖒?^~i[;vh{mr;m7c] EO<_ lq ~j5nzr4!yk7e%=8l>yR>>S+P 9=p؋>}FMC[vvg2+  #PM@9.NMp~_9 d[[=$':Z{K u_x>ر;@|6|0{q6!v@p<ԔpDֻKlؑvL=J5f=+?֛&F9!!gqAݬ'EV;o󟵯+CTF<&afw:K.g p\N>ZkmpN]q;=+L V-[Fx<~asnyڨqt\q7졇kC4CFK,N?۾u OK)Rѳ1h=>p4Jڊ5f(m->k?z&; yԖSW\y~2&<0z[qMvnݺvEիM|n)ئSj\ }5} {sUR-ʄ~/[ 7 }nVjklpG]9fl[ W>א|*܍n39IT֠A8]J7*vJMA ~r-]-6fӣ5TH&vH`pFn`UWÇ2tLXPSv ,L !R h钥wVlxλlu0e$}>HGZn.T:~^sU@I}gc}jnW~n,Xؾw:jʶPr _iM>e;l]-iv:ћk믻oCXvfMup tyg s2>Xؾv=Pog;,Pa<U>s\-\vMk0aD< u;S޵/k/oGV}˯}E S@R[ -/ۮe>U\K2ؔ,8`eVNE/_aZI}߀(IY:@j|F@@llќ5N۾I^@gV;) j;.N^gnF7`(1 >լW'.ЪrtY$3f̌!bi\AВKV==`[M4TG"r]aln:.)|e6ԩS߄Z8 pط/ eL~3|l3~n~Z+$zhQ+4ՔVwt>s7ApM}ܲ6 S\={"ڵ4j]waF/Gi^.xqE~eG5k0jEt4g)?LpJ2}\/Фa.Y_~#;*2OoOoV>7lO.HC/m=Cs/]A/c?Kì4с?s @*ૺ#AkӦM6L7 2~Z@0)"\ɍ7(b;z߅;1c& 8z% mZu9~N^7ƞz=j_$TH/T|WkELz"}a?TiӦ߬Qkd7oju%al,cFz2$ڷOuCA+{Uk  <]0PApۢaCkn7T\}wtzeťlW䫌']e<,*pwڻ,Ygvo7'{)GF}oB %lh4Ǟy)k9 ixV׸y%4{Oً/7c2@@ Љ0lz{U{DyȎu=wYlĐR75dcn4ƻcf:6^Z=({EA={z/*bᴏlmsTU7_uAԫY*I9+MuI"rI2H &CQYzg}֥*^igUJuw9&Y <dCvj4+mG/HWe24+?6vgl7xKdu\j\ɘi^*JCgTHYkfFF ȈEm(mGk؍ }O\aC#_|٦Nv1b6mrΡ`ڎ  ߫˞{ZC yx(bĪIQ"O ni~cw z94SSY6T/ 7Pߥ{}p?e(Noh_rhy4lPUk ۪Vb֯ (sV~Qruu.v474o @@@ ~:qXe%ԲK.;7u}]d ʵџӻַ Db 1[n jwbTECeвUButceL7ʘ ՟QGY -zxM0OS'ߪla-+;! wӹvHW縂I l<8~WvOܐeFNtNvvgԒ]BfL qR}`yqӴQ:g?Z䝣`SOhqD>&k~BդcW1;>P`yBMt;ԓ>ivl.if@(Rj z)ТnT5eќ}Yn(þFi!ZRSYBj~'#Օueb tu">-K0oŎ:"\3Oͳn負u.#MY]*}w C;q鑍@@,eb Z<_/7_0v_77ם˚~R"~\i,V}H_վ_Q;O?\˵u+]S7*T`kY9ؠIMS@N0}F pC$(IT7RT>wef诊RwclQoZJdϿiaߗnOܰ4 k( f iؔ2t-uS0j=:*mNC@@ (>}Ve:%ƸW˲ %(S'tSUI:euM0=[Y U]ehx ->=ZCX+ ŷkҥ~TԳO,w  Tt+LYJ4euڕa;|=st,:2P:_K\ QPGq˘esv;Zm[B+] s) }@@@BT3;) [n#PXC:"yPq1ÍBTI$;ccRim92~Ku]!C ;!  aYPm=V:ջQAT@ll `f;v  !Psl@@@@ lN9B;q6"a   *:]ZV2"@@@@=?o;\7uY8V-we(f;v   ElK8Bf#   !Wz @@@@hO=IHHDT}X   5U@%h7Q$ޠNttA@S_'^@@@(L@u7 :u5$%%ٸ96m!:]ڴ^ٖi S}827e   T Rf9maW))G;SFu|pG_qu9 @@@VAF8 x9(vu4U 'e4@9IDAT@@@& (Wt SGtqi0)    PN0נB:@@@@tr@@@@T08C@@@J+@@   T gw    @iV@@@@  S@@@( >    Pt*!   H*J~nnLK.}@@@@& )xϯB: x~    @uPG? >s 9ٖe:\&    @uqILL$?9coTbeL[͟ e5@@@@$ujcG[gm{UqI#H,Ŷbaڕ"Wײv.( )( J[ׂ*E.5 )ɝLB&3!$w̝;9Ax2ua|3F@@\;~6l`3ϴ5kĵӬ,6w꿳v*/ՇF@@*E_jY}Z5Ld [&&-4ے߫q/fG5./(2ζ'x~7ۜU`{j0˭[13Olg3l]v}Fۖ-vUI'uS|h/8Uoڴ9$jAyk   @e n ,5B]l\shG][+u2s?׆ENC9ou/~Yf[sϱױ`[tX_7_}-Y$IrrמvaZRÏ@@@*Lh0P0gKv}hM[ɲsr}5%XZu\l~Ze~3+|U.}C%Zxt9U)8OSom>Q\?}69xUrߖgng}fM}'O}fb]'33?~gӖu 7|kFMt 3ϰ/df?ozmv S%x@@@ @DINUڙ%.6V$S篵{ή>4;=:_jcf]?~c]PFZ 6Ghs6۬CZPICm]ǼyfvH Lxlyf[uٺL! |6nd'O3gβε=< ?*Pv?hkjqv8^7^#t̢ Úhf]\@j[Dt#0Ev1Gk36gN[[ze7}={7;Dž,]f jWDi=2ßyeNnv}z@@@,@@'ߤv72,#eWKVtǵ]MpIQϒ:SSka\8\P')-4H%!%z_Yqu?[K\n _נai?  ν{cdFKf}]&Z;1n_*Y&شk4'>qǟcߵaGi}b.//RSS=bm߼l:>(cH}.:G]׷];9.C@@*8nKjJ(t{ o`+j<'O˰9(k:Ula妠2o?W_vmlvy+Y7 99K{|k.>(#㏧B[CCvbӣuիWϞ{y[b/bXjj6Y~_'|f8.P1!>ऍ`9j;u>VkV[췭+W \pt?sVq j͚5it;w@۩-_O-rT0KŨ grw^(}Y:u}n @^|aڭ=1dժ |loոIc9@@@.@@';8TVyKHHiY_6ds-XgdJ(vq^m_[04.0׭26m~[N(]JU%W`8ht ^?mZd;M#7լ3ҥ ]&IsaquqAVV-V5#3~WS ?!y>f·~d.*G>b ꇳږ-=:vw+܉@@@ Љlrpj&ھ :LZk5sܰz.9 Gx6oɱ $$Uqv޼ewS UI&6cL?pi)nHMIĉM:v:תWG*j3r5tA[Q jnHTЂivZW5lޜ_é 7 Yl /S`dfdZ>W7Th%n{TpJU4ήJ심ѣaSٯT_)hMnbQrY uEoRz_W@@@ G(*[Xqv >355uB"O-]ɩmS}vJȲ<>3,z_ 7,)ZS@r4fn͚5 /dz qR 2~mׯ,:ej[T[%2&pl⻡ tkkq}s׽6ݨ^cZ5|#$WGESp/ C[N6e?dHe.CE8V_LYÚTXMY.A?woj~ioò}#<&O(5j輂Y"YgjQ*}YYQk}mx Vkй<ѳ}ͷ~Țj$>שּׁi#ϑe@@@`G Љd%V~:Գ]k&\k|.j[ۂ%rs?4+cNT@XrkHLQW_~: L j|G8STSehmWpW 2j̘>39žYrrr G3>M~jTaF];5e Y3дR\}yfpy+55nϛ VxÝ\ lu ]\:w@SEMJNNkERUnrߖ~۠eh~y}\e5M}``r3]DKm!6g}_9)~_   ,\=[&6J͇S?xN;p l[^x̕?ʉ{_ezjk[#ؖcj٭rQJCUTZ,AƐ ?TGf=M:\%$ەvYY"kh\@*bұCŒ53{n5kU|Ϡqn;C$~=EC@@v#O?h"utJzu˲IHTN-ATNIM/Oh޼ѐ֦֟v95]aٱ;*nQLsAfp"?mg3nmC@@@% T݈ĶBʤm+v_5s R ϩ--9V5{)nZ谭פaUμfmɒ%~ @@@ PplFe" yaÆ=(,>fҬZBUV-?t\^\7\A@@@ Soب[6om@@@(,"G@@@*褑#T"[lk    P;A"   (!W ¡!   D(I::DĐh7    PuTFqO i@G'tZ7ur@@@@TWXq OPL::ELrr"͵iKֱ@@@2s'QDqOG%Om]';;233mjwHy-3{[6    @0+e(ӼvU%%%Nt4#ȠNVV(0T9.W   J (G(;'`0<A*g4@@@@* (9A'Gtq`=    @U8kЉ    ] ѷ@@@@r S@@@( =    Pt!    SZAG@@@YN9s8@@@@tJ+    @9 )gp   V ;({Zm   T6IkW.pr'I?@@@@ (D:<r-++v։6@@@*@@NRRINN7TB㠊뵍Es233mjwHy-3{wf    @%dֺQ"ݚ7VēSe(he=2u9(nbVAr     Piҳfb6nnvl:.:fnCa4Jw:|   T-iK̾_m}diiiW]+eh2sh    (nR4SSPr5sfXB@@@$xj xT<(ú\#}@@@@ /PI(M\_HŀhW@ClPqO3C@@@ 9*C U.A8C@@@J,P.C\K{s/@@@ ìv/lg1   @    e/@@9    ]lWNv   7E̞[ϵ[a1}Y&fee=w oWSyWd؜TS@@@;|gV?HM2kY BaKڤf[Oq/fG5./(2ζ'x~7ۜU`{j0˭[13Olg3l]v}Fۖ-vUI'uS|h/8Uoڴ9$jA,\5rjedf؈/Xݺum6Y㏳>}{Gŋ؃=Su=E_ZR.)?ÓÞTo'-~}?c@@(K:qv !֮ilc6tf9I ksmzh'@! {\[}JrrrSRcG};cUmժ5گ-[φuݡcŗ6r( ԩ 8+VM_C&Q/$au?eA^%&ew\ҟI^M͛٢;۫^ >*kzzM|֭l=|\[ǟ-Я4oV'wV{5ko}>xu8۴qM}ٖZm{}   PrE_pf lεmi 7YvNԹkT+mnn(]=Ol|]vxݯfjcwD ]:G*Gi 3v,>e(Fjgyu~9/<횕u:>Şj,oϷ>WPevuwa K. Vm,x}1+jll|ڵkmƍER {id5sMsE^bsoX_]`.8֛oKq[g??:z]<ұ222ly1  -oRt֚]C.6V,S篵{ή>4;=:_kcf]?~뇻]PFZ 6G(Ym֏@NrZ-K6-PpH҄Y ҥ[g?TGA_j |9 }9sv`83`茲cA[W#K/ ~YT[`=#nּE3R{gQ]]q}w_-yc ok36gNij?._Aw˯ٳg2;zw;JSo>{F0¾v4e{qZG 2ϵvQGZzn ժU;+8IMw&V1##Əo|OCuxŴ:ujs ZG}ݰ ]Zzvy:ȥa޻mwG}_w=.φC^ߕ`wswLAWyE@@m \ڡN,˰]-9/c{ai7EzRjԳjiUOIN~%sm|s}CA>KJIs닮+KCZ SYn MҠa`~CΜo4 +5W7~Evݵ~x4I[::?é*()O>=Ԕodڧv_ tWPJ?ʆQF 8h7u\j(qLcLv*U\zMih2C?T;I]R BAuws<y_U$.EwG6͹ )|ZO]Ϸ𧢚N/<}6ѱǶ+V}g~N0 5l߾͚5ۮwG[w~{྇ߐ˖-n5n Ѿf詾y={ؗ_~eoFjekO/6' nN4~tC;PWo\Zx?G@@* T<{ SS\ kK׹׼`N D~6{څGv#'99cӪ|rSPDǟp|ڵkwfO<9Fa}N81ga^˒ݷWx~^m/:JXz7 h?]qiq o ڽK5Uu/v<sM[ {ahqo9>|~edC}(j;up*텗9Z+[qA_ QZ:N6]ޔn3O?Ak/@V0l`W^f<<~g]Bpu>̳0mj\wۢV3TO? Vm}Aۖ.]ft8{}=̳>{}pLB Imc܎믍3YB t;ѧ"u-v\c寧'qv執^.smc/C R*J쬈*t^ ڸa{C@@ D'*RuVVUMS[.#%"e}eۄ?5鐷-\?4$خ!UMCRRR \Dׯ[>zl*4 mQSFU.|%iYCHvFњNp/m)ѺSn]z}bPP5ժ.쪇s=Ԫ]=_z .XNsM·bj:jfVO=Qg+6ݨQC>Wq'ڀ?QA?r˲wM_ҨQ#ueUCHEk>3\w_Eפ!iii7Kxyy+xuy)iVzp@,re)P C gVv>̰;oSQy Nnn-s5e-iR}SƖт`7\O?LAao]o 6UA2}2]&дxjL ߚB0_w߀_  Tq:q|6z85Sm&9nXU=q^yK`@'!) wR To=_nWSq&M،3} OpAKI)Wz;}~a:j vHFDD0-Q;ot-ot6]ƌ^O?~ ޫU_U 78[b-k0#i -5̫n<֯_^4JC23kp |sZJ{-D]~e:kc_V`f+ =TkuUv;W''|b~1}QXZ׿u/U͚Z|e)ML5b#<xmڌ@@*O`obM'&̜Դ{ s4]ɩM5Vס9_ ;|7TEì ЭGW+V)1^YnAd7E 2(0upXy{왠MpEyulMYGY;ʼQSm7ƍݰ/ 6 }Ե{W_lVՎ?B,ޣ ~4hkl"&O H3*ଦQfL6YBC0TQSKn)N5L4-0瞻8xl@Qi*#ǘfZd'Z-5{) Νl hy֖%*7o o}Ûκ>|Q $ؑ z|H\oڡ+W]3aNpA5lԨ>`QӾb b`f*T)ժ8RSୟ*[h 4Rl?*sT3TYˑM32nV+'(KW|t?cgW^~5w /++*Ÿߋf͚b=WBf>WM^ASFA^΢pٙyX0{cWswkU@L- yuT8h hjsQA>3\oJL唵)u Rl" 7C "" '%+ߵ}B@@Hp eKЃ/'ճa"?fu*ReӟV;9+,ϴ?6Wk[ƆU54*+c@jSs3}m_Sk7ĝNQ25k΀١YP\,96o2z+>=#vڍ7PW͎\=w_zpWF.cicV(AI%&FʎEzp1{}t4Ò4P*v@ /(",ta?\Pi^^x .ŋX+zcƎ~Q}^˗pזV0}ޅ>o 9G~^5}E~':ۻbgQuuT^6w\1(|aT\@JY9^:f撆&w`"  Py5{N:q~+ZzNfe -v!zɩ5M?43rxh矉kRSTӐ`zqM!Gi{1Euk ^OI['A:+>fOn+Y%ޭ7iG w[(6 fz^~I8XoST_.  WI}iݳß/YJrm+2ޖ9}]騑]bX!WT+7 0M C v"  @tSp3el};~װ=L/rwJЩii} rf*nZu-GyfSjP :o?9TJ|.ڵ~-336{4<2el   T Rf9aWժYRR+KL: dee<999^ Ir    P`qяs ::Hѫ9{}FC@@@;{byK@'8 'x    TE kPxO~    +}{>A@@@(g: @@@@ ) #   ,@@9    PZ:d{@@@@38C@@@J+@@l   rp    @iV@@@@r S@@@( =    Pt!    SZAG@@@YN9s8@@@@tJ+    @9 )gp   V %ҁ IENDB`vitalik-django-ninja-0b67d47/docs/docs/img/tutorial-path-swagger.png000066400000000000000000003421331515660254400254630ustar00rootroot00000000000000PNG  IHDR M8 aiCCPICC ProfileHWXSW>wdEf!2Q I aĘDRQhUDjD((T*XŅ2yosr@/H Ii,#@ P(dih;xM "$,BPq x@&/3 e*,Hx h j.Mi|<6(g rGK)zF |!I*( v2wCgg s.5$ Y>ٚMʡibyT~ÛyӣUq4+6NkJRʨd>j.Ppa; 9<+[XRK.)>7ʧ' l9qUmʼdM7U8)b*H .FhfS"ȕ fXF<"A/+P Ջ%X-*'Ei@ rbj5c"i^재04Ak'ˏdQ~Jn(Qk+S'i3s5E pA`%,0I{oc/| 9@ܴ!T>A "P ۅgE?K5O7-R[h+Vh)H]s͇%1Zr/KoHN #F#θ1g~COxL < \#tnMʿe#g}^1}zx =L ^0[U;9\g=Q)(e%UG?&׬rgB8F-ag9(X S5H%Ƀ~$TuR^A; EŅ Ɲ.% YxRQ,wwTK[0%+@`ѿd_2'wu;8FidAzpGK` `Eƃ8Tg1\r0 A+Zln(8 ~ep ܆<}5@bX!+⁰ $A4$A|T 69D!->҃G1:e4MB9 ].Ct/ڀD/.ڏLcb֘ƸXecrlVUb5X=  Dp7d\K noï>N0' <$Ba&PII8L8 wS75Hdp7sK-Cb?D2%Iq$>TFZOK:A$uޒuVdr9,%+{ɝ'>ŞO)();(͔KnՀH &Qs UziK?::U:tyG3и BE{I!tz!}~~V;Z+ԝ[۠۩\gћWWwH^>EAן_D~`AAR=   2| .CqmD4r4U3j73642N1.66>fĘL3yy~ш%#Gtxc2$DdRn{SiiJFӻfDfN40R0|. ͷ_4ﷰY8ekɴ ̵\cyܲNJad%Zcu71gUX}QJm6666mRmٶٶkl[m&ͱŞb϶ۯ?c!F&<:;Nt`N5NWlbY }Ʈ#㏴64q􏻎Z>f|lqEOo9uZSN]m~:ٟ"~:usG;r}υvK.]nq3䕰+?]]p-Z7od)V2p{w+߫]>]ݿ 퇂)}^ՓڧOD\modz~7}s?žI}//\W^Z.x=μO}d`҇?E3X08(]`\ɚ;=Uš{|mdtȪzR@==YKlO/ Ge殩""lRNfiT6 _<ZeXIfMM*>F(iNx ASCIIScreenshot&o pHYs%%IR$iTXtXML:com.adobe.xmp 1798 Screenshot 1056 čDiDOT(&@IDATxg;]QAQ{^AAQPwP,)ł b׫`EDHe{'d3Y㝔L曙,o9d˿%++Nw]h&YwD{ө؇      ,r*      Hy0Ob[5kR/0Y      @ )}r3@@@@@@R#c&z/ө؇      $%Z^v:@@@@@@"@0X_$@@@@@@8k,,//sR/@      @TU`,X!a*>t*Y      @*beZ= ݦ|7N{(ri];N{icۮ}Dy       7ۊ5{Sbվ·-eb'@@@@@@*̳t.u,obC@{i}Ի,T#>      QYX>m(W'%z@̝NP;P؇ @@@@@@T x,egg;j:=v5=Aotԙl}=| HA@@@@@@ ]l&6לgކv~2)% l a g/͑oɯ埕&8,}&2RC@@@@@X&[Q_LӢXZ7+uA !d7`PA KJJk,[Q@@@@@@~ F+P077 m(h_kS 15PPm#iaE }eK˦YP$[Rd@@@@@@NLdrzn|[S} D:lR4ZtC5`XP>%ҼQSZ'ZP/$@@@@@@T YR.(EE[*s[ pP߳yX[ .DՎ'dC}#|Bx4      kZ@QӋkYjfɱ% ږւYO9|܄)^*AS@@@@@@ CӭmMB'v)ƃAۍm- G~X(Γ׍3`N*BT#X      @ V4Β w_ srrnDkըŠ m1XRR"EEErM\%7'؂V&nk_S/^@@@@@@Xe"O+l݉&;`JA m0xMG滉eTTzG      ej_ڝZ ՠ- S}      @ /Q_PիW=4s #      b^-+Q;       P:v%L鿗sdr)-2')d@l%i-t>?     uJ ;-uh1l0he     Q+~,u`}EsV4]Nǁ     @z ւ |X@L@@@@@XC6?HJ+ зHSo#3@@@@@K6"< L P+7E0X+@@@@@  F2͢( *@0B@@@@@J`0 *E  GF@@@@sQO`T)e`t>2     @ zJQ/3@@@@@`SF0Uz(@0'     P2R@ <|d@@@@@:'@0 F^  fI##    9`02P`0O:@@@@@  F=eQ gwA:Qrss3L$|WrđԮ6SF+nRAZlQo?+,1yQ;q?     F#*E X/stw导9]/^5k[Vә?Tn޺2r}X }L5ᆱ.]'4kւz7pOnnƳw#=ܻ$ *oN\|r1GVŶd -70=z5GK|0nmlBPVFCFUYWvC9Lڴ։ΝΕŋT9!CȖ[n^e9 @@@`s7㟹k&}fp0`p܌"zny2mZqob`P[&M2z#Ӯ ˖.38wO<9A4yήFEUäSeԸqݣypPt6|:N|Iq#"w]i8-؂e{_\|z_XI^3LZC֤?1!eAZ5n_~Ih˲Nm[{'Vj15} r-`#_vx}2qѴLS@@R)@0U3fίgaq{եX@@@  F= ^z@]߅%rsd degKye 7ť"^\ S(̵6ZdsBd.XZ,}&ϮR774hڼr$&6bzN_DR+W+*Bƍ˺뮛tv˗/W8-arrbML93g!=/ݑ?&Nx(E/MCxwkiB['-5]^uO8hF-#A}AAŃ l'*\-w9H{}wsv2ċ/L#Ƹk{^lc# nN1f͚&vLh@׌淽rUJ&z0äK,uKGI/e^nTN5#xl:f]Yc6lؠJ oTJ7ײ%Kk~n}>;]6&ssн-6k=~u7 o+~Q5yaR ]W}-@@Q[oE}۵]oFY|ah7<,]-IvnLJW,Pj`3K* ?-oWmɿ39 Z%M Csc/XtlK)˂$˄9yW Xu`OF4|[o+|/Tn{JND  __~ tvf.]:Ʉ >uѥ])intzIq[hψvXl~Gޢ7;lV Orgu:k֟ܳ/ʯ&?[WE=}K:0>7L\y~CN;dg3ϼ`DB/[&-7liZk-,))W_}M>6_1zK9eMZigt|@-ZdG&{ﳧL~i:mScb/[c7خƩuXhч͝/-Znᓨ~,X<`Dm  )@0dh0f9a\7VɃ,&U,/+ :iz2*b1F k0er7ckK6#Aa|~z;7Օv6:c.}<;sZ`RP$3V7ns7r 3r2eʫ&Ԟ-1^;]z՗{;ޘֆ0J)X/bj0fx_m|uH0ۅj4jpћ\‹MLXp;gʙ&xU`2{aXva믒߷ g5{΄vq %=~׿;.8Œ/zg4Xj O_0^)k=fm:pKj fE}P-zz˭}dwU^ߞ=Nwkc-癿Ѷk6m6\s>CӿoKyտ_}y]'po3gΒ,> hwi0{Yg&k\rUJBziܸ2v3ccݩm9<;(zp?0   P' O)GmW)ר7K}hr)Zo׸yKhe𮤬\`oJ䛹 ~kVoM:.m޸і Zdh+OneBoxokơCie:n¾r]BхGsZ72>ݵvWo+ q;~{3[Nu^] Ѯz#O lVFz=Ѓk.w.^X:w'2qo\ԮjRyt4o^5.P ި:zINȳϮt,D.tآjoLbCޱ&>CK.*-C tL뽋>c +X^2M\khT5E}brgeAmQK$Sjr{? z]uؓa{JhYȾڴZ%rim ;͚#5Ch0-T٢_k0<чbjZsuzװ`0׌Aߌ^|usn}Ӓ9οi1xew5-[Ok2dyij*~,>^i׾3{kλ+=nDm-Z,guFs:Kǎ:^]b~I{?^@@@  /?WmP)-/./EփYRnzwsej3֠-.Kdl7`R `+UhP]k|] =Mva{yJwcǍ MW/r}c髆 ۚnMW w37*O}nԹwdKʙgtiq-mE=^~wZeyӺE~F:^؀R6ЀDo<_vYOf' u%\?Ksl{_apת{\tw_\jv>5{w8]V71M1MM}(+~wm%JkwwB҇x[zA^s!V;lwo ϵMG}Bv㾣ii] CA/Ys̕''     F`#d>+Z+hWt9Wl:%揕^0{mcyj} Jz 5$u}_CcGDzZo}d¢;X˿VnE]ޢ7cڮ4k&u]|>I2vM-U.˽]Vϋ*[XQXa7t 4o6^uX ho Zua-1&]޷VQӏzww|6]a_Ϲ٧]T[7(|-ѱankZ ?ۍݷ}Ֆ pYH ˼EVԛڵjn]̘f'yWǜ^bӚ[aqˢLo6k^] k<[`|tX_װab=4]= vwΫ\d־ezM򋯜V(;츽۶^3cvu˟{c{utnhN&®# @@HP`0*X}ȓuU S]e/qu/X4 մZkq+[nnK3Jw31]p^Ǎ;v*݊ =g3 TbóiLuE~ž1zӵ36w Uo_v-vי lzZ[iHC8Sy 2`P[=jozv?σ>0qjzͰ﩯K,/L˴ &Ϋ ˽%xh>YCrr7ؒν-{}t~7}| Â`p5ؽ L*`0 5t:Ď:閛wĘҿ=;Ӗb߻xm_\ipWdW=+ۤl9-\nmy<7ٳװQ?/^{Ԩ;iD^k s̑x}׋qG:-$3㝿˖-3:V/հbꢭj/o0^XL 3-~Gn޼yn+   K`0Lpy%[l}E2o;ݾ /vjx7oI< 1\P J05 j˨K.0zG Mh,qv`0YUKMN[..ݸ`0t-+8Z8ˮxӛi v]m-Xw@?k `{3O -uɨ_.L{u輶28ڄ{dܮEXk7waXk뇵^tWyul8?1A6m֏2[9) շV[l>5Y_ž !3ƹU7`/Ŵ +gR/J5[[9jWaE^7\Sengx.`d& tU7c-`P[I5@0)VI5C 9h:Ơm u-}6 :Ѕ]|MO5]pJZ!V0k̙gW^A]Wi.f"^{:Vimo0]jY]z}r:]x]{jKC;^hlxAmEFVZ0QpVmll    * ۖA[[|nõEJ.SE~;]ecSE[ս& |Xz0Yf}M}euW/`0؅=ohoM0 k sm:.&\`85}uj}͵W!fJ:\]i1! eX0X׌oֳ 5 ΃]|m:pqKTz v-zCuޕDݽSK۶Z #̸Z:樶ǟp~uôw   @eh0Er>g/.{.ɕKel@ juWę֍+5=l?-KE01tXſX<'=okh5j"E[hwzǘnBu쿜f~ y֭}]%j 7&?s' mq4Cشߧ-\E-ymv5- ʭ)~*j$//׽e0ѝ^UrA fm1=XQϑ5G_ugy>40|% >Ӣ-o%^6dv}~?lD[ ⚡>2 =C=Pz+[@}Z `0:fRk-^Gٺ^KZWg߽ s1j*=8ϧc8 {%V?[7ZϦ{}0m.cbr"-Ce@@VjZUy]]_]d} 18y'ǾyҦy0Jb`g\fj;\xiuGbǏ-12 l:"BvzuW{FO6i:71h0&uear7 :Fu,ԛ/q% v_gb֬? .U^?Z98. ޸eZ4H͍gEq4 !o鎇l2o%?v?r͵ (:GC6ZdR-/Oy;NM/W?kwj&tzR[zAwȶuzǛo\oƻ+cGL_o93v]`_;MW;6N2=kg9մ z?Na}[z^o+_2য়~.7vzs]5L7?Vnk#@Sqc`ӭKg^;hv 2ly\u^ZT׌xrQDJؿOlD/VT^L7?T4yoejWwh`pi>tE;80~+jLA@@ )Z:_Fs}+xUl4K6i-'R]A䍑׋b֥`LZYQ`aϕW^ݼ" e+~&?W>r1G87ؽOhSt lVZeqtv[qōhWXޛE͛7N;TmV;v^-j߾vmg֚zC8;+[͟/Jx7t? "Šgc^m@ BST%Ko.mޖOLM+Zvj׉>{s]v2]K(ӵ`[㩧({칛w3cXk~7Qswwk4]=.&ڪŖիWKϋuF[` Ǝ9< ۧ]]ozd+֋z,[ΗV9w_?NWm0;U؍xV| zn0;ﲣ87Žm50-_.Rwu}g^.5=ܳDzyƊ븶V;3Ls7s%o -xZՖ[*j?rzއHcbZev2-:_:C|!.ג5Cp.>; HzM|ڴ랷5q,˃jxj]Δ38VnןX!km[v29o6lN-fx1wGO߳DǙ & =4wZ[YucFj~a=x[zmJefQO=vȃq}0  x34T[29 U.J0XNAm Fz \RwCFXu#Veݤ c[oT7|MѬ]\E2SKLJ]xyQQ](Alݘ67̪+nVqnK[1QG[[xc7y;=،[.DEodnao,5]C&-:t853K.V71}N]cۊomwЫ\_w݊1Z&3=G/yNƽ(;s,W^ 7lkF{y1n݈}`71n#`P?,rƙM:o1IjHyK.Mz%k>,M*:&{1bc=fo3V9n{i |H YaT^3B&E֋7lL&ÇpWeZkxAõmhk׮!=1cԖB]z]-4hk8Ad)y ufgm}VnοoGo `~G'oG'UvA@@j @0-A%Zoٱut?hԖPo}wi*E+׊}'h1 _zy5[!Ƅp)v8t /b_[ h+ݿ'u.Vvװ7mKn['xZ?_MZx~t:nDwQnx 1&AV 1N Ol. 1uMk뚡ALfDNJ:Ʒ>ћs7KĨ%׌{[ tx~t OVy @HkwlxAyDžhZt|{_[1dGzٽhzO.M:@4*w9"Q;J ~GkPEz[|_h= xp{!wTMje7L b]Gy,7H;-uw"߿Q' {~Yw9ߗ-z,X7&2w=@IDATV   @`Jز KXL8ب [:z#i~~l|wD>Ҏg6tcis=GV%-ڵq_XZK"`[^3ǝH0a7oΑ[+.w>4۷=^^~RFǘ1orez+@j7acj}x޿IvHfCazz>UƪH暡G]ﻞÏ8i72Jhuoonok0q94ںto}TT?/"чx6-cΝ+I5þ5ݯթ-kR`|5]M{C?᷍5wMa3k]-@lrҮ9ikB"X[y/v[ma mчvv}@@H`T D -r^5r& W.yK_V1n4]OV-+͓rפ7M+d #"RФ`]`o[ᆱhLs̕y˪Z0'v7ۭRh:ynݺȩϙ3OVZ17Y V6ܜgMZguLb;1hxp?qiˊ&f A7w~Sv_sMx\WT{\n}'ҸIcyEC?L:~(Z[=׋~Uo287NGtB#Ƹr -.tM7mctR֨]t6W 4(pe ͛7ϩߪU+kAH;J`PǻVQJm_37xYSQG_s߂qw9-[u,GM}z>زtdMZGzpѿ#Ϳ f{zM5;= 8;k0\!L,+VM<0t~_~؞}(35mkeħ~.}\$8ީvn.[{LUwuk.nkCS@@@*@0`02P SAm*1ީ~ wOoC {Ӯ\ 11xov޾Ѯ&3w?e:s :@rs:c0C%=d]*\;9CnQ'm>p |hQJ"cncL>:i,!}y@@@  F=Q xpHg#W_CtLG'{7^nq?Ul:mӅh>rckL36fϋ<(ia=@X6P67㞥SIN=_{S]sZ[s}r۲خgw9,    @0$ F^ dJ0UY.E`六fZ?Q#ܹy'˹ۉ3>n|-(o*fL[3Nc=RrrrҎgʘϿt].-/*i={-[i"O:XY}E1*9cxhxyEb{se]wv1   Q3`T)e@zj/^"-y7n7Lc4+YF|&h馛e%fLYt7m|5IXϿ$;;[ڷo˸IieeeθҦMk׺P^؎s5xbvvlIkiРAX t2ڨQXX   P`R@L 3@@@@@`I0Uz(@0'     P2R@ <|d@@@@@:'@0 F^  fI##    9`02P`0O:@@@@@ `")-8Y!Lސ=Ksd~l|(@@@@@@ GO/9K+A峤@fYc߼t;,@@@@@6[cq gYR(p9o]!     @m`PlAODh-ȷ@@@@@#PE+/KdL"O s4o1< @@@@@45{|=L,+ҊaѭYorLزiU6݇۳C@@@@ f K>뗈υ      `D(!     `B0j      i)@0 F      @Z  F<-      O `D(!     `B0j      i)@0 F      @Z  F<-      O `D(!     @ E dVBY yVb"      6"Rϗ<͕FrD/Py?"      Jk[4b ojr2/@@@@@@&g˖^/K`X+ѻo"{4%̈&@@@@@@ W?Lx7JTL15h1DJKd @@@@@@2BધHvNi1i1WK0_M>$      @*"<`Ezw ޜ`0      W> o8p%`3o5@@@@@@Hk`0"@@@@@@R`0i!E5@@@@@@ xZ#BQ @@@@@@ -#PTC@@@@@HK`0"@@@@@@R`0i!E5@@@@@@ xZ#BQ @@@@@@ -#PTC@@@@@HK`0"@@@@@@R`0i!E5@@@@@@ xZ#BQ @@@@@@ -#PTC@@@@@ P^^X,u_.fGwuFhTC@@@@@ 00tߔ"P޼(t-BR'=7     )`@}-W)hHYiF@vdolm/6CI #p2#~!     Pk&?&WkŎXy 鄃%{D0'2Ǡ     &`2)u|m;F ]rN{\,n@.<Hy0,F@@@@@xC ߊЖy `į%`D(!    dvj4-KU T:NeUV^o3%b%lԗtCop5ӮᠮOg`0"@@@@@2N,--Pfܷ~` WjS;JNNNv)J0{I0j     &i-ho]{J;L P_RV~8-ZJ}`bA]^ `0k@@@@@2SnDKJJUORt5Ojp՗T~ɿ^M۱ +OW)2@@@@@`]>{{Yyz}^@@@@@H?Ga  V w=#     6is*8 @0XN0|%     kZ`pM~$@0Xq6[ɱ      PKn`i"_W@@@@@c-@0XqG@@@@@ `$&*SK0XO|,@@@@@^ 3M`g|0ҔdժUq6V6[m(m2n]V"      ^-%_})efJ?tjP46I.In-Dtc*//KyY{"YMum`e|0x d˽ȅ=z3B^(,t^u d] &@@@@@ dR0Xj()aPv%m׭d>]㫮N`0` Ovu';k ƎL&<=BrW2     I SIhLl<ӂZ*\"ɕ\)/cf%z5 L4i8QsW#@0X @@@@@dB0X4)p tD_}lֶFֻ)%x 4%M{cwwE2}'2Oevګzʱv9  &     @@}We}).}|.4%"Ef_/<#b/o٤4wQN sO0$ d{*o3[+|;v\2믹92:ͤlA/˵9hkR|gݨQ#9ģ::c#1k/DeדviNYdXi&Y7…]Mef͚Xw(˗6mZWǭP =~DnFܲlҺdgg{j`W~]wءʥ'Y~3s{˖-uwiaengy5c [˖s,|A@@@@Lfs6m+.JLWRd,Մ1t)=[J%sfuו[H;H,~w9bݢv7;7ͷ֛uC'˥l\))H-$3wمKHI3Ev976I$*$kz`D {^z|k1[sWvVi;.y4lm1[_ ;ݔy\m˯;5P0|$℃BDF Y'yu0:-wpBLogWj +dΜyr}0̮W=~7]kBHs  -G~X^xY=/.Gv.c\w%.nc|uGfK:|<ܔm< }ot=*jmi+r[,     @`dؑ>F^-:ce+n!.[OEMA}&}n~7JEq$gNoN /3ci 'Hl0xکZbg^V%9߮:O>vOtjں^8cُ>{ 5~m&e/S! nw>hZnV} o[m, :9#D:9zT%cm va8INկN.smO:hǴش{Oƚ֎V' Q2vcʧ4;pʊ&z~y`Ee-; {aU7O ?8N'ʋIÆU{@@@@@ւ@}d|ѧ~Q+߲3͖w40Yv3je:з#cOt  NP"ѴV\x)w>CvYVR8{Xp RR?#ǜ G+˗ɲ>ZzuדO>/= >6{MD}e FdO66NQl\qis 6l]иI˶ o%﷗'u{XxpժB93:O0 IݾsuLz\^C^^.32jDw^'zgÆg{]O?,yy-unE<;y;4ȓvoBK d#,]t꾱믿wi@*ڮSuA m9+@@@@H' 8N?n:`<3_S':;+B7]~Ko)[#oץa,Vy/3i-6e,e溫5kj]R`;Y;i|u/)Nz]1?Ԍ8WѥWK[ T `D5 ڮ&43g̝7_=G{і|R]0xA.VW/_aZ͑sϿ.o/fGn<5o)4O)uvyPPA[f|}u^_} 'ػ׭'vm'rVw^'fgV'S`0 0.3.E[GϝOwkҎܞy@@@@@ ]u08a k 5I9R|)3c||Ug7"E)bW^XNQ RR,"RAEłˋ^T:(ݽLf77;sL$^{ ˡ`̂"}>5]iii\!c:,Jtš{I_Z¿l*u$_x|(=wgڡf7q|f|R*>b*Q 4T?ZJM$)1sW|Vơώz:TEbuo_>[nn,=.W\ $ݡoO!c`yNԩWr硂^#V0hW䡇 KySqO9 FRȞz:zm%o]/x{gdE}$EUӅ&ʕ4{׷4nt%`P?n y'ǽ/"߽̊U&rW&@@@@@_`0훕bH=m!Uh/2e%Pd됟"EDOm cxxiѧG%ic}5&tI옎>ACzN=gN;fk}"sDUSyg݇ _yP^6}Li}w]qEr)'i,4Tr$;v[TFt08c\:Fo)|gYj;vr@@@@@O9%;IwwI_R7w ڝj¹S%v]I#I[{e0{3~zh4{mDW `2Suwڃk[O0AC FM:P;we}`0:5ҫݒ`]+a3zH→+/\\[Ҭ ζʡ^#zIQpt/Zt۶?W_' ԱKn@@@@@AEkwVۼIB&g}'%ۯζ^)0 -g:]IX߃(QMLÃ2U{v/o}R%NSBREIy5IY^f 4KlrCG#L5;sΔOqU_9m&ܷo4s2n09ԓU?l# .gsq27pt'k{Ӯ4'Kwѩ5l n.i0}'~c.wJF߯s     GQ@5w=ºRx¯Nf R] ) lSkJCXm  tip 2rwޯUf/y 3we^%JH!D?"iiN3Βb:K38zĀPX-o~u*8$IT6Q$4?sEYW_2ǔ?% ^$S_wWmc.k*4~;tOV˓O2#C.: ~…>tq͍g7"QrշDF"眭~\Z7޴>? wH[5Ɋȴ/^t3`P[PPxq)Y` k5or_{| n^:Zڶ_v;     (zg^LpOd}BO;)9%QQa`GCv$ĚTREnE`J_X!˳&J%'ǟ,<2$'{ԡr{ũۻoAY5xcqwȭ-U95[-*FN={wp%'ՂThC@@@@?`P;JOzVtfXovP޶EU 7c~ :1P"M[*eVƼը++]eM1 ˚@0H6 j&Cnin Luٲu<5r{wʲnoO۱c4kQ^l<T)[ƻ2Y*y,hYKgTVU',9_7H.mcsԈG;}3oWS)T'NzzvPyu,|o)Z7of7Yv075>h A|1r      n-,@01:~*@@@@@#<4R`0c/7     @sE%@01뚧A@@@@@ `L `@ /x@@@@@p  /OO0@0Xؿx~@@@@@B!@0X(#@0C0 f@@@@@ `AM%b9ʡ?     P`0gy%ʼn@@@@@@`"såF@R E &{t|`$>>B%!!A>X5/ &$ʀI"E$99ٹ_}*`N     @>#IxΓ$~ E oeg V$>`PKFua B.i*mMII'?- ]F6/|JkFuv3/Α؉     @>^_N?ƫRIjԔja j}Khzq TUْ%*~oݲ@@@@@## UO_%4u8zI<B M@~ԅoyBA ]zHN Bvb0}+p     Q~8fԳ|MB/+@@@@@@  B @@@@@@QOPT т@>ɉr 쮹]@@@@@ (E(6 `N@@@@@  Fq FY p0     H`0`0 %@0XA@@@@@ GQ\Q l(5<      9 "a@  a@@@@@ȑ``J`@ '     @@,Pj8y@@@@@r$@0h { @@@@@@   !@@@@@@|)@0h8,PtC@@@@@@ /-!PhVFrʋs:/m       vI0!Q_W)"ɒ( V8}_H$ B.iii"×~W%K8HXWs%5u{^}>@@@@@@8*@0 `$%` ʓ*T  , g^zyqXA@@@@@@ 3< `08$9@Zwj044@IDATb& ˀBbP/Q[W r<      ӃppjϠdU1䯩D`pyiA&Z^zCE8@@@@@@V͠TWŻ D//AQ`uyUY@@@@@@ ]1h?أP{iD}Y1 A<8g^T9qF@@@@@@ ڋ+&:+K@ |2hF7òvZ˵ 6:A S&RRRdwԯԭ[ٞ\9s=ʼnRbg@@@@@sAC5k֐q㟖U]^#?ݷiRZlno _ҶMG讻;x* V@@@@@\  6ԗ޽4ϵ+ z8@w`jJլLKO6Ȏ;QOJOҞfzYl2ҹK\?ΡA]uu,J1      ACT/N(%Jpj ֭۬`Pʕ+꒘>' BD^6n$v-Օdϟ;Vl9تY~SOqf?|r5ݟu@t0]ѦoO5:{}z9ݲelټU-"kw楧dӦMπ}{IwV\>mO@6l` (*KLLNvרgJNN㎫)iiiQw,q߳f-Y;蟁ˡAk/EW=&\aQXsڋ֮^FRSӤj*RRE      @ 4Ƽ5EֹjvE): o$m۶nө^jܸ_8y7@>K/+֭W8٧oB?/gL-n?\?Q͛ 76v :{~χznnxS?{sʽ,i49VXhBzxE};:wdUcM)9<:8;uIY<@>I0Wd'z]ru~ K*E[ߛv6;8χҪ|[xӮϩ^tH+K뙱#NZ֔`}^i0}|v[HmdԔ[ow#z.X.WӱFW s_e̴OpiHbBz 7(DcϵRgfw@@@@ȷC`I5M~ϖ{ LJ=,zxIk^FzRx'^ '{-g< l| rw8۬ r .xy#t Ҭi+MO-{{ٻwڼ)5U71>A{r'JR$-5:.*{zztιtܘ1OKqРGsi2E?-:pt/Yg)>6ȹ>~{zRZϿmeLiV[MZ%z5     @ 46&ݗ~\ t~'w߃N%W+ N]_~B.].&tzJE}Ý]%suM]rEȃ/oP}vӮWth^;s;2ݏu@NA]uoWnRnvO/{HwxTRxsDW_@_P*Wdڬ弳=N7i]1hU34ӄBԩ3y󝦇ϗS?gmo qSCSOvίW~}5^Wb*oߞre˝c7n$w&t(XA@@@@|.@0h8y K=1l|2:{B9;4:k_v wb) epkCbG F2>W02^?/9 {AAEWi?/hW$ Tǟ0^ߩ%j@J`0^i08`@_ҋ+|<=MOU N4U^9Ϗ59z%WwׯW`pP5Y1㢫5      AQ̫`0aubJgwjʥ],'z*g0oĉShܸ)[َ^)_Fa;_ a~h=;g=jjxK0Z4AGO5^3gnje-֔;:wdoa=eSW2+ytL;өDb`=R#    @A 4ݼ fzY^R;\UyvI`P=*;}ux宻:M7_ouS_֮5ST]X/#CMo}XW g A\e*槮*x?*`L&@@@@@ ri?5TN=,W_T8iw{vO?#=Z ϗ]:Iv/7ޜA(;t*t{5>Dƍ{Zj>A5u+u}_=a߁^rw@b=8ᄺrmëbMX}N8Sgw*VEW>Swwuu]۶-ak0Q=䪫(t<0     wA"4J Ag      Aá܆PtC@@@@@ B @@@@@@B0hE7@@@@@@_   !@@@@@@|)@0h8,PtC@@@@@ B @@@@@@B0hE7@@@@@@_   !@@@@@@|)@0h8,PtC@@@@@ B @@@@@@B0hE7@@@@@@_   !@@@@@@|)@0h8,PtC@@@@@ B @@@@@@B0hE7@@@@@@_   !@@@@@@|)@0h8,PtC@@@@@ B @@@@@@B0hE7@@@@@@_   !@@@@@@|)@0h8,PtC@@@@@ B @@@@@@B0hE7@@@@@@_   !@@@@@@|)@0h8,5k H7@@@@@@$Pn_? B @@@@@(jݡ{5#/ Izz/55U//mu0s>9ǻfK      GBACeAC(!     R`pX       KAa!4      / `n       4AC(!     R`pX       KAa!4      / `n       4AC(!     R`pX       KAa!4      / `n       4AC(!     R`pX       KAa!4      / `n       4AC(!     R`pX       KAa!4      / `n       4AC(X cD~q\#7?^$4 ^#q,     T`p` cȆ$4gu\F- sИG%j""%Jt     > 4AC(X`0d     B``*+_: _7guhDż;a}{U\ @л/z+MUEyD)C!Pz>t՟I_9̠     tA&4E=$] %+`&*p\-)^BnjGmoIdz2%p8ӦW{.u$p%2ՖСH0AŸ/U[mˮI[?WKvy; -/-%`VS5ïΐ}om/>/?Hڌ>:vf/# KYm"3,^ 2(%lD@@@@@  .!T.e0Շ+[wcovpV F֮kmB6s?uf<#`U(ᅯK%QggwNо*VxS<V?%xV0x9{%Po`=yfMtw;cЈ     @ 4FACt,K%WIN`rDT%KBGsrfquE`P~zPTX8UUSHN{$&JhdNq]}t :Q+=YB;'TjUIFڃIi[k=$2R?[%}ӽ 5XG@@@@@`  '!TE)i1:"y R՝-$+U 9:K[݃~`$lvpsKe%4YzR$%l;UxKk Tbkh/kO?[n*^Pw.gT=iOB0P     @ 4RACt $H5UMyQ_ O>C7wA8H}f`܋-~w_}Ua' ޔQxjyTZk+P85%D^&J$"_߱xOg/cw  V@@@@@(pCj ~ײkߞqRN-O7Νڛi"+W򴥧dʯ__]vl!*VO''ԭ-Ԗ%{_WٸilXQv-ʗ Kݺu Εcgժ_d:^.VSD-\Yg-hwKI$4gތ=jz̄&J.WrUzC}zA5Ui˜CB)ol[ -SN<, {ḥIMg0N T\;4io Do[]'*zҽx"%JwHK9 $==]퉸  @njDI.Z\(-IE  x=7L#Ȓ%{NtȐ!zڴ%H1q9dθˆ 婧F5M1?u,dٟ«_%_e_tCfH;d9ϨQdK<_}%liҹs'gP+$u,`s/ꜞ`%xy!Xan/(_I"nfJy̞v$J.￲^g]pU71'HLhM/᷌`TrW%<#ۭc. aqhCԕ*c[0p;P$t=>aMŠCeeȾN4   K#eyxjN  T`pcm]b X]:@+ZמNWWM{q}2y򉑞>m4oe߾}ҧY~=k^-=ztqC ^v%K=Q0t<7 ڛƟ?~+_]AٲQd𧂚SN%.>b_~s{+ӑ&\Od:韛`>^s7Ϣ٬@ٱMB_p'DՔz ,6VȺ&IQUz)[*UJ)z-  L@hJJٳG+c"zlj9;@@@8q`MA=`=rн̟L4$-Z6m[Zm[:v\bl 4@.0BnKse+!10F;/V0t$]͔Kh$-ej9gG6+p.U1&riK#[7JxɻN{B{;H蹧*@jՇjJG z+KUp'*\uQW8U{/~28R"ꝈzSιH=~Bw+ԹUV{{  @8p@l"iiiB`ޘr@@!4*0 鞛0Y,xsk$]{ƍ%jg{ŊI*͘1[vsYgcCմ֭2]Idݺ 2cKYS4>M̊Agk%'*34lcIo"󕴮-$wع$!uCf _}B@^lt夓ȧ{we³rz cRTur|r`AA0ۅV@@#+@0xd  Y`ptM08ok2mL)ȸqyg̘,ʗsڦN!̛lZʕջ ݷMۖq&1}9l9n)Y<O?qGY9mDo G'T>  1 @@ @0F{D@@  ӿ 7oޒ2K/4/+u֙ζ^Y3zMW6v7xK&>?MO3Rb}odC8z`F! ,## > pK  SAÁ7>u{/*zui~~5P`F/*WNCr5f2j8Y.;n^}C^xEO?AP`: P`Ї-!  O &{ytk*OڵKZn{!W]uӮ=@n;K\+=&+V{iϿ{޲kN^ҹK'-VXاupX)rXy(@@  !@@`Pnmt{ /<_seyYJs=K6m"_|,uÌ/Hrel׮TZYVEfرGo4nPvN0PRH @  }>@  H`pm0O?p#ob^irɥܧEأ{_Y~C{*6ڽ2l؈x]m^m > `ai@LJC@@ ?  Vn%K>#ļҫ$EO7[A>{ӕ~DdРGvR>Xi}+VL0Z*Uhm zx(`yD@@  A@@'`p޽rkYԠҧo, [ e)ѻ:uk}+5jTw=Ȕ)eѢ&S:n}zuvn6mZXMc -#zjS `AU @o̸c@@*@0h82 %zao=W{Ar=mmƍEl")-W ˔9&C}7n['[lŊJʕKrr!Q`0:ό O`c!  _ G.7S.kt7}dIHHpXA  k<@@  ֑@@{@IDATACӜPH'[̞'}J-[66m[z@  k<@@  ֑@@{ACӜ_"F{)Sʕ+8G @@A @@@  %s .Z=>ٯ->@? @(yyv@@V`3AncGJ L78ZGK" #  @n r ._‹.JUH妛bŊ^n p4>F@m >@@@ 9  OK7[C@ `!l@@,@0hL0hE7 `L@xu@@|&@0h8 PtC  Q@@|,@0[G@@gB0hE7 'iiiTbb(Q"[5w$)^x7o7J(ҥKK:u{NKqݲaٹs?ֱe˖jժ}F"Yvu?zW\a?  9 ̙@@@ `|A  3F6md)RDyg̠AVڵkKΝ=:>}v{nݺҺul?C~m駟ò|֨QC:|rY^xL:Umt>|   =@@@ {} ( ~駲`ǪK.RV-g۽Ǝ45o\;Ʈ2IQ)IBDD%)-J~TBB*Rief޹w̝;w^h{|w3dNӓO>) u5oȑ9uPfM^G׭[LT<w}Ny饗>Ucڵ_%Kˉ.YDΫCCAu/j#@@ _,jҿ+@@@ #Ct8@t T0x Yvl9{L|c:uoר|ګG uY>QFrM79+VZ9N>?-\S %GUYlLJun  @P,4"  i  B (`pѢE2eGo߾RZ56o,j6]T(AURǏOɭ*sSw̞=[ΝԬA5P} UhDMVK>CNӽ+*Ur`ݺu{y@@N_`@@=BCp`Pm?_ͥs~eDUB;쩢BE. q;vQF9niРK.ŋ+˖*|GDݏ  ur@@8)@0h'`nD@NiҤIxb-|'ˈ6mT: / ۶mdks[6mۼ^8p@٣Rg )SFן    W"  G`HN 9 ZJƍOT[l_|9w=HժUZS:<lv9_ʲet(xf x{q@@ s}8  VPtC r:|2l09~V ꫯ3gΔM*Cwy_|( vâEJJJs*`&@@l Fn  AC(!E9 *ӧ;tM-{VZɕW^(,W$%%9OuPfMQTdԩ~ kժ%+VYjyxG0Pp `@@P B (G0uV=zֿQq/#B@̹˓O>)M-Z;OxG:d {މ'vK0Pp `@@PKryX yꩧ}ZleDlAeP;v^Z>YuRBQ >e*\T!c|S  @  81@@@  5!"p_}̙3G˩U9|T{?\y:s\?|NڟdɒgygnݺIz`ĉd`С@q'  Aá&4Q$`p2bĈrjF_"E2;z >\ 6l cƌqU\Yr>U7n,7xSL2E/^׮e<RuJ1?@@.@0uC  ' $ B (W0Ԟ[lӫ]ϯU駟?tZ *$͛7hzz]V-ZW;m/l۶ͩ%F=\QRKZJRRRA $99YH0h@~7  WAÑ'4Q$`>OGPԩSe…p :s7رCFn zB'?R`AA?*  @  f'wC@@ ?  >!"pjiG}+\eDM޳tR;𔮫nЙqqq9l֬lڴI^}U}#;1c,X@7]v@@ Yr@@pL|w,5pfذar1t饗J۶mRSSe֭qFٳg@TRth WX=t萔(QBԲjƢq.;|_^ʖ-  @ +7E@@ _  ;nD@8Ao=:s8@@ȷvp@@]`А`nD@8;YzjA   J`?   ]PtC r2T{ ߿_J,)/?ؑׯ})  (A   @v  J B (`p…{eЪV7C;   W`0=_  @v   B (w0XP!߿$$$D"  U r=  )~ :t[ٷw'Y<O8@`pڵˉ'tRR%iӦ^@@ Y  DD0.,U'nk&9c2ٻg2TZ}[eF> X*kV+b#Qq.9 3x  @ #  Ae77%%$K[oe&93eEAi(mCߝ0Vv)\}Nd ( =' 1>`rs@@CAC(!  )OItCv*D{oxIKKmѻ/a&9퍗Gє&.j)ķƾ"GT;S5kOPPO 7w؅:a  ;9D@"@0&@@8-AC 2o6Z+ZBmj6*%ڷoyz)PTTEJQ&u趭[J%lB9IPX/]s-R̳zYP傖nsdwO(C?S]䥑OUU~RTi}rK`0y.  [`Э1  dE`P/XT-̙,wrcG:mT3些Y /'۹NPwҪQt[Vϩq_tz_v$7hCIHR::t:X)GȘWF9MAgɵ7X6|J˯ B  !   C3  kAC~9K/E?clw3P ɸfB I;]7o &Cg*Yz~6d辇qBEwY5cwS +=,BMUK70  !   B#  !ZVA5n].iV{]= ;@OJ6}f7Ҧ]GPWׯ]-O,}UT$Yשf8oH.oA_z M|,[دRjr9x`~W9 u^vo)ZԮ  "   B  ![V/g͔,OSPOp'S{.\W;sȥm9ǏK\ނ)r~dh|| ywg/HĹF-#onN[5k ^v)S6ABJwykܫֵ{nw˕YNgׁjMqgR-ܒ  nA   ACAjՕ|ۭosKH;=7i&_v>f.?Wm΅`!ݑÇeuzz{/I(CLF>]^mYٽKev`4/zQE |I  Cp@@WVf|<ˍ]J3zo? R7e />uZY˒6%]WZ't-ٟ+P}}<>80=R;S{*nT߬.@ ;E@    -@0hH`нI6)n*f tR-KKMcdk/8 YWuU:vyUceάOdҳ. In >Z>W2ҽg ׻&#wMw_1-@0ݢ@@tOGk@@@ `0 mY ?l\V5T(~䘗G9{K/R4n*'0𓏦ʦ 5kו"X"+-{I'U|N}wl߶Eb]nV˗eLU)R7H:x@\ZTTo?O>*kV~j_@h9tKn m]mc&.p 7들$ry&  @t|>YJ1XFt|_  &@0hHP`[ce玓ZfS-ڏ0Ɗ-.%KֳL'kWtNM('g$vQվjQwqy=..gIKMu)Ĩ{e~{^pQ+IYG}{3wNήQisOUP 2rS`*UV… l@@|*VٸqglTF@@ 4J0ɲ~y$r%2l@O \.RDw]5VXp~]?f6n{f WA&z?|' :s0B%)V,ޙEHb%yvR-x ц@X))Hҥ%!!!a  (]vɾ}h|I)qF9P@@@,  e%T{T ܇/ ϕN7Ϫ!kV.K( 4.jSZ Qd_ts>$TGSRPk~*+[49T~>ϥV_?5ïMן;f[MK,׮*7v嬖#=L h@ {vlҏe`y  =[PI)_E b T   @  }}v랁RX1[u T]wz@'c-ӶǏ%B *oAɃxY}$VS]y&`,`*T`IѰ @@  Pp۶mjmlgG@@ ; 5ʼr5]Ԍ۷4kƞ_MVz ,e LUpJ^fطs?E-+Zxq-8c"x @@|r5:U_UpQ)]Rt| _  .@0h8Y ֬^!|8U?L\蔔#2Dʩ% vM^hvYj HgF^  'LS@@ 413>|O֮^x ?ɗf`?(!w}_SymK+<;՞G4@@K F>YE`Ob>    :dG0/I:Agog3ĉ^"Z-|b rÚU+d?IfHjO@@@@@@n      d!'!@@@@@@"R`pX       B0hE7@@@@@@ 4AC(!     D B @@@@@@ " `n      )@0h8,PtC@@@@@HAa!4      @D   !@@@@@@"R`pX       B0hE7@@@@@@ 4AC(!     D B @@@@@@ " `n      )@0h8,PtC@@@@@HAa!4      @D   !@@@@@@"R`pX       B0hE7@@@@@@ 4AC(!     D B @@@@@@ " `n      )@0h8,PtC@@@@@HAa!4      @D   !@@@@@@"R`pX       B0hE7@@@@@@ 4AC(!     D B @@@@@@ " `n      )@0h8,PtC@@@@@HAa!4      @D   !@@@@@@"R`pX       B0hE7@@@@@@ 4AC(!     D B @@@@@@ " `n      )@0h8,PtC@@@@@HAa!4      @D   !@@@@@@"R`pX |wﻯOwiqYX;R3c[^.R`X@@@@@/#M0hE<'۴NSL#ߐp8gH>!     _ G`nyN`0 /     i   Be_-Ç8wƍ:<Λ%+#<]%1kdEӬ2 IX1Z5x~+bc3woPf 3`@@@@@ 4#4bɚksHΝohQŷgs}wV.sq۱M_*-x%1-[KL*N:Pz.uӴ~Y t[l~"X~/m1].X~uu$tm,ޙ붘JUsU}l ^9jB߾='/ZLbrBe}W3ŷyɾesi;ΘR6@@@@@AAC\ACݮjwߙs3<צ*  cʋ TR5%I-؏knkS[$}HlxgO9Oih'ċ~w ੾;x?%sCiKc B#     "@0hH0h[`0Xnmy~  < iCz2I3ʙ1XQK(>+G%5wRX3ZWˇZ%|Ik-c™S"'Stf٩s/U)9 :7$Ց^u=5j >+:=gϵ]qqHm1t]#     P!Eb0>>07H=)X&OWswYyu8ikn)QZyyRm}t yι !+k E?g{mg}UC[z9KeO?}kwA@@@@@]`А`*DH G􏧄xc&Xˀo̤=W\}rU1UbJ9+3֯˝w1M.GwcZ3^}Ʃd0eX\S\]|~% DO s^9J0 G     d ;&?|r7gU]*W$7nys۶ɑG$\e5/XT%==]֯ ˗?KN8!Ϭ.X%'}2᳂ u˺eժ5r9ӺǙgVjժJF l2Ao?׺]Tݳg+Ya~x*JJ5zM'x+ VTQ_KH(+eʜC-%z!ׅb*EHgI3>A+K7xS Z3k_~Νco)1:~ũ:4 -uTo$+jLq?d0W|f:k)~UO<o )w>*Ǐ#ıIKK^D{.  yU M N .*E @@@ B O*~w-Ȅ JժUd9Evw)v$v/֯ݮ^~i?!VT;[->S&Ab{ uCsΥ^=c0},k.Օط{OxYY ;?o T=K|wHUm ۹E[U)]/^\ *}  dA@rq9t۷Oߩ5{tJY+"   cQVLo~''M JtTիl߾i3=<~Z.AQ}F/+]3U0Nti#8]^yW|?Ηw9mf, `з{s^KQ˖oYN{l$Y~1$ASR*~3`k^+ ˽gK;}iQ G[nQ *cGQj̹XpT|*{)Tu.A{`B R09  䬀ڢbEjj0s0g;  I`p+lrk_tɟhOW+T [_䪫:,y,ą6.P^׬ 3.eke $KskN\([{Բk֬ӧ}̯[bbynݖX*U|.L3d_+dU_iҤ<~mXK{Ηm;YF(k@ tkg k`\4!!` sx.  @صk^VYjX@@rL`А6ZS-.?mjfƿn3>c÷+V}\E=o[cY]'L~_}T,Bo3NBw=Ky%m2dd% D_-A{F0;X񦋚'CIJV:vrfMK߮Z1PJ$AACgz)YZZ 3Gon# ʞ|k`[3\; KLf ?OE@8Yqw.[:$   @  6> >i­-/ ,@Tˈ%;U7w?Ssrg|[I;5YycǽۂE>w,[< XkѣǤ˵7ZDu)(p~$))om8߁g! o̪UjՏIZ#c   eAC¬²+W[z>>?'U``p)ޔi~K*'^;,gL&``upMoY1i{eL;>feu `']Yf>#  ʕ+ĪI   pjS vNz}~_~CfϚ%+^ju&}M;W{lh#2<`$ `?@0 @@4O@@@ `  ~0c0aߋޣtٯͮ ԹO?P/<Y}x}b'Zc" @@( 3@@AA`0\R_loÚ5k ј  @  FJ  QAÁ`hKnذQ}_/yP6C3O~헵n%O Pxt@@ #h0x@@FZ0䮻o{#kVukЇRJ93?\xMn r4nPW *UR&M`?ݿ a  38C@*@0F@@8 ACH',^Dh)R4iX .$֭ P\`P=5sKu a #`x@@!  dd:zc=%_IW+gU`z{gZD08s{x>     dd;HϞѣGߔ|lsǍ ?~sL0Ppa6   O  ! 7o"ww.n!׶f:o_[w;,@5]: sΗ^+*( U5k*WJ,KJJ\V?O_`z1=K6#ٿ}k~1Ulյ~ʖ-#o3ί Y ̊" d`vIr@@ 43oA[h7+;wM7ˆ%D$XUVUT$j(iii>_`)]tЀ27ޏg" tkp  [%s@@>A1kg 2 S  a  5B@@  `nD` & a<|>@@l 4%4Q$@03I03@W`0zǖ/C@@ PtC sf0 sƕ" @  Fe  [`P`nD@NZ/j=URRRdժU{n)X+WNuڵke޽RreZ)R>'NȖ-[dӦM9%KJ*LJr1}XbUEoذA߯TR]ʖ-+T=z,[LOU5d}_}*MKK˗wVam/  Q8|  $@0h/ /a 'O?ꫯo봫E.ժUm۶ɸq~}Tf͚ңG !ٳe޼yvSo Ծj*:tЁɓenX~];eڴi/ 6m*]wn U`:c Q``Qad%P3  @^ KŻ"  C0hE7H `FdѢE! *$]t)Sdծ][RAeAUٻwoILL;Ug *N^zI5t/k@M4믿^7A55 D&Eۧ=   fACnx@  3 .,Փ ҥK T}Uh3$h`اf֩SǾ˺u6Diݺu}n*+V;v8˔)# 8Pʗ/oWӧO^2>V>^ZGdiiiC9PoAwi_[-K/9mC @&hM@@ 4'4Q$`P-Af͘1C,XW UQKzXPKm%7CPwrYg`zҧOPa_ΝyN_7J;mٲt>[-fDezCo@@ a@@"C`p @ 3 hC4#_;szkOy駝PN@@<(@0WF@@ B `nD@8\)A$DS gϞ-sU T5sP5SOS wyҥKGv]vD+ThC@h {@@=AC{AC(!E Λ7Of͚GhѢ~ t2ds{Rn]]w͚5kx@0(B@8}ӷJ@@ Y# I V e˖o팑ڏ/رCF4h+WN @@  !  ÛٿH7@ DC0sN9r#߫W/QS;=#UV6c0pySaҥ稃aÆɱct[׮]%99]ٷoՓfA[    @@@  %  @ DK0d͚5OTHxRre;Xb~]+T7UK߿M4믿^ PA@|.@0  d!&!" 8 O=5|p)TSn@>駟ʷ~*T  pj[o%7npn Cx&Idź޼ysܹs.@}FUZi֬_uu?wq=ݺu50X t ,ihC@`^-@@ 4AC(!E9 Kp޽i&ټy=zT*V(*Uҿ ,WS;J"E$11QTIA@   /@0hhG0hE7H (>@7fP@@r\`А`nD` & a<@yxxu@@"L`p@CC:x@~\ۻGw,'EA  A@@| @0OD@@ L9 ~%Iw;~̟;G--/L*UCߟlټѯOAC%66֯-ʚ+dŭX||f]9@F̓@@2 S    ;T&rr $}9{,]H?9 ͕3}ʮ۝> }|:}gp"& Q^n  `(@0hE7@@8)Nv`PhM/iiiz;z% $绽H9Ԥ֙>ĉWȑú_jgJfzMI pPn=PG a'  AЄ  %@0hȖ]ZF Tx rvR oΫل8k߾ݻv@RR)}F ׹R۶nB#*K $B%w7cV$V Lu瓗F>%^WUIR1?-ܒ  nA   AC 'c|;SUং2g'ߝUk=괩Rϐnf6,׾ןo:AIrFҵGo=[>B-͒ܠ%UC#IP`9"c^4ڿoSWU%p_[`eڔwt6n*.2 u*@0Vn  B`0     ɲ#,YDu@)\$^zjƞgR *$}tݼiLSuf:ِAjơ eKd̏MAoC*Tj 5U .,@0fp  T`0(    phY  >|vu[ityv<+@>+5jֶѧ޴Kv^rC]]v|\WA#m}Mzz^Ӿ_f%762lbJUɡNeW\%4<ש{{٥wARhQo.@0vr  D`0 M   pZlY 5SH?MoC>ysÝOg3p_eϝ4j"iO?.q X{ % c} Ͽ"i辽;mլ?+X{ڥL )qZqG/W8g):]vi7vݢIA sK" #  @V  MUWwɻvnB/m#kܤ\|`\ٶu,:tGu$\SuOZ3tzҶ}g}g.y;فpx{E  Ϛ'!   m@@w9 ?;֨@IDATU/^!:(EA)һ.IS"TzUH[(H@!uτ;ܻل Iwܙ3ߴDGsڌ3!ڴiSލ&N&L7n\Yv=*W?gV|W^o.Ėη@~xwwܮ}8_WLܭ[cLv3kovu/ez+vcɮlfME_y}3Z@08Eݏ @k @hJ@0ؔJm&-/oN)+צ89F"o2˯i-7\V~nŖ 62/sOB.{\}fqeCd-ݩ\^v1|q.]bG,^zxďY?믎Aow>sj92;^reb75;vL}X+V\yBoVwΞI в:6w-|  @. ,H>=>i6tSgN!i`6=Qxi_o1izT3gbg}[яɦ- /4$&<1XKϦ-_kE#=sͶ^4oܩ>< 2Mj#] |ۥǀSNx6 @@+H <ǜo > @% ,(9=^oFE|i4` ܾiӷ_lSY+/=w:i}o6?ϼVPW#NT,܊وP<g&7wt-EXYAL!6U\hࢱ[7U@ dXٳgݻYa @cĈѥlc @ @`'LkxƏ{Gʚӈ\8J6hZop^cW4hx4o-W 1٧5/g-睯\~9zt)߰9WX~_0;K/ KӚ;cTK=f=`A Ӻ}iF]ˇUi-L "i] :٧:uumKk ݺ5U6նqcfSv1|TT:9~瞞OG[E˜'lQKw~L)lDh):th/-``  @H`A *k w[7샡qmi^yMe_)]|l- Mi NֈJjB`İ!1v]Ҵݻw|z{&>K @Ԍ@CCC-FʦM/ֱS95^ @Y[@0X7ƫqWgO5glG"v_#Mmߴ.aS m{WKS;lJE @ @h}}.,U*pAѦkGpQi`;F?NG6+Cktme|\6rn">kw;w4 ~+&^}A~4JM KS~`miZ=]?!M0S!@ @ @Z@0XŠ>XPqSu+Pm*j f#Ӕi/Fń߫GȎ!_x:oS׏轴@nbgE9|ӎGGhKS^]?9 @ @ Ъ_0X *w7*n˾[e0;҆!cˏ,Wγ 'L<| ζm?ζi'gf08]]cYK_i 4jyxڋX0XVK @ @Z``OO0+믿z9*_`Xj%bѣGN;-YfÉ߬:Q:xͷcР7!ǻ+odks^ +]t,][oW6[Xq38xa;`0c!;&bd34k=f}݄ @$6Ѯ]ЩKt#w @3T@0Xcǎ[sM>eyC_txq_78)[nCifԘzVo&Otiq߽T5뎱VUM`ĘQܓUem3lUEEK~53(&^sQvffU˧KúnerζiV`p%nmQQKqEݲъO96iwhimtu iĉ8wDDĿ #>Ύ9tdX麇  @L@nE9暖K @ @`|}}2O?,9hԯtq0Fzȯcw\լZqdQ6[4ٵqjX N_Vso>UmS;p_,[ghS<7ƩȦM׷)diT`kݮO" tݳpEem/;XwN4 \/mw;0ۏ cy'& `2xlf;5|iIWS0S|Æ(3w;vo}c @hhh/5*FX=s+ @ @  Mk0xy[nݫW^qM\vUE>紘oyc:I @`ZƌCLJ" @ SqnZ?]v޳wXc׿_~}bq0vFXk]Z4[;^rd5vP?.{?ĉ'Tyl` X]}qIim} 7:j:ъר VqLAZS'0`Pp @L@ ݦWy98'@ @ LK0/nΝ;wvGSZV ~駱vU 9o-?78v.Y[[l]tpg<|=-&^z镪K/G1GϪ"?m,iͿl+ON +ܣr:ϺſunUy:o28}[4|ԡ_U \<4s|TLhx-Mڦ4ڰ񇲶<,5,꯿j4^+DtR:G2+E$pY[#_cbJ )H/ 8Z.:u'ɞvJӌ.тi޽{P% @$0|lZQg @h%LSq)9++_ʦHGuz`/FǝwSu~E%\:<眿ǿ﹯n׏yv)gLV>?6Z?ϳ J;-LV6~ɵag#>h!RlJ[V[ZJ!_gR[ ׏2Myٙo(fLeޥu UZ5vL(#i`k[  @߭@y`s}O'@ @` i b,]]TV?;Q V(y)MFVn)EXyMSTs[ogUG2~ʱŧj[vQ*_`oP7) @h`3 { @V" ,EO>$vug} |.;Yu2|!מT/,|ŠFySoS/u]+6twc~P*=iǶI%vo#' Nn @o @Z`` ndwꪋ{'x*~{ U7wA%X,~Cw9z&>84 KAG}v9~/ 7^;vjs@5 [SoV @@ ko @YM@0XNJvxX zͪ;|]b6jKG}\<3U_zfsU?"V-q7?qqU]S`*ꫯm|֌C9qcJ@0ت @jV@0X] @r]6-vQx-86]{Y{wWǕW\3Y]e0FQo<?dD!U6Z?ާzZ[vb46Y@0ؚ{߷ @jG@0X;}M @=8-য়~o[w^dcҚ~/>&k*4 7Timw!Z\vUSo~U>gbwijѫ8ڵkWnKU [eh @@ kK @YV@0X%L⢋.+x`<'xRuAV_%~Ú /mܔF6Y@  i @YH@08 uW%@ P4wyT /_~e^W )G9!̋Ikȿ95暫wU{:HwmSß|B,MH5 [SoV @@ ko @YM@0XǦ5,gynwu׊=vuSXx䵣F .$y[y'SiC=ljv?vئ)o~4^h P[oC @`V o ۧуoNQP. .@tо'ސxtC?N;E>}be.ݧ4ݧ\|5]^>~zih P[oC @`V   >ˎ݉cznztT9 Z}7 @ކ @, ,{-%K{0.貪_lESX@k  @ N_x @```?o__?Zc)w@k  @ fx+ @```0Qמ4s+qѮ]&k$j%3fLhР8M6$V]uc=_}|<̓!@o @Z``  B)#Ђfv07pCmj[^iDgSM~nZ(;NuQ1a„8p@^xsΉz+kҥK{챍K @` u; @X@0XhA3;[⡇[`i??HP㰯`O{/b-4iNU.HGyd0 '}mt5?.|嗑ΕG_ @# 9J @5  ` 2-H`f_|Ew˵4_~y[Z'0M駟mYob5;)LAdy;SNa SX6l~P>?kM)d1bDxy]`ߎ>;? 'DN*7M0:ldb!]7rpO忕ӈ@0 @` g' @h-=-,@ 1cƌɴ\ry睧(wWO?o /Bv{K4yaÆI'k u]q=ځicyK޹m| @`& g"[ @he.,@ Y`{;S,RS{g+7(KgE43txGJG&n+k6?N!anc; @3O@08lݙ @@k q`A(eZ ?8s!]~⫝ǙgM)L#xP=7SN9%>t}7sύ7|3;ob!@ @Z``o  B)#ЂfV0K/E]KuQѣGN?)kn*;4RpJ[t馂~8nw]t9ƎG}t޾[ +!@ @Z``o  B)#ЂfV0Fޥx暫|8;guV8|'ꫯ]v袋Fw1F^◿e^T0ô`yjbVgq:t(%@  @Z``g  B)#ЂfV08jԨ8sw= F;S[cN#GfWnvF7n\孩`0;7\p{΋Aemi-Ĵ& @gI @Z``7? ^YX`f#ȧ\yc-ԕW^O?tvr`ZW0MY6xXmʇUi/8oR0_y>?Nb-!@o  @Z``O  B)#Ђff0׿5iMmzƣ +ʵӍvyXr%K/4ܔ &d# .[oeץgiDah ,fa @B@0XhA33LSs):ۀb=Z/̦2dH,*ޥm嗏m٦|409?N ӚJU 'P5J1lhh1f̘v;,?C |$ @-]@0XhA3;LTǏ4u/ؤJ+MyQGe;uꔭWYF^veM l׮]v+nDLh*LrKK Ќf( @-\@0XhA >x뭷Ϧ]p#;ءCrT'Lj :4F=zȦ]lŢ.6MMogsΙ3iLtqW]!@!& @4T@sFt{wVV[+z @@  @f` ` 2-H--g}  @` Zm  @Բ`` B)#ЂZS08dȐ}/K.$  ,O UB^yc @* ,3P  5/o͎  @Q@0،E @  v` 2-HJl-G}  @` Κ  @Ԣ`` 5jgƈO>Ίڶkm]M"g)cРAѮ~Ų.-,K^ -}! @ ĉ㹧>kӂo2Ǝ{W|G~s;i;#m۶UmS;ƫƫ/j?Z+v6R4@k  Ճ @Y@08d. @ @` )4n`ewѣsvݳ#uk޲zO].>샼SNȀvӵz)l׾}/SE.SC` g* @ RF @7 hR SvեĄ 6wֽG7eqR|9ztW^%V_c>tܸqqg_|;6;N'S(/y% 4`= @ `( @Vl3*LtS#iixcN|Mnݺg~}4|X7hߡC{9GɮlHS}H)"Ə{9{}]YV3NC޶϶X(?JH*K,xKѧoL444'>a1=}ߕ @T +5 @ 0=z3*fOM[ owqK3y<Ϯy[ڙն;Fvj̓9z;w6Z|.b9^.7,M]] \t, J;";)ק#>ɏ΀-ޡW^}W5^qc* lVn#@`p 0  @f`A {S˞XW y҈4rֱcK{)TTL:OS +FPr{[oljrw~i\j|wSP3m+kf 63 @4) lE# @B@0Xmz4:|m~˭êJ3_m۶Y4fC6/MYYXre÷|#nHB-KץoΦLK-\Ӎk&NM|K.L&UUwxgw5٧yO qttE.]ʇ~ 4`= @ `( @Vl }ǭsOgOk׮]poS||==8]OĽw3~V~~ @# ,7`]"6t)>yJ!xX~Ǎ[~ŕG?Y7;F>1`1b?:%a=\})J#Ӌ/ttͲ?r`74ix!ѵ[FU 4`= @`)8C @  zMO0+/7_?imvy[ ?n;kN#8U%?TsmyۚiI-MK+o~u ;'^~m L_]y߮{# Қ~T(7oN^1]w @@ @ 'FHvuW[^ެCGozf`pF @ ~5 @ Д`)&ڦ'bofwR(W89_ 0xbWq0wy+/_d%bMKӥm˞1WIӀi>`pmw*i4i:w{pX?jgҋ민瞧j=[:jVLsj92;\reb7)w1qW_cXqUc; QzlC 80wL @!6w-| @ߙ` _t~ pRLmNi0aBom۶4Zrm(4R믊7x-?=gbg}[OG+ /k׮=Ą䐦M#2\kEץgnV‹m;ӧgQiURߎ ǀSNx6 @@+H <ǜo > @% ,(9=^oFE|i4` ܾiӷ_lSY+/=w:i}o6?ϼVPW#NT,܊وP<g&7wt-EXYȴbS[(Ʌ.ouSe4O?={F޽F @ >Ff @ `0ۗ+o{htڵ|X|Ȥ 嫺𫃑}XW׶`ڭ[SeSm7vl6Eh{LϷOA#K^ptnU \toy&P5ؾ|ϔ&A @-BCF  @ ԜprvP}W>זF[fbŗ^`o4ijkWa%}5!0bؐ;ft.iZݻ3ٱgx?/A 2bl_5jT6}hDϹn+ @`zAo\u^sΦ,?z/og5R8M6uͬwœ{4{4J0UZ}?E ly} @|0@IDAT=0`z_oZă?*[o0qfMѽG>h,6K/%u7Y7[ϋ5bd+0aB6 @3JMu;F vÚ3} @9wfD0}w[ncu7nd/ѭ4eʫ}ܬ0W'V^%_pYS; @ @ @`  |2 @ @ @3T@0XS0XJ @ @ @@M  v` 2 @ @ @ `A(e @ @ @5) ,-P @ @ @jR@0X[ @ @ @Ԥ`` B)#@ @ @I`n RF @ @ P", @ @ @&E0XJ @ @ @@M  v` 2 @ @ @ `A(e @ @ @5) ,-P @ @ @jR@0X[ @ @ @Ԥ`` B)#@ @ @I`n RF @ @ P", @ @ @&E0XJ @ @ @@M  v` 2 @ @ @ `A(e @ @ @5) ,-P @ @ @jR@0X[ @ @ @Ԥ`` B)#@ @ @I`n RF @ @ P", @ @ @&E0XJ @ @ @@M  v` 2 @ @ @ `A(e @ @ @5) ,-P @ @ @jR@0X[ @ @ @Ԥ`` B)#@ @ @I`n RF @ @ P", @ @ @&E0XJ @ @ @@M  v` 2 @ @ @ `A(e @ @ @5) ,-P @ @ @jR@0X[ @ @ @Ԥ`` B)#@ @ @I`n RF @ @ P", @ @ @&E0XJ @ @ @@M  v` 2 @ @ @ `A(e @ @ @5) ,-P @ @ @jR@0X[ @ @ @Ԥ`` B)#@ @ @I`n RF @ @ P", @ @ @&E0XJ @ @ @@M  v` 2 @ @ @ `A(e @ @ @5) ,-P @ @ @jR@0X[ @ @ @Ԥ`` B)#@ @ @I`n RF @ @ P", @ @ @&E0XJ @ @ @@M  v` 2 @ @ @iMk}S=5#} @ @ @h=UGF}Ѯ]h۶m:œ ر:m\te\r5ٵ^xf;ܓ?;n蒫KKΉ~o @ @ @@  PsUz>[G",T͔5%oKvꐃ7Z&Mh$@ @ @fq``p]dOjhh!CƠ7߉k%?0 d5Өʹ|^F?-",L @ @;kZCʩDOڪ+OIiMƒ9*),4`; @ @ @* ,=|dѭ[%3/{Cޏ|w/bFW~Ɉa_dk7ڵkz 5 >px3O̭S~w5G7`ܹSkSQȑ_߹1XO! @ @ `_"U学u`΍[n3;{?r[f/Zuޅ T[~cukʃW^}#N=H[Zov61kt n7Xo8*/=WR47^wQ^;˯>}Kα 6[o/60oyWs/_ٞW_qlN=ؓqđ'4.ˎWZqi\ecT_pF}qM_VE"vmúJ/OW+Mqgލ/ˎO^teGsdܲKG_z5.䪬KΉ9nsW]v^-Mmg۳SGlMi#@ @ @Z``6G0xx:{sS,"ۥspku΅y[S;ۖ=v!f{0s쟚$k[vg_o֏Glypiķ#W努i)w}U{c><*U͏=T7W5>Ha䩧KASΥZ,<ƗOv\ prCI:6:uXn~xq8::V]Z=:=BɯzÇ`wO[na_GariJ @ @ @e  8]W5Mfk-6V\6/Z\|5iaqXRݎ{j?]q o\ڙ\]kֱآ '|&ϯ Xmys3 .|h>$/ƍ73OY+FϞ2[2֔v*rMUW'z6k"rej[g5'k}7|'H#Ӗ<./{),o;ˇ{h>vgS+%J٥p5>8o/1 @ @ 0k  {s6]fGa)|Kٳ}ݖqcGGe^^PyCʛuەѩӤuN:wgll4YTǗfd02yISvN6Uq~+L6/IilJPtG{tA{&|76O  @ @ @YO@0X*"T1X\s!]>~ӈ?tfġ5N9qwe<ziݖ[뺫Rk|}yތ +CsHǫ7~tvն?x}QΧ`'3?x^*Jajƴͨ`0٘,|rXvgLrõae=*%w YxXه]VeÆ?v: @ @R@0Xօ %+®~<ғj9.;]!f嶿ZUf}qK1' 3_ >6|eXjYwq>kO[؛m o0z`|txoj9wM aSF=࣪};l^n]_>ʋBzn஻}9<վ~pi;vmy` 3G>S1lwlRi#@ @ @`a_M0ݶ ~}ٳËS?mR;G5]u }欻|{HI\B且hU]w V0f_.i7ȣK`~yݫ03cӹ=kiY3 V0xw Jq ~~UsA_,v !xLRؾzfUWi˃\3p_;뜋uGv@l] @ @X2}~5qG ui7k~_5̗lg6 'pѷڪC =2_yOOg7_g'vڮ* W_˯n}Ma>7yuy-y==>m}.~PKK}M^n9}'\s nƲkjs}s`0}W^Wx` iӹ3gP= @ @ @) ,k >ݎsgzK~f珇qWrxo ߽^YCv]9'.'bv]_flodm)㮸4ɿyO{/ഐB´ V0x9'f:᏷=scjx[T縯~>Գms>-+hȾ<vcзyj6 @ @ @`u0.#xwkZuuG{rt7}RxUK?ᴪ4=p}w/~U]Mx.{Wғi ʾ۴i/m>jw 0Y٦%Xsvs\T`e,vm4r<\ǁ )Laڮlkq  @ @ @` za{u@+8~[o/2\L:|?VI޹ڽ>u{վ4-̀o˗̃| ^nS^vp'U>ㄖ>zW:úU=_wi JSpwjw|V0m tLdLfLۅ~3lz-y~4`0m-ҒiK쾴uAߖ8K>_0x74 i9K{UJQۛ @ @ @K` #GuCZR3mwe3+. cd^z)Rfq7ϗo%:<L;ay>s/> xTN=<7Xަ*pkkk \jak|͗LaΟܡ,cǷm3AĦSO>&u7vo㈯W6dp'T3gw;<|{˱Om˯8ª>r\H/# O3Pn)TN᲍ @ @X=_` R~@x?mݼO9'_TsR뇞jiqݤǟ>OlƖK74m%tttn[W4T7<ͷ[oݵ`iq~tÍƹـ}c-ޱYn;5\=춏~_?>f)6fJ&+ Yk`0}.)l7b=yECO:7mn ?wfeZu-7f?'^s_{/yF/,}ޭA99g wA`ڿAGVdL묽fW @ @ @`  6{ayBL3Җ¯/?@B1%ikנo0»C;nCRBzOo^Km }ߤ@kr믟xF4}Gsˈή=88k GÞqFb~)MK6k;Gwk]^\}7L;S8f R@/!=㰿`0SOW!U#J[Z>t>>G,gM>#w%Q>4/~g{qK| ӫ. ߕ)oKӲgk=`|щ812?18zg%~?.-+%xiC{  @ @ @%K@0X  O2PxG ˏıcM{)`x<.;˅e/L+Wː.qo @ @ @%O@0X=|Si] |2$pؑ'0~ܲa {޺k]  @ @ {0XȠ @ @ @`  ',RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z `[Fƅ N 9;} @ @ @LmwM #G #FRJ2a3fi@~|<===]]]3̞=;̜931U0x{BWww =ݱ>g~@9  @ @ @1 چÿo7zj}Yfc0¯=)B%ٚƎ`zq @ @ @xUgR4~Cc0f n`5;cp8;8(/;պ _  @ @ @@Y4Wl l=18|z-% oRx:*ޙi F7 @ @ @ 08i`5g0oygCz`ZJ[`+3W, @ @ @@c`Ǝ`pJh-g q`σ]u0f 9s>&@ @ @ sg  F7(\e @ @ @]ͪ)`p>@>&@ @ @`=B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@=%#IDAT @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  joQF @ @ 0^MvO0X(|B 儅 @ @ @5S]P\m!; 0>Č{{&L ]/?= @ @ @ho a1aUG-^7&;aThdH:߅`;La`ߕ<nkj7(#@ @ @JhLW`ʒJEuBF6pϞ 8 @ @ @Wו°f@X vf~` ~/igVF @ @ 0ptd9XpP0X+w0 ;|?y @ @ @Y)R  m  [2`1[+\ys{,dUF @ @X,`t|rK  jsg v`kOM,<2 @ @ @A`e:;L1A`/m`9[0.#tR.<2 @ @ @B->j ;êu9`a7 ق)Q @ @ @$p.T`5EuςBט1+>QxFe @ @ @韙::Wˉ cg FȖ^{uYfn[.c@9P}:G5eDc083|2`~ @ @ @w?sδ^k3  V c`PT @ @ @`8-;m!=cP0x @ @ @^`0q)5  @ @ @`0v,qL`aL @ @ 0cyf s c @ @ @& |7S0k @ @ @ 5`X㼙\Ø @ @ @` c00  @ @ @CM@0;8o`00&@ @ @jر< y31 @ @ @P Ǝa`>Λ)5  @ @ @`0v,qL`aL @ @ 0cyf s c @ @ @& |7S0k @ @ @ 5`X㼙\Ø @%EÛ 2wN +:A @ 0h8  @,)fXyWt=5'_ѱAmBx˄aq0g)aVgOW @H8  @,)إ{r#{rF>o @ Z n^0k @ ӂqt @^`0a`>i1 @K@`'|Ԣ}\JTT ? @CC@08o`00&@ @`I N>wރ tV_nD1OL~vV˾3:Ÿ6wǜV[*q& CO =R3ֈ浗:*]=pFW\~d C|hB˾}p?zo8#u| aT]=;)}l @ F< ǹ`00&@ @`I`0YٵŠcki_Naxwv&Yi[w8=Τv?Rf흸aDh)8pKnu0xO kzǀ}1τ@O @ #I\K0k @  ӬRe);u5CX l\/ӬM?;5'Ί } ¯;8ko.ng^OW&\zd{8S1xc1M cFX(LzR6 @RP0k @  K'fÿ?wytܿo\K>7ntGesR|bx^46|=+-r'T\nsx޷ƥ;1'.zYxo1em @( F< 9`00&@ @`I`0;&.yg\^5š+h{|_-ʨ= Ɛ񈏭^Fkvf8+jaZBz߫ wO0xU}OνY7tqΖ}N9|ق{F @`T| s c @W7<˗mxrp.! k1q]c:;\۹˔O޸u9lqxf\tŸicK3wag~pqp/gw/`0=g }#me0dˉ$ @ 0ys3`aL @"7κ5ɳc<[->.#~{^`Z˿nsp;qݨlݤx]gn cFqWaJ @ `s' 5  @XRgue<_Ͷ˜pnk?2=ie˿^˾7;3 s\9F0MƆy]S7<#/廌  @ Я`0a`>1 @Kk 5Äa6 @#G\J0k @  v0;sR  sp2K}O xasOK~Y3vȯ+~/y8̊KٵŠc;}᥮jO޶}  s~dg |7 @X@`|[ s c @ W;<-z{S:7;W,M9)3`LԻZg|gvZ=7a頓xCs<3^׊Νɝz:\#w>fH[ x #:⺧6`k';&Νy>6 ^:q^1lҍ0svOG  @ 0/`| s c @`8lYoiտ}.lmn Iof~>ߋqOoxtFxdž6rt@5]-i쮞pm/'>e[T3aW=V aZgNn a莰e %Gjk1_0x˝S|x>8SV 6qxS3}L l:.lR-뢇ZyC @Q&q&5  @XR K=s<|Lq|{6>o4C1˷K5ª͝7N9Tsw[+3w9 &>ܾ*ޝ1Kػ'G];1->{'ͯ @!q  @,) 2nx8ehz|FH/sԈYw)1Jrqf^Ztx:z{_<׮MV_**- ;6-z/ )-axik˃t@=z7դه/JϓZXql3g]xR8jKqsT8+J̷/^pxnZgsF {~`r J-,Ye˛6I)OH36 @,`0ja`>!1 @X 閏a߃ w<2 Y]1x{K׭:*۟xwЁk_QG_ )|>>pA騖EM3$ǐoR\_ݩn5LKČ_ O~y|Z @\`}g!5  @ @ @`0v,qL`aL @ @ 0cyf s c @ @ @& |7S0k @ @ @ 5`X㼙\Ø @ @ @` c00  @ @ @CM@0;8o`00&@ @ @jر< y31 @ @ @P Ǝa`>Λ)5  @ @ @`0v,qL`aL @ @ 0cyf s c @ @ @& |7S0k @ @ @ 5`X㼙\Ø @ @ @` c00  @ @ @CM@0;8o`00&@ @ @jر< y31 @ @ @P Ǝa`>Λ)5  @ @ @`0v,q%<'BWO~g @ @ @@0#amm-Yͪ.㐭^ #FÇ6ށy]3f48?{CWWWԮ֌  @ @ @sǴö[1t   `7f,?mG @ @ sQa-x{g Ι,hcOOOHҌpߤᬛ&U @ @ @ 믺T 3{ӽ  1`;-'fD w,<2 @ @ @,z#Î[,ٗB6K^7. 7f~B³+#@ @ @ve%D;:zg n8 Ri9hgZR ;85Yߠ @ @ @`( lP0_G{{hR4liQݣ`P~͛;keE:ƒO ypfKq8F @ @ 0KVjo]gdXg1lmu-ysg g Vfvu;_Osˆ} @ @ @V{g #;C=lO|^ ë/198 {b8F9&  @ @ @X7?)36 Vk &D`O$Lj0 _ ~2 @ @ @E* SHyҢ`4 y[B4[Z  @ @ @d0^d9ˊp0m %U,?Bmf#L}-ve @ @ @T uQ>^8/ ihk08W @ @ @*jEuςB[SF @ @  ,,RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R@0X`!2 @ @ @Z  ",RF @ @ PK`a[P @ @ @j) ,l`J @ @ @@-m B)#@ @ @`-B(e @ @ @ E0X @ @ @¶  @ @ @R``xXАnA`G @ @ @`aՋaĈaᡣ#W[^I&6lƌ=O״+tvvVf͚Nu˃Td@9@yN @ @ @tΘ5cS0Ք3gΌ ?' 9^  @ @ @,l~8 ӌ#Gs` f v-\ؿG @ @ 0~Z![Og08{쐖=7cBO\^-#?;7@ @ @ nJ'xSDsk :7_V0% @ @ @`  #Zo0x`pq!s @ @ @ [`k&V`ěSv/\ؿG @ @ 0* RUSSIA INVADED UKRAINE - Please read ![Django Ninja](img/hero.png) Django Ninja is a web framework for building APIs with Django and Python 3.6+ type hints. Key features: - **Easy**: Designed to be easy to use and intuitive. - **FAST execution**: Very high performance thanks to **Pydantic** and **async support**. - **Fast to code**: Type hints and automatic docs lets you focus only on business logic. - **Standards-based**: Based on the open standards for APIs: **OpenAPI** (previously known as Swagger) and **JSON Schema**. - **Django friendly**: (obviously) has good integration with the Django core and ORM. - **Production ready**: Used by multiple companies on live projects (If you use Django Ninja and would like to publish your feedback, please email ppr.vitaly@gmail.com). Benchmarks: ![Django Ninja REST Framework](img/benchmark.png) ## Installation ``` pip install django-ninja ``` ## Quick Example Start a new Django project (or use an existing one) ``` django-admin startproject apidemo ``` in `urls.py` ```python hl_lines="3 5 8 9 10 15" {!./src/index001.py!} ``` Now, run it as usual: ``` ./manage.py runserver ``` Note: You don't have to add Django Ninja to your installed apps for it to work. ## Check it Open your browser at http://127.0.0.1:8000/api/add?a=1&b=2 You will see the JSON response as: ```JSON {"result": 3} ``` Now you've just created an API that: - receives an HTTP GET request at `/api/add` - takes, validates and type-casts GET parameters `a` and `b` - decodes the result to JSON - generates an OpenAPI schema for defined operation ## Interactive API docs Now go to http://127.0.0.1:8000/api/docs You will see the automatic, interactive API documentation (provided by the OpenAPI / Swagger UI or Redoc): ![Swagger UI](img/index-swagger-ui.png) ## Recap In summary, you declare the types of parameters, body, etc. **once only**, as function parameters. You do that with standard modern Python types. You don't have to learn a new syntax, the methods or classes of a specific library, etc. Just standard **Python 3.6+**. For example, for an `int`: ```python a: int ``` or, for a more complex `Item` model: ```python class Item(Schema): foo: str bar: float def operation(a: Item): ... ``` ... and with that single declaration you get: * Editor support, including: * Completion * Type checks * Validation of data: * Automatic and clear errors when the data is invalid * Validation, even for deeply nested JSON objects * Conversion of input data coming from the network, to Python data and types, and reading from: * JSON * Path parameters * Query parameters * Cookies * Headers * Forms * Files * Automatic, interactive API documentation This project was heavily inspired by FastAPI (developed by Sebastián Ramírez) vitalik-django-ninja-0b67d47/docs/docs/javascripts/000077500000000000000000000000001515660254400222725ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/javascripts/ask-ai-button.js000066400000000000000000000026061515660254400253120ustar00rootroot00000000000000// Add "Ask AI" button to the Material for MkDocs navbar document.addEventListener('DOMContentLoaded', function() { // Find the header navigation actions (right side of navbar) const headerActions = document.querySelector('.md-header__topic + .md-header__option'); const headerTitle = document.querySelector('.md-header__title'); if (headerTitle) { // Create the Ask AI button const askAiButton = document.createElement('a'); askAiButton.href = '/chat'; // Update this URL to your desired destination askAiButton.className = 'md-button ask-ai-button'; askAiButton.textContent = 'Ask AI'; askAiButton.title = 'Ask AI about Django Ninja'; // Create a container for the button const buttonContainer = document.createElement('div'); buttonContainer.className = 'ask-ai-button-container'; buttonContainer.appendChild(askAiButton); // Insert the button after the header title const header = document.querySelector('.md-header__inner'); if (header) { // Find the right spot - after title, before search/repo buttons const source = document.querySelector('.md-header__source'); if (source) { header.insertBefore(buttonContainer, source); } else { header.appendChild(buttonContainer); } } } }); vitalik-django-ninja-0b67d47/docs/docs/motivation.md000066400000000000000000000066021515660254400224600ustar00rootroot00000000000000# Motivation !!! quote **Django Ninja** looks basically the same as **FastAPI**, so why not just use FastAPI? Indeed, **Django Ninja** is heavily inspired by FastAPI (developed by Sebastián Ramírez) That said, there are few issues when it comes to getting FastAPI and Django to work together properly: 1) **FastAPI** declares to be ORM agnostic (meaning you can use it with SQLAlchemy or the Django ORM), but in reality the Django ORM is not yet ready for async use (it may be in version 4.0 or 4.1), and if you use it in sync mode, you can have a [closed connection issue](https://github.com/tiangolo/fastapi/issues/716) which you will have to overcome with a **lot** of effort. 2) The dependency injection with arguments makes your code too verbose when you rely on authentication and database sessions in your operations (which for some projects is about 99% of all operations). ```python hl_lines="25 26" ... app = FastAPI() # Dependency def get_db(): db = SessionLocal() try: yield db finally: db.close() async def get_current_user(token: str = Depends(oauth2_scheme)): user = decode(token) if not user: raise HTTPException(...) return user @app.get("/task/{task_id}", response_model=Task) def read_user( task_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): ... use db with current_user .... ``` 3) Since the word `model` in Django is "reserved" for use by the ORM, it becomes very confusing when you mix the Django ORM with Pydantic/FastAPI model naming conventions. ### Django Ninja Django Ninja addresses all those issues, and integrates very well with Django (ORM, urls, views, auth and more) Working at [Code-on a Django webdesign webedevelopment studio](https://code-on.be/) I get all sorts of challenges and to solve these I started Django-Ninja in 2020. Note: **Django Ninja is a production ready project** - my estimation is at this time already 100+ companies using it in production and 500 new developers joining every month. Some companies are already looking for developers with django ninja experience. #### Main Features 1) Since you can have multiple Django Ninja API instances - you can run [multiple API versions](guides/versioning.md) inside one Django project. ```python api_v1 = NinjaAPI(version='1.0', auth=token_auth) ... api_v2 = NinjaAPI(version='2.0', auth=token_auth) ... api_private = NinjaAPI(auth=session_auth, urls_namespace='private_api') ... urlpatterns = [ ... path('api/v1/', api_v1.urls), path('api/v2/', api_v2.urls), path('internal-api/', api_private.urls), ] ``` 2) The Django Ninja 'Schema' class is integrated with the ORM, so you can [serialize querysets](guides/response/index.md#returning-querysets) or ORM objects: ```python @api.get("/tasks", response=List[TaskSchema]) def tasks(request): return Task.objects.all() @api.get("/tasks", response=TaskSchema) def tasks_details(request): task = Task.objects.first() return task ``` 3) [Create Schema's from Django Models](guides/response/django-pydantic.md). 4) Instead of dependency arguments, **Django Ninja** uses `request` instance attributes (in the same way as regular Django views) - more detail at [Authentication](guides/authentication.md). vitalik-django-ninja-0b67d47/docs/docs/proposals/000077500000000000000000000000001515660254400217635ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/proposals/cbv.md000066400000000000000000000111311515660254400230540ustar00rootroot00000000000000# Class Based Operations !!! warning "" This is just a proposal and it is **not present in library code**, but eventually this can be a part of Django Ninja. Please consider adding likes/dislikes or comments in [github issue](https://github.com/vitalik/django-ninja/issues/15) to express your feeling about this proposal ## Problem An API operation is a callable which takes a request and parameters and returns a response, but it is often a case in real world when you need to reuse the same pieces of code in multiple operations. Let's take the following example: - we have a Todo application with Projects and Tasks - each project has multiple tasks - each project may also have an owner (user) - users should not be able to access projects they do not own Model structure is something like this: ```python class Project(models.Model): title = models.CharField(max_length=100) owner = models.ForeignKey('auth.User', on_delete=models.CASCADE) class Task(models.Model): project = models.ForeignKey(Project, on_delete=models.CASCADE) title = models.CharField(max_length=100) completed = models.BooleanField() ``` Now, let's create a few API operations for it: - a list of tasks for the project - some task details - a 'complete task' action The code should validate that a user can only access his/her own project's tasks (otherwise, return 404) It can be something like this: ```python router = Router() @router.get('/project/{project_id}/tasks/', response=List[TaskOut]) def task_list(request): user_projects = request.user.project_set project = get_object_or_404(user_projects, id=project_id)) return project.task_set.all() @router.get('/project/{project_id}/tasks/{task_id}/', response=TaskOut) def details(request, task_id: int): user_projects = request.user.project_set project = get_object_or_404(user_projects, id=project_id)) user_tasks = project.task_set.all() return get_object_or_404(user_tasks, id=task_id) @router.post('/project/{project_id}/tasks/{task_id}/complete', response=TaskOut) def complete(request, task_id: int): user_projects = request.user.project_set project = get_object_or_404(user_projects, id=project_id)) user_tasks = project.task_set.all() task = get_object_or_404(user_tasks, id=task_id) task.completed = True task.save() return task ``` As you can see, these lines are getting repeated pretty often to check permission: ```python hl_lines="1 2" user_projects = request.user.project_set project = get_object_or_404(user_projects, id=project_id)) ``` You can extract it to a function, but it will just make it 3 lines smaller, and it will still be pretty polluted ... ## Solution The proposal is to have alternative called "Class Based Operation" where you can decorate the entire class with a `path` decorator: ```python hl_lines="7 8" from ninja import Router router = Router() @router.path('/project/{project_id}/tasks') class Tasks: def __init__(self, request, project_id=int): user_projects = request.user.project_set self.project = get_object_or_404(user_projects, id=project_id)) self.tasks = self.project.task_set.all() @router.get('/', response=List[TaskOut]) def task_list(self, request): return self.tasks @router.get('/{task_id}/', response=TaskOut) def details(self, request, task_id: int): return get_object_or_404(self.tasks, id=task_id) @router.post('/{task_id}/complete', response=TaskOut) def complete(self, request, task_id: int): task = get_object_or_404(self.tasks, id=task_id) task.completed = True task.save() return task ``` All common initiation and permission checks are placed in the constructor: ```python hl_lines="4 5 6" @router.path('/project/{project_id}/tasks') class Tasks: def __init__(self, request, project_id=int): user_projects = request.user.project_set self.project = get_object_or_404(user_projects, id=project_id)) self.tasks = self.project.task_set.all() ``` This makes the main business operation focus only on tasks (exposed as the `self.tasks` attribute) You can use both `api` and `router` instances to support class paths. ## Issue The `__init__` method: ```def __init__(self, request, project_id=int):``` Python doesn't support the `async` keyword for `__init__`, so to support async operations we need some other method for initialization, but `__init__` sounds the most logical. ## Your thoughts/proposals Please give you thoughts/likes/dislikes about this proposal in the [github issue](https://github.com/vitalik/django-ninja/issues/15) vitalik-django-ninja-0b67d47/docs/docs/proposals/index.md000066400000000000000000000007141515660254400234160ustar00rootroot00000000000000# Enhancement Proposals Enhancement Proposals are a formal way of proposing large feature additions to the **Django Ninja Framework**. You can create a proposal by making a pull request with a new page under [`docs/proposals`](https://github.com/vitalik/django-ninja/tree/master/docs/docs/proposals), or by creating an [issue on github](https://github.com/vitalik/django-ninja/issues). Please see the current proposals: - [Class Based Operations](cbv.md) vitalik-django-ninja-0b67d47/docs/docs/proposals/v1.md000066400000000000000000000016201515660254400226320ustar00rootroot00000000000000# Potential v1 changes Django Ninja is already used by tens of companies and by the visitors and downloads stats it's growing. At this point introducing changes that will force current users to change their code (or break it) is not acceptable. On the other hand some decisions that where initially made does not work well. These breaking changes will be introduced in version 1.0.0 ## Changes that most likely be in v1 - **auth** will be class interface instead of callable (to support async authenticators) - **responses** to support **codes/headers/content** (like general Response class) - **routers paths** currently automatically **joined with "/"** - which might not needed on some cases where router prefix will act like a prefix and not subfolder ## Your thoughts/proposals Please give you thoughts/likes/dislikes in the [github issue](https://github.com/vitalik/django-ninja/issues/146). vitalik-django-ninja-0b67d47/docs/docs/reference/000077500000000000000000000000001515660254400216775ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/reference/api.md000066400000000000000000000001561515660254400227740ustar00rootroot00000000000000# NinjaAPI ::: ninja.main.NinjaAPI rendering: show_signature: False group_by_category: False vitalik-django-ninja-0b67d47/docs/docs/reference/csrf.md000066400000000000000000000101621515660254400231560ustar00rootroot00000000000000# CSRF ## What is CSRF? > [Cross Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery) occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials (or location on the network, not covered by this documentation) of a logged-in user who visits the malicious site in their browser. ## How to protect against CSRF with Django Ninja ### Use an authentication method not automatically embedded in the request CSRF attacks rely on authentication methods that are automatically included in requests started from another site, like [cookies](https://en.wikipedia.org/wiki/HTTP_cookie) or [Basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication). Using an authentication method that does not automatically gets embedded, such as the `Authorization: Bearer` header for exemple, mitigates this attack. ### Use Django's built-in CSRF protection In case you are using the default Django authentication, which uses cookies, you must also use the default [Django CSRF protection](https://docs.djangoproject.com/en/4.2/ref/csrf/). By default, **Django Ninja** has CSRF protection turned **OFF** for all operations, but will automatically enable csrf **for Cookie based** authentication: ```python hl_lines="8" from ninja import NinjaAPI from ninja.security import APIKeyCookie class CookieAuth(APIKeyCookie): def authenticate(self, request, key): return key == "test" api = NinjaAPI(auth=CookieAuth()) ``` or django-auth based (which is inherited from cookie based auth): ```python hl_lines="4" from ninja import NinjaAPI from ninja.security import django_auth api = NinjaAPI(auth=django_auth) ``` #### Django `ensure_csrf_cookie` decorator You can use the Django [ensure_csrf_cookie](https://docs.djangoproject.com/en/4.2/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) decorator on an unprotected route to make it include a `Set-Cookie` header for the CSRF token. Note that: - The route decorator must be executed before (i.e. above) the [ensure_csrf_cookie](https://docs.djangoproject.com/en/4.2/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) decorator). - You must `csrf_exempt` that route. - The `ensure_csrf_cookie` decorator works only on a Django `HttpResponse` (and subclasses like `JsonResponse`) and not on a dict like most Django Ninja decorators. - If you [set a Cookie based authentication (which includes `django_auth`) globally to your API](../guides/authentication.md), you'll have to specifically disable auth on that route (with `auth=None` in the route decorator) as Cookie based authentication would raise an Exception when applied to an unprotected route (for security reasons). ```python hl_lines="4" from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie @api.post("/csrf") @ensure_csrf_cookie @csrf_exempt def get_csrf_token(request): return HttpResponse() ``` A request to that route triggers a response with the adequate `Set-Cookie` header from Django. #### Frontend code You may use the [Using CSRF protection with AJAX](https://docs.djangoproject.com/en/4.2/howto/csrf/#using-csrf-protection-with-ajax) and [Setting the token on the AJAX request](https://docs.djangoproject.com/en/4.2/howto/csrf/#setting-the-token-on-the-ajax-request) part of the [How to use Django’s CSRF protection](https://docs.djangoproject.com/en/4.2/howto/csrf/) to know how to handle that CSRF protection token in your frontend code. ## A word about CORS You may want to set-up your frontend and API on different sites (in that case, you may check [django-cors-headers](https://github.com/adamchainz/django-cors-headers)). While not directly related to CSRF, CORS (Cross-Origin Resource Sharing) may help in case you are defining the CSRF cookie on another site than the frontend consuming it, as this is not allowed by default by the [Same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy). You may check the [django-cors-headers README](https://github.com/adamchainz/django-cors-headers#readme) then. vitalik-django-ninja-0b67d47/docs/docs/reference/management-commands.md000066400000000000000000000004631515660254400261370ustar00rootroot00000000000000# Management Commands Management commands require **Django Ninja** to be installed in Django's `INSTALLED_APPS` setting: ```python INSTALLED_APPS = [ ... 'ninja', ] ``` ::: ninja.management.commands selection: filters: - "![A-Z]" rendering: show_root_toc_entry: False vitalik-django-ninja-0b67d47/docs/docs/reference/operations-parameters.md000066400000000000000000000150621515660254400265510ustar00rootroot00000000000000# Operations parameters ## OpenAPI Schema related The following parameters interact with how the OpenAPI schema (and docs) are generated. ### `tags` You can group your API operations using the `tags` argument (`list[str]`). ```python hl_lines="6" @api.get("/hello/") def hello(request, name: str): return {"hello": name} @api.post("/orders/", tags=["orders"]) def create_order(request, order: Order): return {"success": True} ``` Tagged operations may be handled differently by various tools and libraries. For example, the Swagger UI uses tags to group the displayed operations. ![Summary`](../img/operation_tags.png) #### Router tags You can use `tags` argument to apply tags to all operations declared by router: ```python api.add_router("/events/", events_router, tags=["events"]) # or using constructor: router = Router(tags=["events"]) ``` ### `summary` A human-readable name for your operation. By default, it's generated by capitalizing your operation function name: ```python hl_lines="2" @api.get("/hello/") def hello(request, name: str): return {"hello": name} ``` ![Summary`](../img/operation_summary_default.png) If you want to override it or translate it to other language, use the `summary` argument in the `api` decorator. ```python hl_lines="1" @api.get("/hello/", summary="Say Hello") def hello(request, name: str): return {"hello": name} ``` ![Summary`](../img/operation_summary.png) ### `description` To provide more information about your operation, use either the `description` argument or normal Python docstrings: ```python hl_lines="1" @api.post("/orders/", description="Creates an order and updates stock") def create_order(request, order: Order): return {"success": True} ``` ![Summary`](../img/operation_description.png) When you need to provide a long multi line description, you can use Python `docstrings` for the function definition: ```python hl_lines="4 5 6 7" @api.post("/orders/") def create_order(request, order: Order): """ To create an order please provide: - **first_name** - **last_name** - and **list of Items** *(product + amount)* """ return {"success": True} ``` ![Summary`](../img/operation_description_docstring.png) ### `operation_id` The OpenAPI `operationId` is an optional unique string used to identify an operation. If provided, these IDs must be unique among all operations described in your API. By default, **Django Ninja** sets it to `module name` + `function name`. If you want to set it individually for each operation, use the `operation_id` argument: ```python hl_lines="2" ... @api.post("/tasks", operation_id="create_task") def new_task(request): ... ``` If you want to override global behavior, you can inherit the NinjaAPI instance and override the `get_openapi_operation_id` method. It will be called for each operation that you defined, so you can set your custom naming logic like this: ```python hl_lines="5 6 7 9" from ninja import NinjaAPI class MySuperApi(NinjaAPI): def get_openapi_operation_id(self, operation): # here you can access operation ( .path , .view_func, etc) return ... api = MySuperApi() @api.get(...) ... ``` ### `deprecated` Mark an operation as deprecated without removing it by using the `deprecated` argument: ```python hl_lines="1" @api.post("/make-order/", deprecated=True) def some_old_method(request, order: str): return {"success": True} ``` It will be marked as deprecated in the JSON Schema and also in the interactive OpenAPI docs: ![Deprecated](../img/deprecated.png) ### `include_in_schema` If you need to include/exclude some operation from OpenAPI schema use `include_in_schema` argument: ```python hl_lines="1" @api.post("/hidden", include_in_schema=False) def some_hidden_operation(request): pass ``` ## openapi_extra You can customize your OpenAPI schema for specific endpoint (detail [OpenAPI Customize Options](https://swagger.io/docs/specification/about/)) ```python hl_lines="1 26" # You can set requestBody from openapi_extra @api.get( "/tasks", openapi_extra={ "requestBody": { "content": { "application/json": { "schema": { "required": ["email"], "type": "object", "properties": { "name": {"type": "string"}, "phone": {"type": "number"}, "email": {"type": "string"}, }, } } }, "required": True, } }, ) def some_operation(request): pass # You can add additional responses to the automatically generated schema @api.post( "/tasks", openapi_extra={ "responses": { 400: { "description": "Error Response", }, 404: { "description": "Not Found Response", }, }, }, ) def some_operation_2(request): pass ``` ## Response output options There are a few arguments that lets you tune response's output: ### `by_alias` Whether field aliases should be used as keys in the response (defaults to `False`). ### `exclude_unset` Whether fields that were not set when creating the schema, and have their default values, should be excluded from the response (defaults to `False`). ### `exclude_defaults` Whether fields which are equal to their default values (whether set or otherwise) should be excluded from the response (defaults to `False`). ### `exclude_none` Whether fields which are equal to `None` should be excluded from the response (defaults to `False`). ## url_name Allows you to set api endpoint url name (using [django path's naming](https://docs.djangoproject.com/en/stable/topics/http/urls/#reversing-namespaced-urls)) ```python hl_lines="1 7" @api.post("/tasks", url_name='tasks') def some_operation(request): pass # then you can get the url with reverse('api-1.0.0:tasks') ``` See the [Reverse Resolution of URLs](../guides/urls.md) guide for more details. ## Specifying servers If you want to specify single or multiple servers for OpenAPI specification `servers` can be used when initializing NinjaAPI instance: ```python hl_lines="4 5 6 7" from ninja import NinjaAPI api = NinjaAPI( servers=[ {"url": "https://stag.example.com", "description": "Staging env"}, {"url": "https://prod.example.com", "description": "Production env"}, ] ) ``` This will allow switching between environments when using interactive OpenAPI docs: ![Servers](../img/servers.png) vitalik-django-ninja-0b67d47/docs/docs/reference/settings.md000066400000000000000000000001631515660254400240610ustar00rootroot00000000000000# Django Settings ::: ninja.conf.Settings rendering: show_source: False show_root_toc_entry: Falsevitalik-django-ninja-0b67d47/docs/docs/releases.md000066400000000000000000000001671515660254400220720ustar00rootroot00000000000000# Release Notes Follow and subscribe for new releases on GitHub: vitalik-django-ninja-0b67d47/docs/docs/tutorial/000077500000000000000000000000001515660254400216045ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/tutorial/index.md000066400000000000000000000033621515660254400232410ustar00rootroot00000000000000# Tutorial - First Steps This tutorial shows you how to use **Django Ninja** with most of its features. This tutorial assumes that you know at least some basics of the Django Framework, like how to create a project and run it. ## Installation ```console pip install django-ninja ``` !!! note It is not required, but you can also put `ninja` to `INSTALLED_APPS`. In that case the OpenAPI/Swagger UI (or Redoc) will be loaded (faster) from the included JavaScript bundle (otherwise the JavaScript bundle comes from a CDN). ## Create a Django project Start a new Django project (or if you already have an existing Django project, skip to the next step). ``` django-admin startproject myproject ``` ## Create the API Let's create a module for our API. Create an `api.py` file in the same directory location as your Django project's root `urls.py`: ```python from ninja import NinjaAPI api = NinjaAPI() ``` Now go to `urls.py` and add the following: ```python hl_lines="3 7" from django.contrib import admin from django.urls import path from .api import api urlpatterns = [ path("admin/", admin.site.urls), path("api/", api.urls), ] ``` ## Our first operation **Django Ninja** comes with a decorator for each HTTP method (`GET`, `POST`, `PUT`, etc). In our `api.py` file, let's add in a simple "hello world" operation. ```python hl_lines="5-7" from ninja import NinjaAPI api = NinjaAPI() @api.get("/hello") def hello(request): return "Hello world" ``` Now browsing to localhost:8000/api/hello will return a simple JSON response: ```json "Hello world" ``` !!! success Continue on to **[Parsing input](step2.md)**.vitalik-django-ninja-0b67d47/docs/docs/tutorial/other/000077500000000000000000000000001515660254400227255ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/docs/tutorial/other/crud.md000066400000000000000000000161311515660254400242060ustar00rootroot00000000000000# CRUD example **CRUD** - **C**reate, **R**etrieve, **U**pdate, **D**elete are the four basic functions of persistent storage. This example will show you how to implement these functions with **Django Ninja**. Let's say you have the following Django models that you need to perform these operations on: ```python class Department(models.Model): title = models.CharField(max_length=100) class Employee(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) department = models.ForeignKey(Department, on_delete=models.CASCADE) birthdate = models.DateField(null=True, blank=True) cv = models.FileField(null=True, blank=True) ``` Now let's create CRUD operations for the Employee model. ## Create To create an employee lets define an INPUT schema: ```python from datetime import date from ninja import Schema class EmployeeIn(Schema): first_name: str last_name: str department_id: int = None birthdate: date = None ``` This schema will be our input payload: ```python hl_lines="2" @api.post("/employees") def create_employee(request, payload: EmployeeIn): employee = Employee.objects.create(**payload.dict()) return {"id": employee.id} ``` !!! tip `Schema` objects have `.dict()` method with all the schema attributes represented as a dict. You can pass it as `**kwargs` to the Django model's `create` method (or model `__init__`). See the recipe below for handling the file upload (when using Django models): ```python hl_lines="2" from ninja import UploadedFile, File @api.post("/employees") def create_employee(request, payload: EmployeeIn, cv: File[UploadedFile]): payload_dict = payload.dict() employee = Employee(**payload_dict) employee.cv.save(cv.name, cv) # will save model instance as well return {"id": employee.id} ``` If you just need to handle a file upload: ```python hl_lines="2" from django.core.files.storage import FileSystemStorage from ninja import UploadedFile, File STORAGE = FileSystemStorage() @api.post("/upload") def create_upload(request, cv: File[UploadedFile]): filename = STORAGE.save(cv.name, cv) # Handle things further ``` ## Retrieve ### Single object Now to get employee we will define a schema that will describe what our responses will look like. Here we will basically use the same schema as `EmployeeIn`, but will add an extra attribute `id`: ```python hl_lines="2" class EmployeeOut(Schema): id: int first_name: str last_name: str department_id: int = None birthdate: date = None ``` !!! note Defining response schemas are not really required, but when you do define it you will get results validation, documentation and automatic ORM objects to JSON conversions. We will use this schema as the `response` type for our `GET` employee view: ```python hl_lines="1" @api.get("/employees/{employee_id}", response=EmployeeOut) def get_employee(request, employee_id: int): employee = get_object_or_404(Employee, id=employee_id) return employee ``` Notice that we simply returned an employee ORM object, without a need to convert it to a dict. The `response` schema does automatic result validation and conversion to JSON: ```python hl_lines="4" @api.get("/employees/{employee_id}", response=EmployeeOut) def get_employee(request, employee_id: int): employee = get_object_or_404(Employee, id=employee_id) return employee ``` ### List of objects To output a list of employees, we can reuse the same `EmployeeOut` schema. We will just set the `response` schema to a *List* of `EmployeeOut`. ```python hl_lines="3" from typing import List @api.get("/employees", response=List[EmployeeOut]) def list_employees(request): qs = Employee.objects.all() return qs ``` Another cool trick - notice we just returned a Django ORM queryset: ```python hl_lines="4" @api.get("/employees", response=List[EmployeeOut]) def list_employees(request): qs = Employee.objects.all() return qs ``` It automatically gets evaluated, validated and converted to a JSON list! ## Update Update is pretty trivial. We just use the `PUT` method and also pass `employee_id`: ```python hl_lines="1" @api.put("/employees/{employee_id}") def update_employee(request, employee_id: int, payload: EmployeeIn): employee = get_object_or_404(Employee, id=employee_id) for attr, value in payload.dict().items(): setattr(employee, attr, value) employee.save() return {"success": True} ``` **Note** Here we used the `payload.dict` method to set all object attributes: `for attr, value in payload.dict().items()` You can also do this more explicit: ```python employee.first_name = payload.first_name employee.last_name = payload.last_name employee.department_id = payload.department_id employee.birthdate = payload.birthdate ``` **Partial updates** To allow the user to make partial updates, use `payload.dict(exclude_unset=True).items()`. This ensures that only the specified fields get updated. **Enforcing strict field validation** By default, any provided fields that don't exist in the schema will be silently ignored. To raise an error for these invalid fields, you can set `extra = "forbid"` in the model_config. For example: ```python hl_lines="5" from pydantic import ConfigDict class EmployeeIn(Schema): # your fields here... model_config = ConfigDict(extra="forbid") ``` ## Delete Delete is also pretty simple. We just get employee by `id` and delete it from the DB: ```python hl_lines="1 2 4" @api.delete("/employees/{employee_id}") def delete_employee(request, employee_id: int): employee = get_object_or_404(Employee, id=employee_id) employee.delete() return {"success": True} ``` ## Final code Here's a full CRUD example: ```python from datetime import date from typing import List from ninja import NinjaAPI, Schema from django.shortcuts import get_object_or_404 from employees.models import Employee api = NinjaAPI() class EmployeeIn(Schema): first_name: str last_name: str department_id: int = None birthdate: date = None class EmployeeOut(Schema): id: int first_name: str last_name: str department_id: int = None birthdate: date = None @api.post("/employees") def create_employee(request, payload: EmployeeIn): employee = Employee.objects.create(**payload.dict()) return {"id": employee.id} @api.get("/employees/{employee_id}", response=EmployeeOut) def get_employee(request, employee_id: int): employee = get_object_or_404(Employee, id=employee_id) return employee @api.get("/employees", response=List[EmployeeOut]) def list_employees(request): qs = Employee.objects.all() return qs @api.put("/employees/{employee_id}") def update_employee(request, employee_id: int, payload: EmployeeIn): employee = get_object_or_404(Employee, id=employee_id) for attr, value in payload.dict().items(): setattr(employee, attr, value) employee.save() return {"success": True} @api.delete("/employees/{employee_id}") def delete_employee(request, employee_id: int): employee = get_object_or_404(Employee, id=employee_id) employee.delete() return {"success": True} ``` vitalik-django-ninja-0b67d47/docs/docs/tutorial/other/video.md000066400000000000000000000010571515660254400243600ustar00rootroot00000000000000# Video Tutorials ## Sneaky REST APIs With Django Ninja [realpython.com/lessons/sneaky-rest-apis-with-django-ninja-overview/](https://realpython.com/lessons/sneaky-rest-apis-with-django-ninja-overview/) ## Creating a CRUD API with Django-Ninja by BugBytes (English) vitalik-django-ninja-0b67d47/docs/docs/tutorial/step2.md000066400000000000000000000065651515660254400231770ustar00rootroot00000000000000# Tutorial - Parsing Input ## Input from the query string Let's change our operation to accept a name from the URL's query string. To do that, just add a `name` argument to our function. ```python @api.get("/hello") def hello(request, name): return f"Hello {name}" ``` When we provide a name argument, we get the expected (HTTP 200) response. localhost:8000/api/hello?name=you: ```json "Hello you" ``` ### Defaults Not providing the argument will return an HTTP 422 error response. *[HTTP 422]: Unprocessable Entity localhost:8000/api/hello: ```json { "detail": [ { "loc": ["query", "name"], "msg": "field required", "type": "value_error.missing" } ] } ``` We can specify a default for the `name` argument in case it isn't provided: ```python hl_lines="2" @api.get("/hello") def hello(request, name="world"): return f"Hello {name}" ``` ## Input types **Django Ninja** uses standard [Python type hints](https://docs.python.org/3/library/typing.html) to format the input types. If no type is provided then a string is assumed (but it is good practice to provide type hints for all your arguments). Let's add a second operation that does some basic math with integers. ```python hl_lines="5-7" @api.get("/hello") def hello(request, name: str = "world"): return f"Hello {name}" @api.get("/math") def math(request, a: int, b: int): return {"add": a + b, "multiply": a * b} ``` localhost:8000/api/math?a=2&b=3: ```json { "add": 5, "multiply": 6 } ``` ## Input from the path You can declare path "parameters" with the same syntax used by Python format-strings. Any parameters found in the path string will be passed to your function as arguments, rather than expecting them from the query string. ```python hl_lines="1" @api.get("/math/{a}and{b}") def math(request, a: int, b: int): return {"add": a + b, "multiply": a * b} ``` Now we access the math operation from localhost:8000/api/math/2and3. ## Input from the request body We are going to change our `hello` operation to use HTTP `POST` instead, and take arguments from the request body. To specify that arguments come from the body, we need to declare a Schema. *[Schema]: An extension of a Pydantic "Model" ```python hl_lines="1 5-6 8-10" from ninja import NinjaAPI, Schema api = NinjaAPI() class HelloSchema(Schema): name: str = "world" @api.post("/hello") def hello(request, data: HelloSchema): return f"Hello {data.name}" ``` ### Self-documenting API Accessing localhost:8000/api/hello now results in a HTTP 405 error response, since we need to POST to this URL instead. *[HTTP 405]: Method Not Allowed An easy way to do this is to use the Swagger documentation that is automatically created for us, at default URL of "/docs" (appended to our API url root). 1. Visit localhost:8000/api/docs to see the operations we have created 1. Open the `/api/hello` operation 2. Click "Try it out" 3. Change the request body 4. Click "Execute" !!! success Continue on to **[Handling responses](step3.md)**vitalik-django-ninja-0b67d47/docs/docs/tutorial/step3.md000066400000000000000000000026221515660254400231660ustar00rootroot00000000000000# Tutorial - Handling Responses ## Define a response Schema **Django Ninja** allows you to define the schema of your responses both for validation and documentation purposes. We'll create a third operation that will return information about the current Django user. ```python from ninja import Schema class UserSchema(Schema): username: str is_authenticated: bool # Unauthenticated users don't have the following fields, so provide defaults. email: str = None first_name: str = None last_name: str = None @api.get("/me", response=UserSchema) def me(request): return request.user ``` This will convert the Django `User` object into a dictionary of only the defined fields. ### Multiple response types Let's return a different response if the current user is not authenticated. ```python hl_lines="2-5 7-8 10 12-13" class UserSchema(Schema): username: str email: str first_name: str last_name: str class Error(Schema): message: str @api.get("/me", response={200: UserSchema, 403: Error}) def me(request): if not request.user.is_authenticated: return 403, {"message": "Please sign in first"} return request.user ``` As you see, you can return a 2-part tuple which will be interpreted as the HTTP response code and the data. !!! success That concludes the tutorial! Check out the **Other Tutorials** or the **How-to Guides** for more information.vitalik-django-ninja-0b67d47/docs/docs/whatsnew_v1.md000066400000000000000000000124511515660254400225340ustar00rootroot00000000000000# Welcome to Django Ninja 1.0 To get started install latest version with ``` pip install -U django-ninja ``` django-ninja v1 is compatible with Python 3.7 and above. Django ninja series 0.x is still supported but will receive only security updates and critical bug fixes # What's new in Django Ninja 1.0 ## Support for Pydantic2 Pydantic version 2 is re-written in Rust and includes a lot of improvements and features like: - Safer types. - Better extensibility. - Better performance By our tests average project can gain some 10% performance increase on average, while some edge parsing/serializing cases can give you 4x boost. On the other hand it introduces breaking changes and pydantic 1 and 2 are not very compatible - but we tried or best to make this transition easy as possible. So if you used 'Schema' class migration to ninja v1 should be easy. Otherwise follow [pydantic migration guide](https://docs.pydantic.dev/latest/migration/) Some features that are made possible with pydantic2 ### pydantic context Pydantic now supports context during validation and serialization and Django ninja passes "request" object during request and response work ```Python hl_lines="6 7" class Payload(Schema): id: int name: str request_path: str @staticmethod def resolve_request_path(data, context): request = context["request"] return request.get_full_path() ``` During response a "response_code" is also passed to context ## Schema.Meta Pydantic now deprecates BaseModel.Config class. But to keep things consistent with all other django parts we introduce "Meta" class for ModelSchema - which works in a similar way as django's ModelForms: ```Python hl_lines="2 4" class TxItem(ModelSchema): class Meta: model = Transaction fields = ["id", "account", "amount", "timestamp"] ``` (The "Config" class is still supported, but deprecated) ## Shorter / cleaner parameters syntax ```python @api.post('/some') def some_form(request, username: Form[str], password: Form[str]): return True ``` instead of ```python @api.post('/some') def some_form(request, username: str = Form(...), password: str = Form(...)): return True ``` or ```python @api.post('/some') def some_form(request, data: Form[AuthSchema]): return True ``` instead of ```python @api.post('/some') def some_form(request, data: AuthSchema = Form(...)): return True ``` with all the autocompletion in editors On the other hand the **old syntax is still supported** so you can easily port your project to a newer django-ninja version without much haste #### + Annotated typing.Annotated is also supported: ```Python @api.get("/annotated") def annotated(request, data: Annotated[SomeData, Form()]): return {"data": data.dict()} ``` ## Async auth support The async authenticators are finally supported. All you have to do is just add `async` to your `authenticate` method: ```Python class Auth(HttpBearer): async def authenticate(self, request, token): await asyncio.sleep(1) if token == "secret": return token ``` ## Changed CSRF Behavior `csrf=True` requirement is no longer required if you use cookie based authentication. Instead CSRF protection is enabled automatically. This also allow you to mix csrf-protected authenticators and other methods that does not require cookies: ```Python api = NinjaAPI(auth=[django_auth, Auth()]) ``` ## Docs Doc viewer are now configurable and plugable. By default django ninja comes with Swagger and Redoc: ```Python from ninja import NinjaAPI, Redoc, Swagger # use redoc api = NinjaAPI(docs=Redoc())) # use swagger: api = NinjaAPI(docs=Swagger()) # set configuration for swagger: api = NinjaAPI(docs=Swagger({"persistAuthorization": True})) ``` Users now able to create custom docs viewer by inheriting `DocsBase` class ## Router add_router supports string paths: ```Python api = NinjaAPI() api.add_router('/app1', 'myproject.app1.router') api.add_router('/app2', 'myproject.app2.router') api.add_router('/app3', 'myproject.app3.router') api.add_router('/app4', 'myproject.app4.router') api.add_router('/app5', 'myproject.app5.router') ``` ## Decorators When django ninja decorates a view with .get/.post etc. - it wraps the result of the function (which in most cases are not HttpResponse - but some serializable object) so it's not really possible to use some built-in or 3rd-party decorators like: ```python hl_lines="4" from django.views.decorators.cache import cache_page @api.get("/test") @cache_page(5) # <----- will not work def test_view(request): return {"some": "Complex data"} ``` This example does not work. Now django ninja introduces a decorator decorate_view that allows inject decorators that work with http response: ```python hl_lines="1 4" from ninja.decorators import decorate_view @api.get("/test") @decorate_view(cache_page(5)) def test_view(request): return str(datetime.now()) ``` ## Paginations `paginate_queryset` method now takes `request` object #### Backwards incompatible stuff - resolve_xxx(self, ...) - support resolve with (self) is dropped in favor of pydantic build-in functionality - pydantic v1 is no longer supported - python 3.6 is no longer supported BTW - if you like this project and still did not give it a github start - please do so ![github star](img/github-star.png) vitalik-django-ninja-0b67d47/docs/mkdocs.yml000066400000000000000000000065171515660254400210250ustar00rootroot00000000000000site_name: Django Ninja site_description: Django Ninja - Django REST framework with high performance, easy to learn, fast to code. site_url: https://django-ninja.dev repo_name: vitalik/django-ninja repo_url: https://github.com/vitalik/django-ninja edit_uri: "" extra: analytics: provider: google property: G-0E3XZ663ZR extra_css: - extra.css extra_javascript: - javascripts/ask-ai-button.js theme: name: material palette: - media: "(prefers-color-scheme)" primary: green toggle: icon: material/brightness-auto name: Switch to light mode - media: "(prefers-color-scheme: light)" scheme: default primary: green toggle: icon: material/weather-night name: Switch to dark mode - media: "(prefers-color-scheme: dark)" scheme: slate primary: green toggle: icon: material/weather-sunny name: Switch to light mode logo: img/docs-logo.png favicon: img/favicon.svg language: en features: - navigation.expand - search.highlight - search.suggest icon: repo: fontawesome/brands/github-alt nav: - Intro: index.md - motivation.md - Tutorial: - "First Steps": tutorial/index.md - "Parsing Input": tutorial/step2.md - "Handling Responses": tutorial/step3.md - Other Tutorials: - tutorial/other/video.md - tutorial/other/crud.md - How-to Guides: - Parsing input: - guides/input/operations.md - guides/input/path-params.md - guides/input/query-params.md - guides/input/body.md - guides/input/form-params.md - guides/input/file-params.md - guides/input/request-parsers.md - guides/input/filtering.md - Handling responses: - Defining a Schema: guides/response/index.md - guides/response/temporal_response.md - Generating a Schema from Django models: guides/response/django-pydantic.md - Generating a Schema dynamically: guides/response/django-pydantic-create-schema.md - guides/response/config-pydantic.md - guides/response/pagination.md - guides/response/response-renderers.md - Splitting your API with Routers: guides/routers.md - guides/decorators.md - guides/authentication.md - guides/throttling.md - guides/testing.md - guides/api-docs.md - guides/errors.md - guides/urls.md - guides/async-support.md - guides/versioning.md - Reference: - NinjaAPI class: reference/api.md - reference/csrf.md - reference/operations-parameters.md - reference/management-commands.md - reference/settings.md - releases.md - help.md - Enhancement Proposals: - Intro: proposals/index.md - proposals/cbv.md - proposals/v1.md - What's new in V1: whatsnew_v1.md markdown_extensions: - markdown_include.include - markdown.extensions.codehilite: guess_lang: false # Uncomment these 2 lines during development to more easily add highlights #- pymdownx.highlight: # linenums: true - abbr - codehilite - admonition - pymdownx.details - pymdownx.superfences plugins: - search - mkdocstrings: handlers: python: setup_commands: - from django.conf import settings - settings.configure() vitalik-django-ninja-0b67d47/docs/requirements.txt000066400000000000000000000002421515660254400222730ustar00rootroot00000000000000mkdocs==1.5.3 mkdocs-autorefs==1.0.1 mkdocs-material==9.5.4 mkdocs-material-extensions==1.3.1 markdown-include==0.8.1 mkdocstrings[python]==0.24.0 griffe==0.47.0 vitalik-django-ninja-0b67d47/docs/src/000077500000000000000000000000001515660254400176005ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/index001.py000066400000000000000000000004221515660254400215000ustar00rootroot00000000000000from django.contrib import admin from django.urls import path from ninja import NinjaAPI api = NinjaAPI() @api.get("/add") def add(request, a: int, b: int): return {"result": a + b} urlpatterns = [ path("admin/", admin.site.urls), path("api/", api.urls), ] vitalik-django-ninja-0b67d47/docs/src/tutorial/000077500000000000000000000000001515660254400214435ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/000077500000000000000000000000001515660254400244625ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/apikey01.py000066400000000000000000000006721515660254400264640ustar00rootroot00000000000000from ninja.security import APIKeyQuery from someapp.models import Client class ApiKey(APIKeyQuery): param_name = "api_key" def authenticate(self, request, key): try: return Client.objects.get(key=key) except Client.DoesNotExist: pass api_key = ApiKey() @api.get("/apikey", auth=api_key) def apikey(request): assert isinstance(request.auth, Client) return f"Hello {request.auth}" vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/apikey02.py000066400000000000000000000005021515660254400264550ustar00rootroot00000000000000from ninja.security import APIKeyHeader class ApiKey(APIKeyHeader): param_name = "X-API-Key" def authenticate(self, request, key): if key == "supersecret": return key header_key = ApiKey() @api.get("/headerkey", auth=header_key) def apikey(request): return f"Token = {request.auth}" vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/apikey03.py000066400000000000000000000004521515660254400264620ustar00rootroot00000000000000from ninja.security import APIKeyCookie class CookieKey(APIKeyCookie): def authenticate(self, request, key): if key == "supersecret": return key cookie_key = CookieKey() @api.get("/cookiekey", auth=cookie_key) def apikey(request): return f"Token = {request.auth}" vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/basic01.py000066400000000000000000000004721515660254400262610ustar00rootroot00000000000000from ninja.security import HttpBasicAuth class BasicAuth(HttpBasicAuth): def authenticate(self, request, username, password): if username == "admin" and password == "secret": return username @api.get("/basic", auth=BasicAuth()) def basic(request): return {"httpuser": request.auth} vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/bearer01.py000066400000000000000000000004171515660254400264370ustar00rootroot00000000000000from ninja.security import HttpBearer class AuthBearer(HttpBearer): def authenticate(self, request, token): if token == "supersecret": return token @api.get("/bearer", auth=AuthBearer()) def bearer(request): return {"token": request.auth} vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/bearer02.py000066400000000000000000000010431515660254400264340ustar00rootroot00000000000000from ninja import NinjaAPI from ninja.security import HttpBearer api = NinjaAPI() class InvalidToken(Exception): pass @api.exception_handler(InvalidToken) def on_invalid_token(request, exc): return api.create_response(request, {"detail": "Invalid token supplied"}, status=401) class AuthBearer(HttpBearer): def authenticate(self, request, token): if token == "supersecret": return token raise InvalidToken @api.get("/bearer", auth=AuthBearer()) def bearer(request): return {"token": request.auth} vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/code001.py000066400000000000000000000002751515660254400261730ustar00rootroot00000000000000from ninja import NinjaAPI from ninja.security import django_auth api = NinjaAPI() @api.get("/pets", auth=django_auth) def pets(request): return f"Authenticated user {request.auth}" vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/code002.py000066400000000000000000000003451515660254400261720ustar00rootroot00000000000000def ip_whitelist(request): if request.META["REMOTE_ADDR"] == "8.8.8.8": return "8.8.8.8" @api.get("/ipwhitelist", auth=ip_whitelist) def ipwhitelist(request): return f"Authenticated client, IP = {request.auth}" vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/global01.py000066400000000000000000000010361515660254400264350ustar00rootroot00000000000000from ninja import NinjaAPI, Form from ninja.security import HttpBearer class GlobalAuth(HttpBearer): def authenticate(self, request, token): if token == "supersecret": return token api = NinjaAPI(auth=GlobalAuth()) # @api.get(...) # def ... # @api.post(...) # def ... @api.post("/token", auth=None) # < overriding global auth def get_token(request, username: str = Form(...), password: str = Form(...)): if username == "admin" and password == "giraffethinnknslong": return {"token": "supersecret"} vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/multiple01.py000066400000000000000000000006061515660254400270320ustar00rootroot00000000000000from ninja.security import APIKeyQuery, APIKeyHeader class AuthCheck: def authenticate(self, request, key): if key == "supersecret": return key class QueryKey(AuthCheck, APIKeyQuery): pass class HeaderKey(AuthCheck, APIKeyHeader): pass @api.get("/multiple", auth=[QueryKey(), HeaderKey()]) def multiple(request): return f"Token = {request.auth}" vitalik-django-ninja-0b67d47/docs/src/tutorial/authentication/schema01.py000066400000000000000000000000001515660254400264230ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/tutorial/body/000077500000000000000000000000001515660254400224005ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/tutorial/body/code01.py000066400000000000000000000003511515660254400240240ustar00rootroot00000000000000from typing import Optional from ninja import Schema class Item(Schema): name: str description: Optional[str] = None price: float quantity: int @api.post("/items") def create(request, item: Item): return item vitalik-django-ninja-0b67d47/docs/src/tutorial/body/code02.py000066400000000000000000000003771515660254400240350ustar00rootroot00000000000000from ninja import Schema class Item(Schema): name: str description: str = None price: float quantity: int @api.put("/items/{item_id}") def update(request, item_id: int, item: Item): return {"item_id": item_id, "item": item.dict()} vitalik-django-ninja-0b67d47/docs/src/tutorial/body/code03.py000066400000000000000000000004201515660254400240230ustar00rootroot00000000000000from ninja import Schema class Item(Schema): name: str description: str = None price: float quantity: int @api.post("/items/{item_id}") def update(request, item_id: int, item: Item, q: str): return {"item_id": item_id, "item": item.dict(), "q": q} vitalik-django-ninja-0b67d47/docs/src/tutorial/form/000077500000000000000000000000001515660254400224065ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/tutorial/form/code01.py000066400000000000000000000003171515660254400240340ustar00rootroot00000000000000from ninja import Form, Schema class Item(Schema): name: str description: str = None price: float quantity: int @api.post("/items") def create(request, item: Form[Item]): return item vitalik-django-ninja-0b67d47/docs/src/tutorial/form/code02.py000066400000000000000000000004341515660254400240350ustar00rootroot00000000000000from ninja import Form, Schema class Item(Schema): name: str description: str = None price: float quantity: int @api.post("/items/{item_id}") def update(request, item_id: int, q: str, item: Form[Item]): return {"item_id": item_id, "item": item.dict(), "q": q} vitalik-django-ninja-0b67d47/docs/src/tutorial/form/code03.py000066400000000000000000000012361515660254400240370ustar00rootroot00000000000000from ninja import Form, Schema from typing import Annotated, TypeVar from pydantic import WrapValidator from pydantic_core import PydanticUseDefault def _empty_str_to_default(v, handler, info): if isinstance(v, str) and v == '': raise PydanticUseDefault return handler(v) T = TypeVar('T') EmptyStrToDefault = Annotated[T, WrapValidator(_empty_str_to_default)] class Item(Schema): name: str description: str = None price: EmptyStrToDefault[float] = 0.0 quantity: EmptyStrToDefault[int] = 0 in_stock: EmptyStrToDefault[bool] = True @api.post("/items-blank-default") def update(request, item: Form[Item]): return item.dict() vitalik-django-ninja-0b67d47/docs/src/tutorial/path/000077500000000000000000000000001515660254400223775ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/tutorial/path/code01.py000066400000000000000000000001361515660254400240240ustar00rootroot00000000000000@api.get("/items/{item_id}") def read_item(request, item_id): return {"item_id": item_id} vitalik-django-ninja-0b67d47/docs/src/tutorial/path/code010.py000066400000000000000000000004771515660254400241140ustar00rootroot00000000000000import datetime from ninja import Schema, Path class PathDate(Schema): year: int month: int day: int def value(self): return datetime.date(self.year, self.month, self.day) @api.get("/events/{year}/{month}/{day}") def events(request, date: Path[PathDate]): return {"date": date.value()} vitalik-django-ninja-0b67d47/docs/src/tutorial/path/code02.py000066400000000000000000000001431515660254400240230ustar00rootroot00000000000000@api.get("/items/{item_id}") def read_item(request, item_id: int): return {"item_id": item_id} vitalik-django-ninja-0b67d47/docs/src/tutorial/query/000077500000000000000000000000001515660254400226105ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/docs/src/tutorial/query/code01.py000066400000000000000000000003201515660254400242300ustar00rootroot00000000000000weapons = ["Ninjato", "Shuriken", "Katana", "Kama", "Kunai", "Naginata", "Yari"] @api.get("/weapons") def list_weapons(request, limit: int = 10, offset: int = 0): return weapons[offset: offset + limit] vitalik-django-ninja-0b67d47/docs/src/tutorial/query/code010.py000066400000000000000000000005511515660254400243160ustar00rootroot00000000000000import datetime from typing import List from pydantic import Field from ninja import Query, Schema class Filters(Schema): limit: int = 100 offset: int = None query: str = None category__in: List[str] = Field(None, alias="categories") @api.get("/filter") def events(request, filters: Query[Filters]): return {"filters": filters.dict()} vitalik-django-ninja-0b67d47/docs/src/tutorial/query/code02.py000066400000000000000000000004031515660254400242330ustar00rootroot00000000000000weapons = ["Ninjato", "Shuriken", "Katana", "Kama", "Kunai", "Naginata", "Yari"] @api.get("/weapons/search") def search_weapons(request, q: str, offset: int = 0): results = [w for w in weapons if q in w.lower()] return results[offset : offset + 10] vitalik-django-ninja-0b67d47/docs/src/tutorial/query/code03.py000066400000000000000000000002351515660254400242370ustar00rootroot00000000000000from datetime import date @api.get("/example") def example(request, s: str = None, b: bool = None, d: date = None, i: int = None): return [s, b, d, i] vitalik-django-ninja-0b67d47/mypy.ini000066400000000000000000000007521515660254400175640ustar00rootroot00000000000000[mypy] python_version = 3.12 show_column_numbers = True show_error_codes = True follow_imports = normal ignore_missing_imports = True # Exclude directories exclude = ^(\.venv|venv|env)/ # be strict disallow_untyped_calls = True warn_return_any = True strict_optional = True warn_no_return = True warn_redundant_casts = True warn_unused_ignores = True disallow_untyped_defs = True check_untyped_defs = True no_implicit_reexport = True [mypy-ninja.compatibility.*] ignore_errors = True vitalik-django-ninja-0b67d47/ninja/000077500000000000000000000000001515660254400171605ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/__init__.py000066400000000000000000000022121515660254400212660ustar00rootroot00000000000000"""Django Ninja - Fast Django REST framework""" __version__ = "1.6.2" from pydantic import Field from ninja.files import UploadedFile from ninja.filter_schema import FilterConfigDict, FilterLookup, FilterSchema from ninja.main import NinjaAPI from ninja.openapi.docs import Redoc, Swagger from ninja.orm import ModelSchema from ninja.params import ( Body, BodyEx, Cookie, CookieEx, File, FileEx, Form, FormEx, Header, HeaderEx, P, Path, PathEx, Query, QueryEx, ) from ninja.patch_dict import PatchDict from ninja.responses import Status from ninja.router import Router from ninja.schema import Schema from ninja.streaming import JSONL, SSE __all__ = [ "Field", "UploadedFile", "NinjaAPI", "Body", "Cookie", "File", "Form", "Header", "Path", "Query", "BodyEx", "CookieEx", "FileEx", "FormEx", "HeaderEx", "PathEx", "QueryEx", "Router", "P", "Schema", "ModelSchema", "FilterSchema", "FilterLookup", "FilterConfigDict", "Swagger", "Redoc", "PatchDict", "SSE", "JSONL", "Status", ] vitalik-django-ninja-0b67d47/ninja/compatibility/000077500000000000000000000000001515660254400220315ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/compatibility/__init__.py000066400000000000000000000000001515660254400241300ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/compatibility/files.py000066400000000000000000000045001515660254400235040ustar00rootroot00000000000000from typing import Any, List from asgiref.sync import iscoroutinefunction, sync_to_async from django.conf import settings from django.http import HttpRequest from django.utils.decorators import sync_and_async_middleware from ninja.conf import settings as ninja_settings from ninja.params.models import FileModel FIX_MIDDLEWARE_PATH: str = "ninja.compatibility.files.fix_request_files_middleware" FIX_METHODS = ninja_settings.FIX_REQUEST_FILES_METHODS def need_to_fix_request_files(methods: List[str], params_models: List[Any]) -> bool: has_files_params = any( issubclass(model_class, FileModel) for model_class in params_models ) method_needs_fix = bool(set(methods) & FIX_METHODS) middleware_installed = FIX_MIDDLEWARE_PATH in settings.MIDDLEWARE return has_files_params and method_needs_fix and not middleware_installed @sync_and_async_middleware def fix_request_files_middleware(get_response: Any) -> Any: """ This middleware fixes long historical Django behavior where request.FILES is only populated for POST requests. https://code.djangoproject.com/ticket/12635 """ if iscoroutinefunction(get_response): async def async_middleware(request: HttpRequest) -> Any: if ( request.method in FIX_METHODS and request.content_type != "application/json" ): initial_method = request.method request.method = "POST" request.META["REQUEST_METHOD"] = "POST" await sync_to_async(request._load_post_and_files)() request.META["REQUEST_METHOD"] = initial_method request.method = initial_method return await get_response(request) return async_middleware else: def sync_middleware(request: HttpRequest) -> Any: if ( request.method in FIX_METHODS and request.content_type != "application/json" ): initial_method = request.method request.method = "POST" request.META["REQUEST_METHOD"] = "POST" request._load_post_and_files() request.META["REQUEST_METHOD"] = initial_method request.method = initial_method return get_response(request) return sync_middleware vitalik-django-ninja-0b67d47/ninja/compatibility/streaming.py000066400000000000000000000065051515660254400244020ustar00rootroot00000000000000"""Compatibility layer for async streaming responses. Django 4.2+ supports passing async iterators to StreamingHttpResponse. On older versions, async generators must be eagerly consumed into a list. TODO: When dropping Django < 4.2 support: 1. Remove this module entirely. 2. In AsyncOperation._async_stream_response (ninja/operation.py), pass the async content generator directly to StreamingHttpResponse and copy temporal_response headers lazily inside the generator: async def content_iter(): async for chunk in content_gen: yield chunk for key, value in temporal_response.items(): if key.lower() != "content-type": response[key] = value for cookie_name, cookie in temporal_response.cookies.items(): response.cookies[cookie_name] = cookie response = StreamingHttpResponse( content_iter(), content_type=..., status=..., ) """ from typing import Any, Dict import django from django.http import HttpResponse, StreamingHttpResponse ASYNC_STREAMING = django.VERSION >= (4, 2) def _copy_temporal_headers( temporal_response: HttpResponse, response: StreamingHttpResponse ) -> None: """Copy headers and cookies from temporal response, skipping Content-Type.""" for key, value in temporal_response.items(): if key.lower() != "content-type": response[key] = value for cookie_name, cookie in temporal_response.cookies.items(): response.cookies[cookie_name] = cookie if ASYNC_STREAMING: async def create_streaming_response( content_gen: Any, *, content_type: str, status: int, temporal_response: HttpResponse, extra_headers: Dict[str, str], ) -> StreamingHttpResponse: """Create a StreamingHttpResponse from an async content generator. Django 4.2+: passes the async generator directly and copies temporal response headers/cookies lazily after the generator is exhausted. """ async def with_lazy_headers() -> Any: async for chunk in content_gen: yield chunk _copy_temporal_headers(temporal_response, response) response = StreamingHttpResponse( with_lazy_headers(), content_type=content_type, status=status, ) for key, value in extra_headers.items(): response[key] = value return response else: async def create_streaming_response( content_gen: Any, *, content_type: str, status: int, temporal_response: HttpResponse, extra_headers: Dict[str, str], ) -> StreamingHttpResponse: """Create a StreamingHttpResponse from an async content generator. Django < 4.2: eagerly consumes the async generator into a list since StreamingHttpResponse does not support async iterators. """ chunks = [] async for chunk in content_gen: chunks.append(chunk) response = StreamingHttpResponse( iter(chunks), content_type=content_type, status=status, ) _copy_temporal_headers(temporal_response, response) for key, value in extra_headers.items(): response[key] = value return response vitalik-django-ninja-0b67d47/ninja/compatibility/util.py000066400000000000000000000020231515660254400233550ustar00rootroot00000000000000import sys from typing import Union __all__ = ["UNION_TYPES", "get_annotations_from_namespace"] # python3.10+ syntax of creating a union or optional type (with str | int) # UNION_TYPES allows to check both universes if types are a union try: from types import UnionType UNION_TYPES = (Union, UnionType) except ImportError: UNION_TYPES = (Union,) # python3.14+ no longer puts __annotations__ in the class namespace dict # during metaclass __new__; instead an __annotate__ function is used (PEP 749) if sys.version_info >= (3, 14): import annotationlib def get_annotations_from_namespace(namespace: dict) -> dict: ann = annotationlib.get_annotate_from_class_namespace(namespace) if ann is not None: return annotationlib.call_annotate_function( ann, format=annotationlib.Format.VALUE ) return namespace.get("__annotations__", {}) else: def get_annotations_from_namespace(namespace: dict) -> dict: return namespace.get("__annotations__", {}) vitalik-django-ninja-0b67d47/ninja/conf.py000066400000000000000000000027651515660254400204710ustar00rootroot00000000000000from math import inf from typing import Dict, Optional, Set, Tuple from django.conf import settings as django_settings from pydantic import BaseModel, ConfigDict, Field class Settings(BaseModel): model_config = ConfigDict(from_attributes=True) # Pagination PAGINATION_CLASS: str = Field( "ninja.pagination.LimitOffsetPagination", alias="NINJA_PAGINATION_CLASS" ) PAGINATION_DEFAULT_ORDERING: Tuple[str, ...] = Field( ("-pk",), alias="NINJA_PAGINATION_DEFAULT_ORDERING" ) PAGINATION_MAX_OFFSET: int = Field(100, alias="NINJA_PAGINATION_MAX_OFFSET") PAGINATION_PER_PAGE: int = Field(100, alias="NINJA_PAGINATION_PER_PAGE") PAGINATION_MAX_PER_PAGE_SIZE: int = Field(100, alias="NINJA_MAX_PER_PAGE_SIZE") PAGINATION_MAX_LIMIT: int = Field(inf, alias="NINJA_PAGINATION_MAX_LIMIT") # type: ignore # Throttling NUM_PROXIES: Optional[int] = Field(None, alias="NINJA_NUM_PROXIES") DEFAULT_THROTTLE_RATES: Dict[str, Optional[str]] = Field( { "auth": "10000/day", "user": "10000/day", "anon": "1000/day", }, alias="NINJA_DEFAULT_THROTTLE_RATES", ) FIX_REQUEST_FILES_METHODS: Set[str] = Field( {"PUT", "PATCH", "DELETE"}, alias="NINJA_FIX_REQUEST_FILES_METHODS" ) settings = Settings.model_validate(django_settings) if hasattr(django_settings, "NINJA_DOCS_VIEW"): raise Exception( "NINJA_DOCS_VIEW is removed. Use NinjaAPI(docs=...) instead" ) # pragma: no cover vitalik-django-ninja-0b67d47/ninja/constants.py000066400000000000000000000005541515660254400215520ustar00rootroot00000000000000from typing import Any, Dict, Optional __all__ = ["NOT_SET"] class NOT_SET_TYPE: def __repr__(self) -> str: # pragma: no cover return f"{__name__}.{self.__class__.__name__}" def __copy__(self) -> Any: return NOT_SET def __deepcopy__(self, memodict: Optional[Dict] = None) -> Any: return NOT_SET NOT_SET = NOT_SET_TYPE() vitalik-django-ninja-0b67d47/ninja/decorators.py000066400000000000000000000032301515660254400216750ustar00rootroot00000000000000from functools import partial from typing import Any, Callable, Tuple from typing_extensions import Literal from ninja.operation import Operation from ninja.types import TCallable from ninja.utils import contribute_operation_callback # Type for decorator modes DecoratorMode = Literal["operation", "view"] # Since @api.method decorator is applied to function # that is not always returns a HttpResponse object # there is no way to apply some standard decorators form # django stdlib or public plugins # # @decorate_view allows to apply any view decorator to Ninja api operation # # @api.get("/some") # @decorate_view(cache_page(60 * 15)) # <------- # def some(request): # ... # def decorate_view(*decorators: Callable[..., Any]) -> Callable[[TCallable], TCallable]: def outer_wrapper(op_func: TCallable) -> TCallable: if hasattr(op_func, "_ninja_operation"): # Means user used decorate_view on top of @api.method _apply_decorators(decorators, op_func._ninja_operation) # type: ignore else: # Means user used decorate_view after(bottom) of @api.method contribute_operation_callback( op_func, partial(_apply_decorators, decorators) ) return op_func return outer_wrapper def _apply_decorators( decorators: Tuple[Callable[..., Any]], operation: Operation ) -> None: # Track decorators for cloning support if not hasattr(operation, "_run_decorators"): operation._run_decorators = [] # type: ignore for deco in decorators: operation.run = deco(operation.run) # type: ignore operation._run_decorators.append(deco) # type: ignore vitalik-django-ninja-0b67d47/ninja/errors.py000066400000000000000000000071721515660254400210550ustar00rootroot00000000000000import logging import traceback from functools import partial from typing import TYPE_CHECKING, Generic, List, Optional, TypeVar import pydantic from django.conf import settings from django.http import Http404, HttpRequest, HttpResponse from ninja.types import DictStrAny if TYPE_CHECKING: from ninja import NinjaAPI # pragma: no cover from ninja.params.models import ParamModel # pragma: no cover __all__ = [ "ConfigError", "AuthenticationError", "AuthorizationError", "ValidationError", "HttpError", "set_default_exc_handlers", ] logger = logging.getLogger("django") class ConfigError(Exception): pass TModel = TypeVar("TModel", bound="ParamModel") class ValidationErrorContext(Generic[TModel]): """ The full context of a `pydantic.ValidationError`, including all information needed to produce a `ninja.errors.ValidationError`. """ def __init__( self, pydantic_validation_error: pydantic.ValidationError, model: TModel ): self.pydantic_validation_error = pydantic_validation_error self.model = model class ValidationError(Exception): """ This exception raised when operation params do not validate Note: this is not the same as pydantic.ValidationError the errors attribute as well holds the location of the error(body, form, query, etc.) """ def __init__(self, errors: List[DictStrAny]) -> None: self.errors = errors super().__init__(errors) class HttpError(Exception): def __init__(self, status_code: int, message: str) -> None: self.status_code = status_code self.message = message super().__init__(status_code, message) def __str__(self) -> str: return self.message class AuthenticationError(HttpError): def __init__(self, status_code: int = 401, message: str = "Unauthorized") -> None: super().__init__(status_code=status_code, message=message) class AuthorizationError(HttpError): def __init__(self, status_code: int = 403, message: str = "Forbidden") -> None: super().__init__(status_code=status_code, message=message) class Throttled(HttpError): def __init__(self, wait: Optional[int]) -> None: self.wait = wait super().__init__(status_code=429, message="Too many requests.") def set_default_exc_handlers(api: "NinjaAPI") -> None: api.add_exception_handler( Exception, partial(_default_exception, api=api), ) api.add_exception_handler( Http404, partial(_default_404, api=api), ) api.add_exception_handler( HttpError, partial(_default_http_error, api=api), ) api.add_exception_handler( ValidationError, partial(_default_validation_error, api=api), ) def _default_404(request: HttpRequest, exc: Exception, api: "NinjaAPI") -> HttpResponse: msg = "Not Found" if settings.DEBUG: msg += f": {exc}" return api.create_response(request, {"detail": msg}, status=404) def _default_http_error( request: HttpRequest, exc: HttpError, api: "NinjaAPI" ) -> HttpResponse: return api.create_response(request, {"detail": str(exc)}, status=exc.status_code) def _default_validation_error( request: HttpRequest, exc: ValidationError, api: "NinjaAPI" ) -> HttpResponse: return api.create_response(request, {"detail": exc.errors}, status=422) def _default_exception( request: HttpRequest, exc: Exception, api: "NinjaAPI" ) -> HttpResponse: if not settings.DEBUG: raise exc # let django deal with it logger.exception(exc) tb = traceback.format_exc() return HttpResponse(tb, status=500, content_type="text/plain") vitalik-django-ninja-0b67d47/ninja/files.py000066400000000000000000000016711515660254400206410ustar00rootroot00000000000000from typing import Any, Callable, Dict from django.core.files.uploadedfile import UploadedFile as DjangoUploadedFile from pydantic_core import core_schema __all__ = ["UploadedFile"] class UploadedFile(DjangoUploadedFile): @classmethod def __get_pydantic_json_schema__( cls, core_schema: Any, handler: Callable[..., Any] ) -> Dict: # calling handler(core_schema) here raises an exception json_schema: Dict[str, str] = {} json_schema.update(type="string", format="binary") return json_schema @classmethod def _validate(cls, v: Any, _: Any) -> Any: if not isinstance(v, DjangoUploadedFile): raise ValueError(f"Expected UploadFile, received: {type(v)}") return v @classmethod def __get_pydantic_core_schema__( cls, source: Any, handler: Callable[..., Any] ) -> Any: return core_schema.with_info_plain_validator_function(cls._validate) vitalik-django-ninja-0b67d47/ninja/filter_schema.py000066400000000000000000000226401515660254400223430ustar00rootroot00000000000000import warnings from typing import Any, List, Optional, TypeVar, Union, cast from django.core.exceptions import ImproperlyConfigured from django.db.models import Q, QuerySet from pydantic import ConfigDict from pydantic.fields import FieldInfo from typing_extensions import Literal from .constants import NOT_SET from .schema import Schema # XOR is available only in Django 4.1+: https://docs.djangoproject.com/en/4.1/ref/models/querysets/#xor ExpressionConnector = Literal["AND", "OR", "XOR"] DEFAULT_IGNORE_NONE: bool = True DEFAULT_CLASS_LEVEL_EXPRESSION_CONNECTOR: ExpressionConnector = "AND" DEFAULT_FIELD_LEVEL_EXPRESSION_CONNECTOR: ExpressionConnector = "OR" class FilterLookup: """ Annotation class for specifying database query lookups in FilterSchema fields. Example usage: class MyFilterSchema(FilterSchema): name: Annotated[Union[str, None], FilterLookup("name__icontains")] = None search: Annotated[Union[str, None], FilterLookup(["name__icontains", "email__icontains"])] = None """ def __init__( self, q: Union[str, List[str], None], *, expression_connector: ExpressionConnector = DEFAULT_FIELD_LEVEL_EXPRESSION_CONNECTOR, ignore_none: bool = DEFAULT_IGNORE_NONE, ): """ Args: q: Database lookup expression(s). Can be: - A string like "name__icontains" - A list of strings like ["name__icontains", "email__icontains"] - Use "__" prefix for implicit field name: "__icontains" becomes "fieldname__icontains" expression_connector: How to combine multiple field-level expressions ("OR", "AND", "XOR"). Default is "OR". ignore_none: Whether to ignore None values for this field specifically. Default is True. """ self.q = q self.expression_connector = expression_connector self.ignore_none = ignore_none T = TypeVar("T", bound=QuerySet) class FilterConfigDict(ConfigDict, total=False): ignore_none: bool expression_connector: ExpressionConnector class FilterSchema(Schema): model_config = FilterConfigDict( ignore_none=DEFAULT_IGNORE_NONE, expression_connector=DEFAULT_CLASS_LEVEL_EXPRESSION_CONNECTOR, ) def custom_expression(self) -> Q: """ Implement this method to return a combination of filters that will be used """ raise NotImplementedError def get_filter_expression(self) -> Q: """ Returns a Q expression based on the current filters """ try: return self.custom_expression() except NotImplementedError: return self._connect_fields() def filter(self, queryset: T) -> T: return queryset.filter(self.get_filter_expression()) def _get_filter_lookup( self, field_name: str, field_info: FieldInfo ) -> Optional[FilterLookup]: if not hasattr(field_info, "metadata") or not field_info.metadata: return None filter_lookups = [ metadata_item for metadata_item in field_info.metadata if isinstance(metadata_item, FilterLookup) ] if len(filter_lookups) == 0: return None elif len(filter_lookups) == 1: return filter_lookups[0] else: raise ImproperlyConfigured( f"Multiple FilterLookup instances found in metadata of {self.__class__.__name__}.{field_name}.\n" f"Use at most one FilterLookup instance per field.\n" f"If you need multiple lookups, specify them as a list in a single FilterLookup:\n" f"{field_name}: Annotated[{field_info.annotation}, FilterLookup(['lookup1', 'lookup2', ...])]" ) def _get_field_q_expression( self, field_name: str, field_info: FieldInfo, ) -> Union[str, List[str], None]: filter_lookup = self._get_filter_lookup(field_name, field_info) if filter_lookup: return filter_lookup.q # Legacy approach, consider removing in future versions return cast( Union[str, List[str], None], self._get_from_deprecated_field_extra(field_name, field_info, "q"), ) def _get_field_expression_connector( self, field_name: str, field_info: FieldInfo, ) -> Union[ExpressionConnector, None]: filter_lookup = self._get_filter_lookup(field_name, field_info) if filter_lookup: return filter_lookup.expression_connector # Legacy approach, consider removing in future versions return cast( Union[ExpressionConnector, None], self._get_from_deprecated_field_extra( field_name, field_info, "expression_connector" ), ) def _get_field_ignore_none( self, field_name: str, field_info: FieldInfo ) -> Union[bool, None]: filter_lookup = self._get_filter_lookup(field_name, field_info) if filter_lookup: return filter_lookup.ignore_none # Legacy approach, consider removing in future versions return cast( Union[bool, None], self._get_from_deprecated_field_extra( field_name, field_info, "ignore_none" ), ) def _resolve_field_expression( self, field_name: str, field_value: Any, field_info: FieldInfo ) -> Q: func = getattr(self, f"filter_{field_name}", None) if callable(func): return cast(Q, func(field_value)) q_expression = self._get_field_q_expression(field_name, field_info) expression_connector = ( self._get_field_expression_connector(field_name, field_info) or DEFAULT_FIELD_LEVEL_EXPRESSION_CONNECTOR ) if not q_expression: return Q(**{field_name: field_value}) elif isinstance(q_expression, str): if q_expression.startswith("__"): q_expression = f"{field_name}{q_expression}" return Q(**{q_expression: field_value}) elif isinstance(q_expression, list) and all( isinstance(item, str) for item in q_expression ): q = Q() for q_expression_part in q_expression: if q_expression_part.startswith("__"): q_expression_part = f"{field_name}{q_expression_part}" q = q._combine( # type: ignore[attr-defined] Q(**{q_expression_part: field_value}), expression_connector, ) return q else: raise ImproperlyConfigured( f"Field {field_name} of {self.__class__.__name__} defines an invalid value for 'q'.\n" f"Use FilterLookup annotation: {field_name}: Annotated[{field_info.annotation}, FilterLookup('lookup')]\n" f"Alternatively, you can implement {self.__class__.__name__}.filter_{field_name} that must return a Q expression for that field" ) def _connect_fields(self) -> Q: q = Q() class_ignore_none = self.model_config.get("ignore_none", DEFAULT_IGNORE_NONE) for field_name, field_info in self.__class__.model_fields.items(): filter_value = getattr(self, field_name) # class-level ignore_none set to False (non-default) takes precedence over field-level ignore_none if class_ignore_none is False: ignore_none = False else: field_ignore_none = self._get_field_ignore_none(field_name, field_info) if field_ignore_none is not None: ignore_none = field_ignore_none else: ignore_none = DEFAULT_IGNORE_NONE # Resolve Q expression for a field even if we skip it due to None value # So that improperly configured fields are easier to detect field_q = self._resolve_field_expression( field_name, filter_value, field_info ) if filter_value is None and ignore_none: continue q = q._combine( # type: ignore[attr-defined] field_q, self.model_config.get( "expression_connector", DEFAULT_CLASS_LEVEL_EXPRESSION_CONNECTOR ), ) return q def _get_from_deprecated_field_extra( self, field_name: str, field_info: FieldInfo, attr: str ) -> Union[Any, None]: """ Backward-compatible shim which looks up filtering parameters in the Field's **extra kwargs. Consider removing this method in favor of FilterLookup annotation class. """ field_extra = cast(dict, field_info.json_schema_extra) or {} value = field_extra.get(attr, NOT_SET) if value is not NOT_SET: warnings.warn( f"Using Pydantic Field with extra keyword arguments ('{attr}') " f"in field {self.__class__.__name__}.{field_name} is deprecated. Please use ninja.FilterLookup instead:\n" f" from typing import Annotated\n" f" from ninja import FilterLookup, FilterSchema\n\n" f" class {self.__class__.__name__}(FilterSchema):\n" f" {field_name}: Annotated[Optional[...], FilterLookup(q='...', ...)] = None", DeprecationWarning, stacklevel=4, ) return value return None vitalik-django-ninja-0b67d47/ninja/main.py000066400000000000000000000557351515660254400204750ustar00rootroot00000000000000from typing import ( TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, TypeVar, Union, ) from django.http import HttpRequest, HttpResponse from django.urls import URLPattern, URLResolver, reverse from django.utils.module_loading import import_string from ninja.constants import NOT_SET, NOT_SET_TYPE from ninja.decorators import DecoratorMode from ninja.errors import ( ConfigError, ValidationError, ValidationErrorContext, set_default_exc_handlers, ) from ninja.openapi import get_schema from ninja.openapi.docs import DocsBase, Swagger from ninja.openapi.schema import OpenAPISchema from ninja.openapi.urls import get_openapi_urls, get_root_url from ninja.parser import Parser from ninja.renderers import BaseRenderer, JSONRenderer from ninja.router import BoundRouter, Router, RouterMount from ninja.throttling import BaseThrottle from ninja.types import DictStrAny, TCallable if TYPE_CHECKING: from .operation import Operation # pragma: no cover __all__ = ["NinjaAPI"] _E = TypeVar("_E", bound=Exception) Exc = Union[_E, Type[_E]] ExcHandler = Callable[[HttpRequest, Exc[_E]], HttpResponse] class NinjaAPI: """ Ninja API """ def __init__( self, *, title: str = "NinjaAPI", version: str = "1.0.0", description: str = "", openapi_url: Optional[str] = "/openapi.json", docs: DocsBase = Swagger(), docs_url: Optional[str] = "/docs", docs_decorator: Optional[Callable[[TCallable], TCallable]] = None, servers: Optional[List[DictStrAny]] = None, urls_namespace: Optional[str] = None, auth: Optional[Union[Sequence[Callable], Callable, NOT_SET_TYPE]] = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, renderer: Optional[BaseRenderer] = None, parser: Optional[Parser] = None, default_router: Optional[Router] = None, openapi_extra: Optional[Dict[str, Any]] = None, ): """ Args: title: A title for the api. description: A description for the api. version: The API version. urls_namespace: The Django URL namespace for the API. If not provided, the namespace will be ``"api-" + self.version``. openapi_url: The relative URL to serve the openAPI spec. openapi_extra: Additional attributes for the openAPI spec. docs_url: The relative URL to serve the API docs. servers: List of target hosts used in openAPI spec. auth (Callable | Sequence[Callable] | NOT_SET | None): Authentication class renderer: Default response renderer parser: Default request parser """ self.title = title self.version = version self.description = description self.openapi_url = openapi_url self.docs = docs self.docs_url = docs_url self.docs_decorator = docs_decorator self.servers = servers or [] self.urls_namespace = urls_namespace or f"api-{self.version}" self.renderer = renderer or JSONRenderer() self.parser = parser or Parser() self.openapi_extra = openapi_extra or {} self._exception_handlers: Dict[Exc, ExcHandler] = {} self.set_default_exception_handlers() self.auth: Optional[Union[Sequence[Callable], NOT_SET_TYPE]] if callable(auth): self.auth = [auth] else: self.auth = auth self.throttle = throttle # Top-level router registrations (new architecture) # Stores (prefix, router, auth, throttle, tags, url_name_prefix) for each add_router call self._router_registrations: List[ Tuple[str, Router, Any, Any, Optional[List[str]], Optional[str]] ] = [] self._bound_routers_cache: Optional[List[BoundRouter]] = None # Backward compat: keep _routers list populated self._routers: List[Tuple[str, Router]] = [] self.default_router = default_router or Router() self.add_router("", self.default_router) def get( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: """ `GET` operation. See operations parameters reference. """ return self.default_router.get( path, auth=auth is NOT_SET and self.auth or auth, throttle=throttle is NOT_SET and self.throttle or throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def post( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: """ `POST` operation. See operations parameters reference. """ return self.default_router.post( path, auth=auth is NOT_SET and self.auth or auth, throttle=throttle is NOT_SET and self.throttle or throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def delete( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: """ `DELETE` operation. See operations parameters reference. """ return self.default_router.delete( path, auth=auth is NOT_SET and self.auth or auth, throttle=throttle is NOT_SET and self.throttle or throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def patch( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: """ `PATCH` operation. See operations parameters reference. """ return self.default_router.patch( path, auth=auth is NOT_SET and self.auth or auth, throttle=throttle is NOT_SET and self.throttle or throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def put( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: """ `PUT` operation. See operations parameters reference. """ return self.default_router.put( path, auth=auth is NOT_SET and self.auth or auth, throttle=throttle is NOT_SET and self.throttle or throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def api_operation( self, methods: List[str], path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: return self.default_router.api_operation( methods, path, auth=auth is NOT_SET and self.auth or auth, throttle=throttle is NOT_SET and self.throttle or throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def add_decorator( self, decorator: Callable, mode: DecoratorMode = "operation", ) -> None: """ Add a decorator to be applied to all operations in the entire API. Args: decorator: The decorator function to apply mode: "operation" (default) applies after validation, "view" applies before validation """ # Store decorator on default router - will be inherited by all routers during build self.default_router.add_decorator(decorator, mode) def add_router( self, prefix: str, router: Union[Router, str], *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, tags: Optional[List[str]] = None, url_name_prefix: Optional[str] = None, parent_router: Optional[Router] = None, ) -> None: """ Add a router to this API. Args: prefix: URL prefix for all routes in the router router: Router instance or import path string auth: Authentication override for this router throttle: Throttle override for this router tags: Tags override for this router url_name_prefix: Prefix for URL names (required when mounting same router multiple times) parent_router: Internal use - parent router for nested routers """ # Prevent adding routers after URLs have been generated if self._bound_routers_cache is not None: raise ConfigError( "Cannot add routers after URLs have been generated. " "Add all routers before accessing api.urls" ) if isinstance(router, str): router = import_string(router) assert isinstance(router, Router) # Check for duplicate router template - require url_name_prefix existing_templates = {reg[1] for reg in self._router_registrations} if router in existing_templates and url_name_prefix is None: raise ConfigError( "Router is already mounted to this API. When mounting the same router " "multiple times, you must provide unique url_name_prefix for each mount." ) # Store registration for later processing during URL generation # This allows child routers to be added after add_router() is called self._router_registrations.append(( prefix, router, auth, throttle, tags, url_name_prefix, )) # Backward compat: keep _routers list updated (just the top-level router) self._routers.append((prefix, router)) @property def urls(self) -> Tuple[List[Union[URLResolver, URLPattern]], str, str]: """ str: URL configuration Returns: Django URL configuration """ self._validate() return ( self._get_urls(), "ninja", self.urls_namespace.split(":")[-1], # ^ if api included into nested urls, we only care about last bit here ) def _get_bound_routers(self) -> List[BoundRouter]: """Get or create bound router instances.""" if self._bound_routers_cache is None: # Build mounts from registrations (delayed to capture all child routers) all_mounts: List[RouterMount] = [] for ( prefix, router, auth, throttle, tags, url_name_prefix, ) in self._router_registrations: # Get API-level decorators from default router api_decorators = ( self.default_router._decorators if router is not self.default_router else [] ) # Build mount configurations (non-mutating) # Pass auth/throttle/tags so they can be inherited by children mounts = router.build_routers( prefix, api_decorators, inherited_auth=auth, inherited_throttle=throttle, inherited_tags=tags, ) # Apply mount-level overrides to the first (parent) mount # build_routers() always returns at least one mount (the router itself) first_mount = mounts[0] if auth is not NOT_SET: first_mount.auth = auth if throttle is not NOT_SET: first_mount.throttle = throttle if tags is not None: first_mount.tags = tags # Apply url_name_prefix to all mounts if url_name_prefix is not None: for mount in mounts: mount.url_name_prefix = url_name_prefix all_mounts.extend(mounts) # Create bound routers from mounts self._bound_routers_cache = [ BoundRouter(mount, self) for mount in all_mounts ] # Freeze all templates after binding for mount in all_mounts: mount.template._freeze() # Update _routers for backward compat (include all nested routers) self._routers = [(m.prefix, m.template) for m in all_mounts] return self._bound_routers_cache def _get_urls(self) -> List[Union[URLResolver, URLPattern]]: result = get_openapi_urls(self) for bound_router in self._get_bound_routers(): result.extend(bound_router.urls_paths(bound_router.prefix)) result.append(get_root_url(self)) return result def get_root_path(self, path_params: DictStrAny) -> str: name = f"{self.urls_namespace}:api-root" return reverse(name, kwargs=path_params) def create_response( self, request: HttpRequest, data: Any, *, status: Optional[int] = None, temporal_response: Optional[HttpResponse] = None, ) -> HttpResponse: if temporal_response: status = temporal_response.status_code assert status content = self.renderer.render(request, data, response_status=status) if temporal_response: response = temporal_response response.content = content else: response = HttpResponse( content, status=status, content_type=self.get_content_type() ) return response def create_temporal_response(self, request: HttpRequest) -> HttpResponse: return HttpResponse("", content_type=self.get_content_type()) def get_content_type(self) -> str: return f"{self.renderer.media_type}; charset={self.renderer.charset}" def get_openapi_schema( self, *, path_prefix: Optional[str] = None, path_params: Optional[DictStrAny] = None, ) -> OpenAPISchema: if path_prefix is None: path_prefix = self.get_root_path(path_params or {}) return get_schema(api=self, path_prefix=path_prefix) def get_openapi_operation_id(self, operation: "Operation") -> str: name = operation.view_func.__name__ module = operation.view_func.__module__ return (module + "_" + name).replace(".", "_") def get_operation_url_name(self, operation: "Operation", router: Router) -> str: """ Get the default URL name to use for an operation if it wasn't explicitly provided. """ return operation.view_func.__name__ def add_exception_handler( self, exc_class: Type[_E], handler: ExcHandler[_E] ) -> None: assert issubclass(exc_class, Exception) self._exception_handlers[exc_class] = handler def exception_handler( self, exc_class: Type[Exception] ) -> Callable[[TCallable], TCallable]: def decorator(func: TCallable) -> TCallable: self.add_exception_handler(exc_class, func) return func return decorator def set_default_exception_handlers(self) -> None: set_default_exc_handlers(self) def on_exception(self, request: HttpRequest, exc: Exc[_E]) -> HttpResponse: handler = self._lookup_exception_handler(exc) if handler is None: raise exc return handler(request, exc) def validation_error_from_error_contexts( self, error_contexts: List[ValidationErrorContext] ) -> ValidationError: errors: List[Dict[str, Any]] = [] for context in error_contexts: model = context.model e = context.pydantic_validation_error for i in e.errors(include_url=False): i["loc"] = ( model.__ninja_param_source__, ) + model.__ninja_flatten_map_reverse__.get(i["loc"], i["loc"]) # removing pydantic hints del i["input"] # type: ignore if ( "ctx" in i and "error" in i["ctx"] and isinstance(i["ctx"]["error"], Exception) ): i["ctx"]["error"] = str(i["ctx"]["error"]) errors.append(dict(i)) return ValidationError(errors) def _lookup_exception_handler(self, exc: Exc[_E]) -> Optional[ExcHandler[_E]]: for cls in type(exc).__mro__: if cls in self._exception_handlers: return self._exception_handlers[cls] return None def _validate(self) -> None: # Registry check no longer needed - routers are independent templates # and can be reused across multiple APIs without conflicts pass vitalik-django-ninja-0b67d47/ninja/management/000077500000000000000000000000001515660254400212745ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/management/__init__.py000066400000000000000000000000001515660254400233730ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/management/commands/000077500000000000000000000000001515660254400230755ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/management/commands/__init__.py000066400000000000000000000000001515660254400251740ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/management/commands/export_openapi_schema.py000066400000000000000000000056041515660254400300300ustar00rootroot00000000000000import json from pathlib import Path from typing import Any, Optional from django.core.management.base import BaseCommand, CommandError, CommandParser from django.urls.base import resolve from django.utils.module_loading import import_string from ninja.main import NinjaAPI from ninja.management.utils import command_docstring from ninja.responses import NinjaJSONEncoder class Command(BaseCommand): """ Example: ```terminal python manage.py export_openapi_schema ``` ```terminal python manage.py export_openapi_schema --api project.urls.api ``` """ help = "Exports Open API schema" def _get_api_instance(self, api_path: Optional[str] = None) -> NinjaAPI: if not api_path: try: return resolve("/api/").func.keywords["api"] # type: ignore except AttributeError: raise CommandError( "No NinjaAPI instance found; please specify one with --api" ) from None try: api = import_string(api_path) except ImportError: raise CommandError( f"Module or attribute for {api_path} not found!" ) from None if not isinstance(api, NinjaAPI): raise CommandError(f"{api_path} is not instance of NinjaAPI!") return api def add_arguments(self, parser: CommandParser) -> None: parser.add_argument( "--api", dest="api", default=None, type=str, help="Specify api instance module", ) parser.add_argument( "--output", dest="output", default=None, type=str, help="Output schema to a file (outputs to stdout if omitted).", ) parser.add_argument( "--indent", dest="indent", default=None, type=int, help="JSON indent" ) parser.add_argument( "--sorted", dest="sort_keys", default=False, action="store_true", help="Sort Json keys", ) parser.add_argument( "--ensure-ascii", dest="ensure_ascii", default=False, action="store_true", help="ensure_ascii for JSON output", ) def handle(self, *args: Any, **options: Any) -> None: api = self._get_api_instance(options["api"]) schema = api.get_openapi_schema() result = json.dumps( schema, cls=NinjaJSONEncoder, indent=options["indent"], sort_keys=options["sort_keys"], ensure_ascii=options["ensure_ascii"], ) if options["output"]: with Path(options["output"]).open("wb") as f: f.write(result.encode()) else: self.stdout.write(result) __doc__ = command_docstring(Command) vitalik-django-ninja-0b67d47/ninja/management/utils.py000066400000000000000000000035371515660254400230160ustar00rootroot00000000000000import textwrap from typing import Type from django.core.management.base import BaseCommand def command_docstring(cmd: Type[BaseCommand]) -> str: base_args = [] if cmd is not BaseCommand: # pragma: no branch base_parser = cmd().create_parser("base", "") for group in base_parser._action_groups: for action in group._group_actions: base_args.append(",".join(action.option_strings)) parser = cmd().create_parser("command", "") doc = parser.description or "" if cmd.__doc__: # pragma: no branch if doc: # pragma: no branch doc += "\n\n" doc += textwrap.dedent(cmd.__doc__) args = [] for group in parser._action_groups: for action in group._group_actions: if "--help" in action.option_strings: continue name = ",".join(action.option_strings) action_type = action.type if not action_type and action.nargs != 0: action_type = str if action_type: if isinstance(action_type, type): # pragma: no branch action_type = action_type.__name__ name += f" ({action_type})" help = action.help or "" if help and not action.required and action.nargs != 0: if not help.endswith("."): help += "." if action.default is not None: help += f" Defaults to {action.default}." else: help += " Optional." args.append((name, help)) # Sort args from this class first, then base args. args.sort(key=lambda o: (o[0] in base_args, o[0])) if args: # pragma: no branch doc += "\n\nAttributes:" for name, description in args: doc += f"\n {name}: {description}" return doc vitalik-django-ninja-0b67d47/ninja/openapi/000077500000000000000000000000001515660254400206135ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/openapi/__init__.py000066400000000000000000000001061515660254400227210ustar00rootroot00000000000000from ninja.openapi.schema import get_schema __all__ = ["get_schema"] vitalik-django-ninja-0b67d47/ninja/openapi/docs.py000066400000000000000000000072331515660254400221220ustar00rootroot00000000000000import json from abc import ABC, abstractmethod from pathlib import Path from typing import TYPE_CHECKING, Any, Optional from django.conf import settings from django.http import HttpRequest, HttpResponse from django.shortcuts import render from django.urls import reverse from ninja.constants import NOT_SET from ninja.types import DictStrAny if TYPE_CHECKING: # if anyone knows a cleaner way to make mypy happy - welcome from ninja import NinjaAPI # pragma: no cover ABS_TPL_PATH = Path(__file__).parent.parent / "templates/ninja/" class DocsBase(ABC): @abstractmethod def render_page( self, request: HttpRequest, api: "NinjaAPI", **kwargs: Any ) -> HttpResponse: pass # pragma: no cover def get_openapi_url(self, api: "NinjaAPI", path_params: DictStrAny) -> str: return reverse(f"{api.urls_namespace}:openapi-json", kwargs=path_params) class Swagger(DocsBase): template = "ninja/swagger.html" template_cdn = str(ABS_TPL_PATH / "swagger_cdn.html") default_settings = { "layout": "BaseLayout", "deepLinking": True, } def __init__(self, settings: Optional[DictStrAny] = None): self.settings = {} self.settings.update(self.default_settings) if settings: self.settings.update(settings) def render_page( self, request: HttpRequest, api: "NinjaAPI", **kwargs: Any ) -> HttpResponse: self.settings["url"] = self.get_openapi_url(api, kwargs) context = { "swagger_settings": json.dumps(self.settings, indent=1), "api": api, "add_csrf": _csrf_needed(api), } return render_template(request, self.template, self.template_cdn, context) class Redoc(DocsBase): template = "ninja/redoc.html" template_cdn = str(ABS_TPL_PATH / "redoc_cdn.html") default_settings: DictStrAny = {} def __init__(self, settings: Optional[DictStrAny] = None): self.settings = {} self.settings.update(self.default_settings) if settings: self.settings.update(settings) def render_page( self, request: HttpRequest, api: "NinjaAPI", **kwargs: Any ) -> HttpResponse: context = { "redoc_settings": json.dumps(self.settings, indent=1), "openapi_json_url": self.get_openapi_url(api, kwargs), "api": api, } return render_template(request, self.template, self.template_cdn, context) def render_template( request: HttpRequest, template: str, template_cdn: str, context: DictStrAny ) -> HttpResponse: """ I do not really want ninja to be required in INSTALLED_APPS to ease installation so it automatically detects - if ninja is in INSTALLED_APPS - then we render with django.shortcuts.render otherwise - rendering custom html with swagger js from cdn """ if "ninja" in settings.INSTALLED_APPS: return render(request, template, context) else: return _render_cdn_template(request, template_cdn, context) def _render_cdn_template( request: HttpRequest, template_path: str, context: Optional[DictStrAny] = None ) -> HttpResponse: "this is helper to find and render html template when ninja is not in INSTALLED_APPS" from django.template import RequestContext, Template tpl = Template(Path(template_path).read_text()) html = tpl.render(RequestContext(request, context)) return HttpResponse(html) def _csrf_needed(api: "NinjaAPI") -> bool: """ Check if any of the API's auth handlers require CSRF protection. """ if not api.auth or api.auth == NOT_SET: return False return any(getattr(a, "csrf", False) for a in api.auth) # type: ignore vitalik-django-ninja-0b67d47/ninja/openapi/schema.py000066400000000000000000000352311515660254400224310ustar00rootroot00000000000000import itertools import re from http.client import responses from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Set, Tuple from django.utils.termcolors import make_style from pydantic.json_schema import JsonSchemaMode from ninja.constants import NOT_SET from ninja.operation import Operation from ninja.params.models import TModel, TModels from ninja.schema import NinjaGenerateJsonSchema from ninja.types import DictStrAny from ninja.utils import normalize_path if TYPE_CHECKING: from ninja import NinjaAPI # pragma: no cover REF_TEMPLATE: str = "#/components/schemas/{model}" BODY_CONTENT_TYPES: Dict[str, str] = { "body": "application/json", "form": "application/x-www-form-urlencoded", "file": "multipart/form-data", } def get_schema(api: "NinjaAPI", path_prefix: str = "") -> "OpenAPISchema": openapi = OpenAPISchema(api, path_prefix) return openapi bold_red_style = make_style(opts=("bold",), fg="red") class OpenAPISchema(dict): def __init__(self, api: "NinjaAPI", path_prefix: str) -> None: self.api = api self.path_prefix = path_prefix self.schemas: DictStrAny = {} self.securitySchemes: DictStrAny = {} self.all_operation_ids: Set = set() extra_info = api.openapi_extra.get("info", {}) super().__init__([ ("openapi", "3.1.0"), ( "info", { "title": api.title, "version": api.version, "description": api.description, **extra_info, }, ), ("paths", self.get_paths()), ("components", self.get_components()), ("servers", api.servers), ]) for k, v in api.openapi_extra.items(): if k not in self: self[k] = v def get_paths(self) -> DictStrAny: result: DictStrAny = {} # Use bound routers to ensure operations have correct auth/throttle/tags for bound_router in self.api._get_bound_routers(): for path, path_view in bound_router.path_operations.items(): full_path = "/".join([i for i in (bound_router.prefix, path) if i]) full_path = "/" + self.path_prefix + full_path full_path = normalize_path(full_path) full_path = re.sub( r"{[^}:]+:", "{", full_path ) # remove path converters path_methods = self.methods(path_view.operations) if path_methods: try: result[full_path].update(path_methods) except KeyError: result[full_path] = path_methods return result def methods(self, operations: list) -> DictStrAny: result = {} for op in operations: if op.include_in_schema: operation_details = self.operation_details(op) for method in op.methods: result[method.lower()] = operation_details return result def deep_dict_update( self, main_dict: Dict[Any, Any], update_dict: Dict[Any, Any] ) -> None: for key in update_dict: if ( key in main_dict and isinstance(main_dict[key], dict) and isinstance(update_dict[key], dict) ): self.deep_dict_update( main_dict[key], update_dict[key] ) # pragma: no cover elif ( key in main_dict and isinstance(main_dict[key], list) and isinstance(update_dict[key], list) ): main_dict[key].extend(update_dict[key]) else: main_dict[key] = update_dict[key] def operation_details(self, operation: Operation) -> DictStrAny: op_id = operation.operation_id or self.api.get_openapi_operation_id(operation) if op_id in self.all_operation_ids: print( bold_red_style( f'Warning: operation_id "{op_id}" is already used (Try giving a different name to: {operation.view_func.__module__}.{operation.view_func.__name__})' ) ) self.all_operation_ids.add(op_id) result = { "operationId": op_id, "summary": operation.summary, "parameters": self.operation_parameters(operation), "responses": self.responses(operation), } if operation.description: result["description"] = operation.description if operation.tags: result["tags"] = operation.tags if operation.deprecated: result["deprecated"] = operation.deprecated # type: ignore body = self.request_body(operation) if body: result["requestBody"] = body security = self.operation_security(operation) if security: result["security"] = security if operation.openapi_extra: self.deep_dict_update(result, operation.openapi_extra) return result def operation_parameters(self, operation: Operation) -> List[DictStrAny]: result = [] for model in operation.models: if model.__ninja_param_source__ not in BODY_CONTENT_TYPES: result.extend(self._extract_parameters(model)) return result def _extract_parameters(self, model: TModel) -> List[DictStrAny]: result = [] schema = model.model_json_schema( ref_template=REF_TEMPLATE, schema_generator=NinjaGenerateJsonSchema, ) required = set(schema.get("required", [])) properties = schema["properties"] if "$defs" in schema: self.add_schema_definitions(schema["$defs"]) for name, details in properties.items(): is_required = name in required p_name: str p_schema: DictStrAny p_required: bool for p_name, p_schema, p_required in flatten_properties( name, details, is_required, schema.get("$defs", {}) ): if not p_schema.get("include_in_schema", True): continue param = { "in": model.__ninja_param_source__, "name": p_name, "schema": p_schema, "required": p_required, } # copy description from schema description to param description if "description" in p_schema: param["description"] = p_schema["description"] if "examples" in p_schema: param["examples"] = p_schema["examples"] elif "example" in p_schema: param["example"] = p_schema["example"] if "deprecated" in p_schema: param["deprecated"] = p_schema["deprecated"] result.append(param) return result def _flatten_schema(self, model: TModel) -> DictStrAny: params = self._extract_parameters(model) flattened = { "title": model.__name__, # type: ignore "type": "object", "properties": {p["name"]: p["schema"] for p in params}, } required = [p["name"] for p in params if p["required"]] if required: flattened["required"] = required return flattened def _create_schema_from_model( self, model: TModel, by_alias: bool = True, remove_level: bool = True, mode: JsonSchemaMode = "validation", ) -> Tuple[DictStrAny, bool]: if hasattr(model, "__ninja_flatten_map__"): schema = self._flatten_schema(model) else: schema = model.model_json_schema( ref_template=REF_TEMPLATE, by_alias=by_alias, schema_generator=NinjaGenerateJsonSchema, mode=mode, ).copy() # move Schemas from definitions if schema.get("$defs"): self.add_schema_definitions(schema.pop("$defs")) if remove_level and len(schema["properties"]) == 1: name, details = list(schema["properties"].items())[0] # ref = details["$ref"] required = name in schema.get("required", {}) return details, required else: return schema, True def _create_multipart_schema_from_models( self, models: TModels, mode: JsonSchemaMode = "validation", ) -> Tuple[DictStrAny, str]: # We have File and Form or Body, so we need to use multipart (File) content_type = BODY_CONTENT_TYPES["file"] # get the various schemas result = merge_schemas([ self._create_schema_from_model(model, remove_level=False)[0] for model in models ]) result["title"] = "MultiPartBodyParams" return result, content_type def request_body(self, operation: Operation) -> DictStrAny: models = [ m for m in operation.models if m.__ninja_param_source__ in BODY_CONTENT_TYPES ] if not models: return {} if len(models) == 1: model = models[0] content_type = BODY_CONTENT_TYPES[model.__ninja_param_source__] schema, required = self._create_schema_from_model( model, remove_level=model.__ninja_param_source__ == "body", mode="validation", ) else: schema, content_type = self._create_multipart_schema_from_models( models, mode="validation" ) required = True return { "content": {content_type: {"schema": schema}}, "required": required, } def responses(self, operation: Operation) -> Dict[int, DictStrAny]: assert bool(operation.response_models), f"{operation.response_models} empty" result = {} for status, model in operation.response_models.items(): if status == Ellipsis: continue # it's not yet clear what it means if user wants to output any other code description = responses.get(status, "Unknown Status Code") details: Dict[int, Any] = {status: {"description": description}} if model not in [None, NOT_SET]: # ::TODO:: test this: by_alias == True schema = self._create_schema_from_model( model, by_alias=operation.by_alias, mode="serialization" )[0] if operation.stream_format is not None: details[status]["content"] = ( operation.stream_format.openapi_content_schema(schema) ) else: details[status]["content"] = { self.api.renderer.media_type: {"schema": schema} } result.update(details) return result def operation_security(self, operation: Operation) -> Optional[List[DictStrAny]]: if not operation.auth_callbacks: return None result = [] for auth in operation.auth_callbacks: if hasattr(auth, "openapi_security_schema"): scopes: List[DictStrAny] = [] # TODO: scopes name = auth.__class__.__name__ result.append({name: scopes}) # TODO: check if unique self.securitySchemes[name] = auth.openapi_security_schema return result def get_components(self) -> DictStrAny: result = {"schemas": self.schemas} if self.securitySchemes: result["securitySchemes"] = self.securitySchemes return result def add_schema_definitions(self, definitions: dict) -> None: # TODO: check if schema["definitions"] are unique # if not - workaround (maybe use pydantic.schema.schema(models)) to process list of models # assert set(definitions.keys()) - set(self.schemas.keys()) == set() # ::TODO:: this is broken in interesting ways for by_alias, # because same schema (name) can have different values self.schemas.update(definitions) def flatten_properties( prop_name: str, prop_details: DictStrAny, prop_required: bool, definitions: DictStrAny, ) -> Generator[Tuple[str, DictStrAny, bool], None, None]: """ extracts all nested model's properties into flat properties (used f.e. in GET params with multiple arguments and models) """ if "allOf" in prop_details: resolve_allOf(prop_details, definitions) if len(prop_details["allOf"]) == 1 and "enum" in prop_details["allOf"][0]: # is_required = "default" not in prop_details yield prop_name, prop_details, prop_required else: # pragma: no cover # TODO: this code was for pydanitc 1.7+ ... <2.9 - check if this is still needed for item in prop_details["allOf"]: yield from flatten_properties("", item, True, definitions) elif "items" in prop_details and "$ref" in prop_details["items"]: def_name = prop_details["items"]["$ref"].rsplit("/", 1)[-1] prop_details["items"].update(definitions[def_name]) del prop_details["items"]["$ref"] # seems num data is there so ref not needed yield prop_name, prop_details, prop_required elif "$ref" in prop_details: def_name = prop_details["$ref"].split("/")[-1] definition = definitions[def_name] yield from flatten_properties(prop_name, definition, prop_required, definitions) elif "properties" in prop_details: required = set(prop_details.get("required", [])) for k, v in prop_details["properties"].items(): is_required = k in required yield from flatten_properties(k, v, is_required, definitions) else: yield prop_name, prop_details, prop_required def resolve_allOf(details: DictStrAny, definitions: DictStrAny) -> None: """ resolves all $ref's in 'allOf' section """ for item in details["allOf"]: if "$ref" in item: def_name = item["$ref"].rsplit("/", 1)[-1] item.update(definitions[def_name]) del item["$ref"] def merge_schemas(schemas: List[DictStrAny]) -> DictStrAny: result = schemas[0] for scm in schemas[1:]: result["properties"].update(scm["properties"]) required_list = result.get("required", []) required_list.extend( itertools.chain.from_iterable( schema.get("required", ()) for schema in schemas[1:] ) ) if required_list: result["required"] = required_list return result vitalik-django-ninja-0b67d47/ninja/openapi/urls.py000066400000000000000000000022271515660254400221550ustar00rootroot00000000000000from functools import partial from typing import TYPE_CHECKING, Any, List from django.urls import path from .views import default_home, openapi_json, openapi_view if TYPE_CHECKING: from ninja import NinjaAPI # pragma: no cover __all__ = ["get_openapi_urls", "get_root_url"] def get_openapi_urls(api: "NinjaAPI") -> List[Any]: result = [] if api.openapi_url: view = partial(openapi_json, api=api) if api.docs_decorator: view = api.docs_decorator(view) # type: ignore result.append( path(api.openapi_url.lstrip("/"), view, name="openapi-json"), ) assert ( api.openapi_url != api.docs_url ), "Please use different urls for openapi_url and docs_url" if api.docs_url: view = partial(openapi_view, api=api) if api.docs_decorator: view = api.docs_decorator(view) # type: ignore result.append( path(api.docs_url.lstrip("/"), view, name="openapi-view"), ) return result def get_root_url(api: "NinjaAPI") -> Any: return path("", partial(default_home, api=api), name="api-root") vitalik-django-ninja-0b67d47/ninja/openapi/views.py000066400000000000000000000016561515660254400223320ustar00rootroot00000000000000from typing import TYPE_CHECKING, Any, NoReturn from django.http import Http404, HttpRequest, HttpResponse from ninja.openapi.docs import DocsBase from ninja.responses import Response if TYPE_CHECKING: # if anyone knows a cleaner way to make mypy happy - welcome from ninja import NinjaAPI # pragma: no cover def default_home(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -> NoReturn: "This view is mainly needed to determine the full path for API operations" docs_url = f"{request.path}{api.docs_url}".replace("//", "/") raise Http404(f"docs_url = {docs_url}") def openapi_json(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -> HttpResponse: schema = api.get_openapi_schema(path_params=kwargs) return Response(schema) def openapi_view(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -> HttpResponse: docs: DocsBase = api.docs return docs.render_page(request, api, **kwargs) vitalik-django-ninja-0b67d47/ninja/operation.py000066400000000000000000000645671515660254400215540ustar00rootroot00000000000000import inspect import warnings from typing import ( TYPE_CHECKING, Any, Callable, Coroutine, Dict, Iterable, List, Optional, Sequence, Type, Union, cast, ) import pydantic from asgiref.sync import async_to_sync, sync_to_async from django.http import ( HttpRequest, HttpResponse, HttpResponseNotAllowed, StreamingHttpResponse, ) from django.http.response import HttpResponseBase from pydantic import BaseModel from ninja.compatibility.files import FIX_MIDDLEWARE_PATH, need_to_fix_request_files from ninja.compatibility.streaming import create_streaming_response from ninja.constants import NOT_SET, NOT_SET_TYPE from ninja.errors import ( AuthenticationError, ConfigError, Throttled, ValidationErrorContext, ) from ninja.params.models import TModels from ninja.responses import Status from ninja.schema import Schema, pydantic_version from ninja.signature import ViewSignature, is_async from ninja.streaming import StreamFormat, _serialize_item, _StreamAlias from ninja.throttling import BaseThrottle from ninja.types import DictStrAny from ninja.utils import is_async_callable if TYPE_CHECKING: from ninja import NinjaAPI # pragma: no cover __all__ = ["Operation", "PathView", "ResponseObject"] class Operation: def __init__( self, path: str, methods: List[str], view_func: Callable, *, auth: Optional[Union[Sequence[Callable], Callable, NOT_SET_TYPE]] = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, include_in_schema: bool = True, url_name: Optional[str] = None, openapi_extra: Optional[Dict[str, Any]] = None, ) -> None: self.is_async = False self.path: str = path self.methods: List[str] = methods self.view_func: Callable = view_func self.api: NinjaAPI = cast("NinjaAPI", None) self.csrf_exempt: bool = getattr(view_func, "csrf_exempt", False) if url_name is not None: self.url_name = url_name self.auth_param: Optional[Union[Sequence[Callable], Callable, object]] = auth self.auth_callbacks: Sequence[Callable] = [] self._set_auth(auth) if isinstance(throttle, BaseThrottle): throttle = [throttle] self.throttle_param = throttle self.throttle_objects: List[BaseThrottle] = [] if throttle is not NOT_SET: for th in throttle: # type: ignore assert isinstance( th, BaseThrottle ), "Throttle should be an instance of BaseThrottle" self.throttle_objects.append(th) self.signature = ViewSignature(self.path, self.view_func) self.models: TModels = self.signature.models self.stream_format: Optional[Type[StreamFormat]] = None self.stream_item_model: Optional[Type[Schema]] = None self.response_models: Dict[Any, Any] if isinstance(response, _StreamAlias): self.stream_format = response.format_cls self.stream_item_model = self._create_response_model(response.item_type) self.response_models = {200: self.stream_item_model} elif response is NOT_SET: self.response_models = {200: NOT_SET} elif isinstance(response, dict): self.response_models = self._create_response_model_multiple(response) else: self.response_models = {200: self._create_response_model(response)} if need_to_fix_request_files(methods, self.models): raise ConfigError( f"Router '{path}' has method(s) {methods} that require fixing request.FILES. " f"Please add '{FIX_MIDDLEWARE_PATH}' to settings.MIDDLEWARE" ) self.operation_id = operation_id self.summary = summary or self.view_func.__name__.title().replace("_", " ") self.description = description or self.signature.docstring self.tags = tags self.deprecated = deprecated self.include_in_schema = include_in_schema self.openapi_extra = openapi_extra # Exporting models params self.by_alias = by_alias or False self.exclude_unset = exclude_unset or False self.exclude_defaults = exclude_defaults or False self.exclude_none = exclude_none or False if hasattr(view_func, "_ninja_contribute_to_operation"): # Allow 3rd party code to contribute to the operation behavior callbacks: List[Callable] = view_func._ninja_contribute_to_operation for callback in callbacks: callback(self) def clone(self) -> "Operation": """ Create a fresh copy of this operation for binding to an API. This method is used when mounting the same router multiple times to ensure each mount has independent operation instances. """ # Create instance without calling __init__ to avoid expensive processing cloned = object.__new__(self.__class__) # Copy all essential attributes cloned.is_async = self.is_async cloned.path = self.path cloned.methods = list(self.methods) cloned.view_func = self.view_func cloned.api = cast("NinjaAPI", None) # Will be set during binding cloned.csrf_exempt = self.csrf_exempt # Copy url_name if it exists if hasattr(self, "url_name"): cloned.url_name = self.url_name # Copy auth settings cloned.auth_param = self.auth_param cloned.auth_callbacks = list(self.auth_callbacks) # Copy throttle settings cloned.throttle_param = self.throttle_param cloned.throttle_objects = list(self.throttle_objects) # Copy signature and models (immutable after creation, safe to share) cloned.signature = self.signature cloned.models = self.models # Copy streaming attributes cloned.stream_format = self.stream_format cloned.stream_item_model = self.stream_item_model # Copy response models (dict copy for isolation) cloned.response_models = dict(self.response_models) # Copy metadata cloned.operation_id = self.operation_id cloned.summary = self.summary cloned.description = self.description cloned.tags = list(self.tags) if self.tags else None cloned.deprecated = self.deprecated cloned.include_in_schema = self.include_in_schema cloned.openapi_extra = dict(self.openapi_extra) if self.openapi_extra else None # Copy export model params cloned.by_alias = self.by_alias cloned.exclude_unset = self.exclude_unset cloned.exclude_defaults = self.exclude_defaults cloned.exclude_none = self.exclude_none # Re-apply run decorators (from decorate_view) to the clone's run method # We can't just copy the decorated run because it's bound to the original instance if hasattr(self, "_run_decorators") and self._run_decorators: cloned._run_decorators = [] # type: ignore[attr-defined] for deco in self._run_decorators: cloned.run = deco(cloned.run) # type: ignore cloned._run_decorators.append(deco) # type: ignore[attr-defined] return cloned def run(self, request: HttpRequest, **kw: Any) -> HttpResponseBase: error = self._run_checks(request) if error: return error try: temporal_response = self.api.create_temporal_response(request) values = self._get_values(request, kw, temporal_response) result = self.view_func(request, **values) if self.stream_format: return self._stream_response(request, result, temporal_response) return self._result_to_response(request, result, temporal_response) except Exception as e: if isinstance(e, TypeError) and "required positional argument" in str(e): msg = "Did you fail to use functools.wraps() in a decorator?" msg = f"{e.args[0]}: {msg}" if e.args else msg e.args = (msg,) + e.args[1:] return self.api.on_exception(request, e) def _validate_stream_item(self, item: Any, request: HttpRequest) -> str: """Validate a single stream item and return serialized JSON string.""" assert self.stream_item_model is not None resp_object = ResponseObject(item) validated = self.stream_item_model.model_validate( resp_object, context={"request": request, "response_status": 200} ) model_dump_kwargs: Dict[str, Any] = {} if pydantic_version >= [2, 7]: # pragma: no branch # pydantic added support for serialization context at 2.7 model_dump_kwargs.update( context={"request": request, "response_status": 200} ) result = validated.model_dump( by_alias=self.by_alias, exclude_unset=self.exclude_unset, exclude_defaults=self.exclude_defaults, exclude_none=self.exclude_none, **model_dump_kwargs, )["response"] return _serialize_item(result) def _stream_response( self, request: HttpRequest, generator: Any, temporal_response: HttpResponse, ) -> StreamingHttpResponse: """Create a StreamingHttpResponse from a sync generator.""" assert self.stream_format is not None fmt = self.stream_format def content_iter() -> Any: for item in generator: data = self._validate_stream_item(item, request) yield fmt.format_chunk(data) # Copy headers/cookies after generator completes (user may set them inside) for key, value in temporal_response.items(): if key.lower() != "content-type": response[key] = value for cookie_name, cookie in temporal_response.cookies.items(): response.cookies[cookie_name] = cookie response = StreamingHttpResponse( content_iter(), content_type=fmt.media_type, status=temporal_response.status_code, ) # Add format-specific headers for key, value in fmt.response_headers().items(): response[key] = value return response def _set_auth( self, auth: Optional[Union[Sequence[Callable], Callable, object]] ) -> None: if auth is not None and auth is not NOT_SET: self.auth_callbacks = isinstance(auth, Sequence) and auth or [auth] def _run_checks(self, request: HttpRequest) -> Optional[HttpResponse]: "Runs security/throttle checks for each operation" # NOTE: if you change anything in this function - do this also in AsyncOperation # Set CSRF exempt status on request so auth handlers can check it if self.csrf_exempt: # _ninja_csrf_exempt is a special flag that tells auth handler to skip CSRF checks request._ninja_csrf_exempt = True # type: ignore # auth: if self.auth_callbacks: error = self._run_authentication(request) if error: return error # Throttling: if self.throttle_objects: error = self._check_throttles(request) if error: return error return None def _run_authentication(self, request: HttpRequest) -> Optional[HttpResponse]: for callback in self.auth_callbacks: try: if is_async_callable(callback) or getattr(callback, "is_async", False): result = callback(request) if inspect.iscoroutine(result): result = async_to_sync(callback)(request) else: result = callback(request) except Exception as exc: return self.api.on_exception(request, exc) if result: request.auth = result # type: ignore return None return self.api.on_exception(request, AuthenticationError()) def _check_throttles(self, request: HttpRequest) -> Optional[HttpResponse]: throttle_durations = [] for throttle in self.throttle_objects: if not throttle.allow_request(request): throttle_durations.append(throttle.wait()) if throttle_durations: # Filter out `None` values which may happen in case of config / rate durations = [ duration for duration in throttle_durations if duration is not None ] duration = max(durations, default=None) return self.api.on_exception(request, Throttled(wait=duration)) # type: ignore return None def _model_dump_kwargs(self, request: HttpRequest, status: int) -> Dict[str, Any]: kwargs: Dict[str, Any] = {} if pydantic_version >= [2, 7]: kwargs["context"] = {"request": request, "response_status": status} return kwargs def _result_to_response( self, request: HttpRequest, result: Any, temporal_response: HttpResponse ) -> HttpResponseBase: """ The protocol for results - if HttpResponse - returns as is - if Status object - uses status code + body - if tuple with 2 elements - means http_code + body (deprecated) - otherwise it's a body """ if isinstance(result, HttpResponseBase): return result status: int = 200 if len(self.response_models) == 1: status = next(iter(self.response_models)) if isinstance(result, Status): status = result.status_code result = result.value elif isinstance(result, tuple) and len(result) == 2: warnings.warn( "Returning tuple (status_code, response) is deprecated. " "Use Status(status_code, response) instead.", DeprecationWarning, stacklevel=2, ) status, result = result if status in self.response_models: response_model = self.response_models[status] elif Ellipsis in self.response_models: response_model = self.response_models[Ellipsis] else: raise ConfigError( f"Schema for status {status} is not set in response" f" {self.response_models.keys()}" ) temporal_response.status_code = status if response_model is NOT_SET: return self.api.create_response( request, result, temporal_response=temporal_response ) if response_model is None: # Empty response. return temporal_response model_dump_kwargs = self._model_dump_kwargs(request, status) # Skip re-validation for pydantic model instances matching the response type resp_annotation = response_model.model_fields["response"].annotation if ( isinstance(resp_annotation, type) and isinstance(result, BaseModel) and isinstance(result, resp_annotation) ): result = cast(BaseModel, result).model_dump( by_alias=self.by_alias, exclude_unset=self.exclude_unset, exclude_defaults=self.exclude_defaults, exclude_none=self.exclude_none, **model_dump_kwargs, ) return self.api.create_response( request, result, temporal_response=temporal_response ) resp_object = ResponseObject(result) # ^ we need object because getter_dict seems work only with model_validate validated_object = response_model.model_validate( resp_object, context={"request": request, "response_status": status} ) result = validated_object.model_dump( by_alias=self.by_alias, exclude_unset=self.exclude_unset, exclude_defaults=self.exclude_defaults, exclude_none=self.exclude_none, **model_dump_kwargs, )["response"] return self.api.create_response( request, result, temporal_response=temporal_response ) def _get_values( self, request: HttpRequest, path_params: Any, temporal_response: HttpResponse ) -> DictStrAny: values = {} error_contexts: List[ValidationErrorContext] = [] for model in self.models: try: data = model.resolve(request, self.api, path_params) values.update(data) except pydantic.ValidationError as e: error_contexts.append( ValidationErrorContext(pydantic_validation_error=e, model=model) ) if error_contexts: validation_error = self.api.validation_error_from_error_contexts( error_contexts ) raise validation_error if self.signature.response_arg: values[self.signature.response_arg] = temporal_response return values def _create_response_model_multiple( self, response_param: DictStrAny ) -> Dict[str, Optional[Type[Schema]]]: result = {} for key, model in response_param.items(): status_codes = isinstance(key, Iterable) and key or [key] for code in status_codes: result[code] = self._create_response_model(model) return result def _create_response_model(self, response_param: Any) -> Optional[Type[Schema]]: if response_param is None: return None attrs = {"__annotations__": {"response": response_param}} return type("NinjaResponseSchema", (Schema,), attrs) class AsyncOperation(Operation): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.is_async = True async def run(self, request: HttpRequest, **kw: Any) -> HttpResponseBase: # type: ignore error = await self._run_checks(request) if error: return error try: temporal_response = self.api.create_temporal_response(request) values = self._get_values(request, kw, temporal_response) if self.stream_format: result = self.view_func(request, **values) return await self._async_stream_response( request, result, temporal_response ) result = await self.view_func(request, **values) return self._result_to_response(request, result, temporal_response) except Exception as e: return self.api.on_exception(request, e) async def _async_stream_response( self, request: HttpRequest, generator: Any, temporal_response: HttpResponse, ) -> StreamingHttpResponse: """Create a StreamingHttpResponse from an async generator.""" assert self.stream_format is not None fmt = self.stream_format async def content_gen() -> Any: async for item in generator: data = self._validate_stream_item(item, request) yield fmt.format_chunk(data) return await create_streaming_response( content_gen(), content_type=fmt.media_type, status=temporal_response.status_code, temporal_response=temporal_response, extra_headers=fmt.response_headers(), ) async def _run_checks(self, request: HttpRequest) -> Optional[HttpResponse]: # type: ignore "Runs security/throttle checks for each operation" # NOTE: if you change anything in this function - do this also in Sync Operation # Set CSRF exempt status on request so auth handlers can check it if self.csrf_exempt: request._ninja_csrf_exempt = True # type: ignore # auth: if self.auth_callbacks: error = await self._run_authentication(request) if error: return error # Throttling: if self.throttle_objects: error = self._check_throttles(request) if error: return error return None async def _run_authentication(self, request: HttpRequest) -> Optional[HttpResponse]: # type: ignore for callback in self.auth_callbacks: try: if is_async_callable(callback) or getattr(callback, "is_async", False): cor: Optional[Coroutine] = callback(request) if cor is None: result = None else: result = await cor else: result = await sync_to_async(callback)(request) except Exception as exc: return self.api.on_exception(request, exc) if result: request.auth = result # type: ignore return None return self.api.on_exception(request, AuthenticationError()) class PathView: def __init__(self) -> None: self.operations: List[Operation] = [] self.is_async = False # if at least one operation is async - will become True self.url_name: Optional[str] = None def add_operation( self, path: str, methods: List[str], view_func: Callable, *, auth: Optional[Union[Sequence[Callable], Callable, NOT_SET_TYPE]] = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Operation: if url_name: self.url_name = url_name OperationClass = Operation is_streaming = isinstance(response, _StreamAlias) if is_async(view_func) or ( is_streaming and inspect.isasyncgenfunction(view_func) ): self.is_async = True OperationClass = AsyncOperation operation = OperationClass( path, methods, view_func, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, include_in_schema=include_in_schema, url_name=url_name, openapi_extra=openapi_extra, ) self.operations.append(operation) view_func._ninja_operation = operation # type: ignore return operation def clone(self) -> "PathView": """ Create a fresh copy of this PathView with cloned operations. This method is used when mounting the same router multiple times to ensure each mount has independent PathView and Operation instances. """ cloned = PathView() cloned.is_async = self.is_async cloned.url_name = self.url_name cloned.operations = [op.clone() for op in self.operations] return cloned def get_view(self) -> Callable: # Create a unique view function for this PathView if self.is_async: # Create a wrapper for async view async def async_view_wrapper( request: HttpRequest, *args: Any, **kwargs: Any ) -> HttpResponseBase: return await self._async_view(request, *args, **kwargs) # All django-ninja views are CSRF exempt at Django middleware level # Cookie-based auth (APIKeyCookie) handles CSRF checking separately async_view_wrapper.csrf_exempt = True # type: ignore return async_view_wrapper else: # Create a wrapper for sync view def sync_view_wrapper( request: HttpRequest, *args: Any, **kwargs: Any ) -> HttpResponseBase: return self._sync_view(request, *args, **kwargs) # All django-ninja views are CSRF exempt at Django middleware level # Cookie-based auth (APIKeyCookie) handles CSRF checking separately sync_view_wrapper.csrf_exempt = True # type: ignore return sync_view_wrapper def _sync_view(self, request: HttpRequest, *a: Any, **kw: Any) -> HttpResponseBase: operation = self._find_operation(request) if operation is None: return self._not_allowed() return operation.run(request, *a, **kw) async def _async_view( self, request: HttpRequest, *a: Any, **kw: Any ) -> HttpResponseBase: operation = self._find_operation(request) if operation is None: return self._not_allowed() if operation.is_async: return await cast(AsyncOperation, operation).run(request, *a, **kw) return await sync_to_async(operation.run)(request, *a, **kw) def _find_operation(self, request: HttpRequest) -> Optional[Operation]: for op in self.operations: if request.method in op.methods: return op return None def _not_allowed(self) -> HttpResponse: allowed_methods = set() for op in self.operations: allowed_methods.update(op.methods) return HttpResponseNotAllowed(allowed_methods, content=b"Method not allowed") class ResponseObject: "Basically this is just a helper to be able to pass response to pydantic's model_validate" def __init__(self, response: HttpResponse) -> None: self.response = response vitalik-django-ninja-0b67d47/ninja/orm/000077500000000000000000000000001515660254400177555ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/orm/__init__.py000066400000000000000000000003021515660254400220610ustar00rootroot00000000000000from ninja.orm.factory import create_schema from ninja.orm.fields import register_field from ninja.orm.metaclass import ModelSchema __all__ = ["create_schema", "register_field", "ModelSchema"] vitalik-django-ninja-0b67d47/ninja/orm/factory.py000066400000000000000000000130421515660254400217760ustar00rootroot00000000000000import itertools from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, cast from django.db.models import Field as DjangoField from django.db.models import ManyToManyRel, ManyToOneRel, Model from pydantic import create_model as create_pydantic_model from ninja.errors import ConfigError from ninja.orm.fields import get_schema_field from ninja.schema import Schema # MAYBE: # Schema = create_schema(Model, exclude=['id']) # # @api.post # def operation_create(request, payload: Schema): # orm_instance = payload.orm.apply(Model()) # orm_instance.save() # # @api.post("/{id}") # def operation_edit(request, id: int, payload: Schema): # orm_instance = payload.orm.apply(Model.objects.get(id=id)) # orm_instance.save() __all__ = ["SchemaFactory", "factory", "create_schema"] SchemaKey = Tuple[Type[Model], str, int, str, str, str, str] class SchemaFactory: def __init__(self) -> None: self.schemas: Dict[SchemaKey, Type[Schema]] = {} self.schema_names: Set[str] = set() def create_schema( self, model: Type[Model], *, name: str = "", depth: int = 0, fields: Optional[List[str]] = None, exclude: Optional[List[str]] = None, optional_fields: Optional[List[str]] = None, custom_fields: Optional[List[Tuple[str, Any, Any]]] = None, base_class: Type[Schema] = Schema, ) -> Type[Schema]: name = name or model.__name__ if fields and exclude: raise ConfigError("Only one of 'fields' or 'exclude' should be set.") key = self.get_key( model, name, depth, fields, exclude, optional_fields, custom_fields ) if key in self.schemas: return self.schemas[key] model_fields_list = list(self._selected_model_fields(model, fields, exclude)) if optional_fields: if optional_fields == "__all__": optional_fields = [f.name for f in model_fields_list] definitions = {} for fld in model_fields_list: python_type, field_info = get_schema_field( fld, depth=depth, optional=optional_fields and (fld.name in optional_fields), ) definitions[fld.name] = (python_type, field_info) if custom_fields: for fld_name, python_type, field_info in custom_fields: # if not isinstance(field_info, FieldInfo): # field_info = Field(field_info) definitions[fld_name] = (python_type, field_info) if name in self.schema_names: name = self._get_unique_name(name) schema: Type[Schema] = create_pydantic_model( name, __config__=None, __base__=base_class, __module__=base_class.__module__, __validators__={}, **definitions, ) # type: ignore # __model_name: str, # *, # __config__: ConfigDict | None = None, # __base__: None = None, # __module__: str = __name__, # __validators__: dict[str, AnyClassMethod] | None = None, # __cls_kwargs__: dict[str, Any] | None = None, # **field_definitions: Any, self.schemas[key] = schema self.schema_names.add(name) return schema def get_key( self, model: Type[Model], name: str, depth: int, fields: Union[str, List[str], None], exclude: Optional[List[str]], optional_fields: Optional[Union[List[str], str]], custom_fields: Optional[List[Tuple[str, str, Any]]], ) -> SchemaKey: "returns a hashable value for all given parameters" # TODO: must be a test that compares all kwargs from init to get_key return ( model, name, depth, str(fields), str(exclude), str(optional_fields), str(custom_fields), ) def _get_unique_name(self, name: str) -> str: "Returns a unique name by adding counter suffix" for num in itertools.count(start=2): # pragma: no branch result = f"{name}{num}" if result not in self.schema_names: break return result def _selected_model_fields( self, model: Type[Model], fields: Optional[List[str]] = None, exclude: Optional[List[str]] = None, ) -> Iterator[DjangoField]: "Returns iterator for model fields based on `exclude` or `fields` arguments" all_fields = {f.name: f for f in self._model_fields(model)} if not fields and not exclude: for f in all_fields.values(): yield f invalid_fields = (set(fields or []) | set(exclude or [])) - all_fields.keys() if invalid_fields: raise ConfigError( f"DjangoField(s) {invalid_fields} are not in model {model}" ) if fields: for name in fields: yield all_fields[name] if exclude: for f in all_fields.values(): if f.name not in exclude: yield f def _model_fields(self, model: Type[Model]) -> Iterator[DjangoField]: "returns iterator with all the fields that can be part of schema" for fld in model._meta.get_fields(): if isinstance(fld, (ManyToOneRel, ManyToManyRel)): # skipping relations continue yield cast(DjangoField, fld) factory = SchemaFactory() create_schema = factory.create_schema vitalik-django-ninja-0b67d47/ninja/orm/fields.py000066400000000000000000000144251515660254400216030ustar00rootroot00000000000000import datetime from decimal import Decimal from typing import Any, Callable, Dict, List, Tuple, Type, TypeVar, Union, no_type_check from uuid import UUID from django.db.models import ManyToManyField from django.db.models.fields import Field as DjangoField from pydantic import IPvAnyAddress from pydantic.fields import FieldInfo from pydantic_core import PydanticUndefined, core_schema from ninja.errors import ConfigError from ninja.openapi.schema import OpenAPISchema from ninja.types import DictStrAny __all__ = ["create_m2m_link_type", "get_schema_field", "get_related_field_schema"] # keep_lazy seems not needed as .title forces translation anyway # https://github.com/vitalik/django-ninja/issues/774 # @keep_lazy_text def title_if_lower(s: str) -> str: if s == s.lower(): return s.title() return s class AnyObject: @classmethod def __get_pydantic_core_schema__( cls, source: Any, handler: Callable[..., Any] ) -> Any: return core_schema.with_info_plain_validator_function(cls.validate) @classmethod def __get_pydantic_json_schema__( cls, schema: Any, handler: Callable[..., Any] ) -> DictStrAny: return {"type": "object"} @classmethod def validate(cls, value: Any, _: Any) -> Any: return value TYPES = { "AutoField": int, "BigAutoField": int, "BigIntegerField": int, "BinaryField": bytes, "BooleanField": bool, "CharField": str, "DateField": datetime.date, "DateTimeField": datetime.datetime, "DecimalField": Decimal, "DurationField": datetime.timedelta, "FileField": str, "FilePathField": str, "FloatField": float, "GenericIPAddressField": IPvAnyAddress, "IPAddressField": IPvAnyAddress, "IntegerField": int, "JSONField": AnyObject, "NullBooleanField": bool, "PositiveBigIntegerField": int, "PositiveIntegerField": int, "PositiveSmallIntegerField": int, "SlugField": str, "SmallAutoField": int, "SmallIntegerField": int, "TextField": str, "TimeField": datetime.time, "UUIDField": UUID, # postgres fields: "ArrayField": List, "CICharField": str, "CIEmailField": str, "CITextField": str, "HStoreField": Dict, } TModel = TypeVar("TModel") def register_field(django_field: str, python_type: Any) -> None: TYPES[django_field] = python_type @no_type_check def create_m2m_link_type(type_: Type[TModel]) -> Type[TModel]: class M2MLink(type_): # type: ignore @classmethod def __get_pydantic_core_schema__(cls, source, handler): return core_schema.with_info_plain_validator_function(cls._validate) @classmethod def __get_pydantic_json_schema__(cls, schema, handler): json_type = { int: "integer", str: "string", float: "number", UUID: "string", }[type_] return {"type": json_type} @classmethod def _validate(cls, v: Any, _): try: return v.pk # when we output queryset - we have db instances except AttributeError: return type_(v) # when we read payloads we have primakey keys return M2MLink @no_type_check def get_schema_field( field: DjangoField, *, depth: int = 0, optional: bool = False ) -> Tuple: "Returns pydantic field from django's model field" alias = None default = ... default_factory = None description = None title = None max_length = None nullable = False python_type = None if field.is_relation: if depth > 0: return get_related_field_schema(field, depth=depth) internal_type = field.related_model._meta.pk.get_internal_type() if not field.concrete and field.auto_created or field.null or optional: default = None nullable = True alias = getattr(field, "get_attname", None) and field.get_attname() pk_type = TYPES.get(internal_type, int) if field.one_to_many or field.many_to_many: m2m_type = create_m2m_link_type(pk_type) python_type = List[m2m_type] # type: ignore else: python_type = pk_type else: _f_name, _f_path, _f_pos, field_options = field.deconstruct() blank = field_options.get("blank", False) null = field_options.get("null", False) max_length = field_options.get("max_length") internal_type = field.get_internal_type() try: python_type = TYPES[internal_type] except KeyError as e: msg = [ f"Do not know how to convert django field '{internal_type}'.", "Try from ninja.orm import register_field", f"register_field('{internal_type}', )", ] raise ConfigError("\n".join(msg)) from e if field.primary_key or blank or null or optional: default = None nullable = True if field.has_default(): if callable(field.default): default_factory = field.default else: default = field.default if default_factory: default = PydanticUndefined if nullable: python_type = Union[python_type, None] # aka Optional in 3.7+ description = field.help_text or None title = title_if_lower(field.verbose_name) return ( python_type, FieldInfo( default=default, alias=alias, validation_alias=alias, serialization_alias=alias, default_factory=default_factory, title=title, description=description, max_length=max_length, ), ) @no_type_check def get_related_field_schema(field: DjangoField, *, depth: int) -> Tuple[OpenAPISchema]: from ninja.orm import create_schema model = field.related_model schema = create_schema(model, depth=depth - 1) default = ... if not field.concrete and field.auto_created or field.null: default = None if isinstance(field, ManyToManyField): schema = List[schema] # type: ignore return ( schema, FieldInfo( default=default, description=field.help_text, title=title_if_lower(field.verbose_name), ), ) vitalik-django-ninja-0b67d47/ninja/orm/metaclass.py000066400000000000000000000077451515660254400223200ustar00rootroot00000000000000from typing import Any, List, Optional, Union, no_type_check from django.apps import apps from django.db.models import Model as DjangoModel from pydantic.dataclasses import dataclass from ninja.compatibility.util import get_annotations_from_namespace from ninja.errors import ConfigError from ninja.orm.factory import create_schema from ninja.schema import ResolverMetaclass, Schema _is_modelschema_class_defined = False @dataclass class MetaConf: model: Any fields: Optional[List[str]] = None exclude: Union[List[str], str, None] = None fields_optional: Union[List[str], str, None] = None @staticmethod def from_schema_class(name: str, namespace: dict) -> "MetaConf": if "Config" in namespace: raise ConfigError( # pragma: no cover "The use of `Config` class is removed for ModelSchema, use 'Meta' instead", ) if "Meta" in namespace: meta = namespace["Meta"] model = meta.model if isinstance(model, str): try: app_label, model_name = model.split(".") except ValueError as e: raise ValueError( f"Model string must be in format 'app_label.ModelName', got: {model}" ) from e model = apps.get_model(app_label, model_name) fields = getattr(meta, "fields", None) exclude = getattr(meta, "exclude", None) optional_fields = getattr(meta, "fields_optional", None) else: raise ConfigError(f"ModelSchema class '{name}' requires a 'Meta' subclass") assert issubclass(model, DjangoModel) if not fields and not exclude: raise ConfigError( "Creating a ModelSchema without either the 'fields' attribute" " or the 'exclude' attribute is prohibited" ) if fields == "__all__": fields = None # ^ when None is passed to create_schema - all fields are selected return MetaConf( model=model, fields=fields, exclude=exclude, fields_optional=optional_fields, ) class ModelSchemaMetaclass(ResolverMetaclass): @no_type_check def __new__( mcs, name: str, bases: tuple, namespace: dict, **kwargs, ): cls = super().__new__( mcs, name, bases, namespace, **kwargs, ) for base in reversed(bases): if ( _is_modelschema_class_defined and issubclass(base, ModelSchema) and base == ModelSchema ): meta_conf = MetaConf.from_schema_class(name, namespace) custom_fields = [] annotations = get_annotations_from_namespace(namespace) for attr_name, type in annotations.items(): if attr_name.startswith("_"): continue default = namespace.get(attr_name, ...) custom_fields.append((attr_name, type, default)) # # cls.__doc__ = namespace.get("__doc__", config.model.__doc__) # cls.__fields__ = {} # forcing pydantic recreate # # assert False, "!! cls.model_fields" # print(config.model, name, fields, exclude, "!!") model_schema = create_schema( meta_conf.model, name=name, fields=meta_conf.fields, exclude=meta_conf.exclude, optional_fields=meta_conf.fields_optional, custom_fields=custom_fields, base_class=cls, ) model_schema.__doc__ = cls.__doc__ return model_schema return cls class ModelSchema(Schema, metaclass=ModelSchemaMetaclass): pass _is_modelschema_class_defined = True vitalik-django-ninja-0b67d47/ninja/orm/shortcuts.py000066400000000000000000000010521515660254400223630ustar00rootroot00000000000000from typing import Any, List, Type from ninja import Schema from ninja.orm.factory import create_schema __all__ = ["S", "L"] # GOAL: # from ninja.orm import S, L # S(Job) -> JobSchema? Job? # S(Job) -> should reuse already created schema # S(Job, fields='xxx') -> new schema ? how to name Job1 , 2, 3 and so on ? # L(Job) -> List[Job] def S(model: Any, **kwargs: Any) -> Type[Schema]: return create_schema(model, **kwargs) def L(model: Any, **kwargs: Any) -> List[Any]: schema = S(model, **kwargs) return List[schema] # type: ignore vitalik-django-ninja-0b67d47/ninja/pagination.py000066400000000000000000000614601515660254400216720ustar00rootroot00000000000000import binascii import inspect from abc import ABC, abstractmethod from base64 import b64decode, b64encode from functools import partial, wraps from math import inf from typing import ( Any, AsyncGenerator, Callable, List, Optional, Tuple, Type, Union, ) from urllib import parse from django.db.models import QuerySet from django.http import HttpRequest from django.utils.module_loading import import_string from pydantic import BaseModel, field_validator from typing_extensions import get_args as get_collection_args from ninja import Field, Query, Router, Schema from ninja.conf import settings from ninja.constants import NOT_SET from ninja.errors import ConfigError, ValidationError from ninja.operation import Operation from ninja.responses import Status from ninja.signature.details import is_collection_type from ninja.utils import ( contribute_operation_args, contribute_operation_callback, is_async_callable, ) class PaginationBase(ABC): class Input(Schema): pass InputSource = Query(...) class Output(Schema): items: List[Any] count: int items_attribute: str = "items" def __init__(self, *, pass_parameter: Optional[str] = None, **kwargs: Any) -> None: self.pass_parameter = pass_parameter @abstractmethod def paginate_queryset( self, queryset: QuerySet, pagination: Any, request: HttpRequest, **params: Any, ) -> Any: pass # pragma: no cover def _items_count(self, queryset: QuerySet) -> int: """ Since lists are mainly compatible with QuerySets and can be passed to paginator. We will first to try to use .count - and if not there will use a len """ try: # forcing to find queryset.count instead of list.count: return queryset.all().count() except AttributeError: return len(queryset) class AsyncPaginationBase(PaginationBase): @abstractmethod async def apaginate_queryset( self, queryset: QuerySet, pagination: Any, request: HttpRequest, **params: Any, ) -> Any: pass # pragma: no cover async def _aitems_count(self, queryset: QuerySet) -> int: try: return await queryset.all().acount() except AttributeError: return len(queryset) class LimitOffsetPagination(AsyncPaginationBase): class Input(Schema): limit: int = Field( settings.PAGINATION_PER_PAGE, ge=1, le=( settings.PAGINATION_MAX_LIMIT if settings.PAGINATION_MAX_LIMIT != inf else None ), ) offset: int = Field(0, ge=0) def paginate_queryset( self, queryset: QuerySet, pagination: Input, request: HttpRequest, **params: Any, ) -> Any: offset = pagination.offset limit: int = min(pagination.limit, settings.PAGINATION_MAX_LIMIT) return { self.items_attribute: queryset[offset : offset + limit], "count": self._items_count(queryset), } # noqa: E203 async def apaginate_queryset( self, queryset: QuerySet, pagination: Input, request: HttpRequest, **params: Any, ) -> Any: offset = pagination.offset limit: int = min(pagination.limit, settings.PAGINATION_MAX_LIMIT) if isinstance(queryset, QuerySet): items = [obj async for obj in queryset[offset : offset + limit]] else: items = queryset[offset : offset + limit] return { self.items_attribute: items, "count": await self._aitems_count(queryset), } # noqa: E203 class PageNumberPagination(AsyncPaginationBase): class Input(Schema): page: int = Field(1, ge=1) page_size: Optional[int] = Field(None, ge=1) def __init__( self, page_size: int = settings.PAGINATION_PER_PAGE, max_page_size: int = settings.PAGINATION_MAX_PER_PAGE_SIZE, **kwargs: Any, ) -> None: self.page_size = page_size self.max_page_size = max_page_size super().__init__(**kwargs) def _get_page_size(self, requested_page_size: Optional[int]) -> int: if requested_page_size is None: return self.page_size return min(requested_page_size, self.max_page_size) def paginate_queryset( self, queryset: QuerySet, pagination: Input, request: HttpRequest, **params: Any, ) -> Any: page_size = self._get_page_size(pagination.page_size) offset = (pagination.page - 1) * page_size return { self.items_attribute: queryset[offset : offset + page_size], "count": self._items_count(queryset), } # noqa: E203 async def apaginate_queryset( self, queryset: QuerySet, pagination: Input, request: HttpRequest, **params: Any, ) -> Any: page_size = self._get_page_size(pagination.page_size) offset = (pagination.page - 1) * page_size if isinstance(queryset, QuerySet): items = [obj async for obj in queryset[offset : offset + page_size]] else: items = queryset[offset : offset + page_size] return { self.items_attribute: items, "count": await self._aitems_count(queryset), } # noqa: E203 class CursorPagination(AsyncPaginationBase): max_page_size: int page_size: int items_attribute: str = "results" def __init__( self, *, ordering: Tuple[str, ...] = settings.PAGINATION_DEFAULT_ORDERING, page_size: int = settings.PAGINATION_PER_PAGE, max_page_size: int = settings.PAGINATION_MAX_PER_PAGE_SIZE, **kwargs: Any, ) -> None: self.ordering = ordering # take the first ordering parameter as the attribute for establishing # position self._order_attribute = ( ordering[0][1:] if ordering[0].startswith("-") else ordering[0] ) self._order_attribute_reversed = ordering[0].startswith("-") self.page_size = page_size self.max_page_size = max_page_size super().__init__(**kwargs) class Input(Schema): page_size: Optional[int] = None cursor: Optional[str] = None class Output(Schema): previous: Optional[str] next: Optional[str] results: List[Any] class Cursor(BaseModel): """ Represents pagination state. This is encoded in a base64 query parameter. """ p: Optional[str] = Field( default=None, title="position", description="String identifier for the current position in the dataset", ) r: bool = Field( default=False, title="reverse", description="Whether to reverse the ordering direction", ) # offset enables the use of a non-unique ordering field # e.g. if created time of two items is exactly the same, we can use the offset # to figure out the position exactly o: int = Field( default=0, ge=0, lt=settings.PAGINATION_MAX_OFFSET, title="offset", description="Number of items to skip from the current position", ) @field_validator("*", mode="before") @classmethod def validate_individual_queryparam(cls, value: Any) -> Any: """ Handle query string parsing quirks where single values become lists. URL parsing libraries wrap single query parameters in lists, we only care about a single value """ if isinstance(value, list): return value[0] return value @classmethod def from_encoded_param( cls, encoded_param: Optional[str], context: Any = None ) -> "CursorPagination.Cursor": """ Deserialize cursor from URL-safe base64 token. """ if not encoded_param: return cls() try: decoded = b64decode( encoded_param.encode("ascii"), validate=True ).decode("ascii") except (ValueError, binascii.Error) as e: raise ValidationError([{"cursor": "Invalid Cursor"}]) from e parsed_querystring = parse.parse_qs(decoded, keep_blank_values=True) return cls.model_validate(parsed_querystring, context=context) def encode_as_param(self) -> str: """ Serialize cursor to URL-safe base64 token. """ data = self.model_dump( exclude_defaults=True, exclude_none=True, exclude_unset=True ) query_string = parse.urlencode(data, doseq=True) return b64encode(query_string.encode("ascii")).decode("ascii") @staticmethod def _reverse_order(order: Tuple[str, ...]) -> Tuple[str, ...]: """ Flip ordering direction for backward pagination. Example: ("-created", "pk") becomes ("created", "-pk") ("name", "-updated") becomes ("-name", "updated") """ return tuple( marker[1:] if marker.startswith("-") else f"-{marker}" for marker in order ) def _get_position(self, item: Any) -> str: """ Extract the string representation of the attribute value used for ordering, which serves as the position identifier. """ return str(getattr(item, self._order_attribute)) def _get_page_size(self, requested_page_size: Optional[int]) -> int: """ Determine the actual page size to use, respecting configured limits. Uses the default page size when no specific size is requested, otherwise clamps the requested size within the allowed range to prevent resource exhaustion attacks. """ if requested_page_size is None: return self.page_size return min(self.max_page_size, max(1, requested_page_size)) def _build_next_cursor( self, current_cursor: Cursor, results: List[Any], additional_position: Optional[str] = None, ) -> Optional[Cursor]: """ Build cursor for next page """ if (additional_position is None and not current_cursor.r) or not results: return None if not current_cursor.r: # next position is provided by the additional position in a forward cursor next_position = additional_position else: # default to the last item # this will result in this item being included in the next set of results # when flipping from a reversed cursor query to a forward cursor query next_position = self._get_position(results[-1]) offset = 0 if current_cursor.p == next_position and not current_cursor.r: offset += current_cursor.o + len(results) else: # Count duplicates at page end to find the offset for item in reversed(results): item_position_value = self._get_position(item) if item_position_value != next_position: break offset += 1 return self.Cursor(o=offset, r=False, p=next_position) def _build_previous_cursor( self, current_cursor: Cursor, results: List[Any], additional_position: Optional[str] = None, ) -> Optional[Cursor]: """ Build cursor for previous page """ if ( current_cursor.r and additional_position is None ) or current_cursor.p is None: return None if not results: # End of dataset - create reverse cursor to go backward return self.Cursor(o=0, r=True, p=current_cursor.p) if current_cursor.r: # previous position is provided by the additional position in a # reversed cursor previous_position = additional_position else: # default to the first item # this will result in this item being included in the previous set of # results when flipping from a forward cursor query to a reversed # cursor query previous_position = self._get_position(results[0]) offset = 0 if current_cursor.p == previous_position and current_cursor.r: offset += current_cursor.o + len(results) else: # Count duplicates at page end to find the offset for item in results: item_position_value = self._get_position(item) if item_position_value != previous_position: break offset += 1 return self.Cursor(o=offset, r=True, p=previous_position) @staticmethod def _add_cursor_to_URL(url: str, cursor: Optional[Cursor]) -> Optional[str]: """ Build pagination URLs with an encoded cursor. Ignore any previous cursors but preserve any other query parameters Example: Given URL "https://api.example.com/pages?tag=hiring" and a cursor with position "2024-01-01T10:00:00Z", returns: "https://api.example.com/pages?cursor=cD0yMDI0LTAxLTAxVDEwJTNBMDA%3D&tag=hiring" """ if cursor is None: return None (scheme, netloc, path, query, fragment) = parse.urlsplit(url) query_dict = parse.parse_qs(query, keep_blank_values=True) query_dict["cursor"] = [cursor.encode_as_param()] query = parse.urlencode(sorted(query_dict.items()), doseq=True) return parse.urlunsplit((scheme, netloc, path, query, fragment)) def _order_queryset(self, queryset: QuerySet, cursor: Cursor) -> QuerySet: """ Apply ordering to queryset based on cursor direction. For backward pagination (cursor.r=True), flips the ordering direction to traverse the dataset in reverse. """ if cursor.r: return queryset.order_by(*self._reverse_order(self.ordering)) return queryset.order_by(*self.ordering) def _find_position(self, queryset: QuerySet, cursor: Cursor) -> QuerySet: """ Filter queryset to start from the cursor position. """ if cursor.p is None: return queryset cmp = "gte" if cursor.r == self._order_attribute_reversed else "lte" filters = {f"{self._order_attribute}__{cmp}": cursor.p} return queryset.filter(**filters) def paginate_queryset( self, queryset: QuerySet, pagination: Input, request: HttpRequest, **params: Any ) -> Any: """ Execute cursor-based pagination with stable positioning. We fetch page_size + 1 items to detect whether more pages exist without requiring a separate count query. The extra item is discarded from results but used for next/previous cursor generation. """ page_size = self._get_page_size(pagination.page_size) cursor = self.Cursor.from_encoded_param(pagination.cursor) queryset = self._order_queryset(queryset, cursor) queryset = self._find_position(queryset, cursor) # fetch results here and turn into a list results_plus_one = list(queryset[cursor.o : cursor.o + page_size + 1]) additional_position = ( self._get_position(results_plus_one[-1]) if len(results_plus_one) > page_size else None ) if cursor.r: results = list(reversed(results_plus_one[:page_size])) else: results = results_plus_one[:page_size] next_cursor = self._build_next_cursor( current_cursor=cursor, results=results, additional_position=additional_position, ) previous_cursor = self._build_previous_cursor( current_cursor=cursor, results=results, additional_position=additional_position, ) base_url = request.build_absolute_uri() return { "next": self._add_cursor_to_URL(base_url, next_cursor), "previous": self._add_cursor_to_URL(base_url, previous_cursor), self.items_attribute: results, } async def apaginate_queryset( self, queryset: QuerySet, pagination: Input, request: HttpRequest, **params: Any, ) -> Any: """ Execute async cursor-based pagination with stable positioning. We fetch page_size + 1 items to detect whether more pages exist without requiring a separate count query. The extra item is discarded from results but used for next/previous cursor generation. """ page_size = self._get_page_size(pagination.page_size) cursor = self.Cursor.from_encoded_param(pagination.cursor) queryset = self._order_queryset(queryset, cursor) queryset = self._find_position(queryset, cursor) # fetch results here and turn into a list results_plus_one = [ obj async for obj in queryset[cursor.o : cursor.o + page_size + 1] ] additional_position = ( self._get_position(results_plus_one[-1]) if len(results_plus_one) > page_size else None ) if cursor.r: results = list(reversed(results_plus_one[:page_size])) else: results = results_plus_one[:page_size] next_cursor = self._build_next_cursor( current_cursor=cursor, results=results, additional_position=additional_position, ) previous_cursor = self._build_previous_cursor( current_cursor=cursor, results=results, additional_position=additional_position, ) base_url = request.build_absolute_uri() return { "next": self._add_cursor_to_URL(base_url, next_cursor), "previous": self._add_cursor_to_URL(base_url, previous_cursor), self.items_attribute: results, } def paginate( func_or_pgn_class: Any = NOT_SET, **paginator_params: Any ) -> Callable[..., Any]: """ @api.get(... @paginate def my_view(request): or @api.get(... @paginate(PageNumberPagination) def my_view(request): """ isfunction = inspect.isfunction(func_or_pgn_class) isnotset = func_or_pgn_class == NOT_SET pagination_class: Type[Union[PaginationBase, AsyncPaginationBase]] = import_string( settings.PAGINATION_CLASS ) if isfunction: return _inject_pagination(func_or_pgn_class, pagination_class) if not isnotset: pagination_class = func_or_pgn_class def wrapper(func: Callable[..., Any]) -> Any: return _inject_pagination(func, pagination_class, **paginator_params) return wrapper def _inject_pagination( func: Callable[..., Any], paginator_class: Type[Union[PaginationBase, AsyncPaginationBase]], **paginator_params: Any, ) -> Callable[..., Any]: if getattr(func, "_ninja_is_paginated", False): return func # ^ user changed pagination manually on function already paginator = paginator_class(**paginator_params) # Check if Input schema has any fields # If it has no fields, we should make it optional to support Pydantic 2.12+ has_input_fields = bool(paginator.Input.model_fields) if is_async_callable(func): if not hasattr(paginator, "apaginate_queryset"): raise ConfigError("Pagination class not configured for async requests") @wraps(func) async def view_with_pagination(request: HttpRequest, **kwargs: Any) -> Any: pagination_params = kwargs.pop("ninja_pagination", None) if pagination_params is None: pagination_params = paginator.Input() if paginator.pass_parameter: kwargs[paginator.pass_parameter] = pagination_params items = await func(request, **kwargs) status_code = None if isinstance(items, Status): status_code = items.status_code items = items.value result = await paginator.apaginate_queryset( items, pagination=pagination_params, request=request, **kwargs ) async def evaluate(results: Union[List, QuerySet]) -> AsyncGenerator: for result in results: yield result if paginator.Output: # type: ignore result[paginator.items_attribute] = [ result async for result in evaluate(result[paginator.items_attribute]) ] if status_code is not None: return Status(status_code, result) return result else: @wraps(func) def view_with_pagination(request: HttpRequest, **kwargs: Any) -> Any: pagination_params = kwargs.pop("ninja_pagination", None) if pagination_params is None: pagination_params = paginator.Input() if paginator.pass_parameter: kwargs[paginator.pass_parameter] = pagination_params items = func(request, **kwargs) status_code = None if isinstance(items, Status): status_code = items.status_code items = items.value result = paginator.paginate_queryset( items, pagination=pagination_params, request=request, **kwargs ) if paginator.Output: # type: ignore result[paginator.items_attribute] = list( result[paginator.items_attribute] ) # ^ forcing queryset evaluation #TODO: check why pydantic did not do it here if status_code is not None: return Status(status_code, result) return result # Only contribute args if Input has fields # For empty Input schemas, don't add the parameter at all to support Pydantic 2.12+ if has_input_fields: contribute_operation_args( view_with_pagination, "ninja_pagination", paginator.Input, paginator.InputSource, ) if paginator.Output: # type: ignore contribute_operation_callback( view_with_pagination, partial(make_response_paginated, paginator), ) view_with_pagination._ninja_is_paginated = True # type: ignore return view_with_pagination class RouterPaginated(Router): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.pagination_class = import_string(settings.PAGINATION_CLASS) def add_api_operation( self, path: str, methods: List[str], view_func: Callable[..., Any], **kwargs: Any, ) -> None: response = kwargs["response"] if is_collection_type(response): view_func = _inject_pagination(view_func, self.pagination_class) return super().add_api_operation(path, methods, view_func, **kwargs) def make_response_paginated(paginator: PaginationBase, op: Operation) -> None: """ Takes operation response and changes it to the paginated response for example: response=List[Some] will be changed to: response=PagedSome where Paged some will be a subclass of paginator.Output: class PagedSome: items: List[Some] count: int """ status_code, item_schema = _find_collection_response(op) # Switching schema to Output schema try: new_name = f"Paged{item_schema.__name__}" except AttributeError: # pragma: no cover # special case for `typing.Any`, only raised for Python < 3.10 new_name = f"Paged{str(item_schema).replace('.', '_')}" # pragma: no cover new_schema = type( new_name, (paginator.Output,), { "__annotations__": {paginator.items_attribute: List[item_schema]}, # type: ignore }, ) # typing: ignore response = op._create_response_model(new_schema) # Changing response model to newly created one op.response_models[status_code] = response def _find_collection_response(op: Operation) -> Tuple[int, Any]: """ Walks through defined operation responses and finds the first that is of a collection type (e.g. List[SomeSchema]) """ for code, resp_model in op.response_models.items(): if resp_model is None or resp_model is NOT_SET: continue model = resp_model.__annotations__["response"] if is_collection_type(model): item_schema = get_collection_args(model)[0] return code, item_schema raise ConfigError( f'"{op.view_func}" has no collection response (e.g. response=List[SomeSchema])' ) vitalik-django-ninja-0b67d47/ninja/params/000077500000000000000000000000001515660254400204435ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/params/__init__.py000066400000000000000000000064571515660254400225700ustar00rootroot00000000000000from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Pattern, TypeVar, Union from typing_extensions import Annotated from ninja.params import functions as param_functions __all__ = [ "Body", "Cookie", "File", "Form", "Header", "Path", "Query", "BodyEx", "CookieEx", "FileEx", "FormEx", "HeaderEx", "PathEx", "QueryEx", "P", ] class ParamShortcut: def __init__(self, base_func: Callable[..., Any]) -> None: self._base_func = base_func def __call__(self, *args: Any, **kwargs: Any) -> Any: return self._base_func(*args, **kwargs) def __getitem__(self, args: Any) -> Any: if isinstance(args, tuple): return Annotated[args[0], self._base_func(**args[1])] return Annotated[args, self._base_func()] if TYPE_CHECKING: # pragma: nocover # mypy cheats T = TypeVar("T") Body = Annotated[T, param_functions.Body()] Cookie = Annotated[T, param_functions.Cookie()] File = Annotated[T, param_functions.File()] Form = Annotated[T, param_functions.Form()] Header = Annotated[T, param_functions.Header()] Path = Annotated[T, param_functions.Path()] Query = Annotated[T, param_functions.Query()] # mypy does not like to extend already annotated params # with extra annotation (so need to cheat with these XXX-Ex types): from typing_extensions import Annotated as BodyEx from typing_extensions import Annotated as CookieEx from typing_extensions import Annotated as FileEx from typing_extensions import Annotated as FormEx from typing_extensions import Annotated as HeaderEx from typing_extensions import Annotated as PathEx from typing_extensions import Annotated as QueryEx else: Body = ParamShortcut(param_functions.Body) Cookie = ParamShortcut(param_functions.Cookie) File = ParamShortcut(param_functions.File) Form = ParamShortcut(param_functions.Form) Header = ParamShortcut(param_functions.Header) Path = ParamShortcut(param_functions.Path) Query = ParamShortcut(param_functions.Query) # mypy does not like to extend already annotated params # with extra annotation (so need to cheat with these XXX-Ex types): BodyEx = Body CookieEx = Cookie FileEx = File FormEx = Form HeaderEx = Header PathEx = Path QueryEx = Query def P( *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Dict[str, Any]: "Arguments for BodyEx, QueryEx, etc." return dict( alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) vitalik-django-ninja-0b67d47/ninja/params/functions.py000066400000000000000000000164431515660254400230350ustar00rootroot00000000000000# Yeah, this is a bit strange # but the whole point of this module is to make mypy and typehints happy # what it basically does makes function XXX that create instance of models.XXX # and annotates function with result = Any # idea from https://github.com/tiangolo/fastapi/blob/master/fastapi/param_functions.py from typing import Any, Dict, Optional, Pattern, Union from ninja.params import models def Path( # noqa: N802 default: Any = ..., *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Any: return models.Path( default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) def Query( # noqa: N802 default: Any = ..., *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Any: return models.Query( default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) def Header( # noqa: N802 default: Any = ..., *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Any: return models.Header( default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) def Cookie( # noqa: N802 default: Any = ..., *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Any: return models.Cookie( default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) def Body( # noqa: N802 default: Any = ..., *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Any: return models.Body( default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) def Form( # noqa: N802 default: Any = ..., *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Any: return models.Form( default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) def File( # noqa: N802 default: Any = ..., *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Union[str, Pattern[str], None] = None, example: Any = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ) -> Any: return models.File( default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, **extra, ) vitalik-django-ninja-0b67d47/ninja/params/models.py000066400000000000000000000175471515660254400223160ustar00rootroot00000000000000from abc import ABC, abstractmethod from typing import ( TYPE_CHECKING, Any, Dict, List, Optional, Pattern, Tuple, Type, TypeVar, Union, ) from django.conf import settings from django.http import HttpRequest from pydantic import BaseModel from pydantic.fields import FieldInfo from ninja.errors import HttpError from ninja.types import DictStrAny if TYPE_CHECKING: from ninja import NinjaAPI # pragma: no cover __all__ = [ "ParamModel", "QueryModel", "PathModel", "HeaderModel", "CookieModel", "BodyModel", "FormModel", "FileModel", ] TModel = TypeVar("TModel", bound="ParamModel") TModels = List[TModel] class ParamModel(BaseModel, ABC): __ninja_param_source__ = None @classmethod @abstractmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: pass # pragma: no cover @classmethod def resolve( cls: Type[TModel], request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny, ) -> TModel: data = cls.get_request_data(request, api, path_params) if data is None: return cls() data = cls._map_data_paths(data) return cls.model_validate(data, context={"request": request}) @classmethod def _map_data_paths(cls, data: DictStrAny) -> DictStrAny: flatten_map = getattr(cls, "__ninja_flatten_map__", None) if not flatten_map: return data mapped_data: DictStrAny = {} for key, path in flatten_map.items(): cls._map_data_path(mapped_data, data.get(key), path) return mapped_data @classmethod def _map_data_path( cls, data: DictStrAny, value: Any, path: Tuple[str, ...] ) -> None: current = data for key in path[:-1]: current = current.setdefault(key, {}) if value is not None: current[path[-1]] = value class QueryModel(ParamModel): @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: list_fields = getattr(cls, "__ninja_collection_fields__", []) return api.parser.parse_querydict(request.GET, list_fields, request) class PathModel(ParamModel): @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: return path_params class HeaderModel(ParamModel): __ninja_flatten_map__: DictStrAny @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: data = {} headers = request.headers for name in cls.__ninja_flatten_map__: if name in headers: data[name] = headers[name] return data class CookieModel(ParamModel): @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: return request.COOKIES class BodyModel(ParamModel): __read_from_single_attr__: str @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: if request.body: try: data = api.parser.parse_body(request) except Exception as e: msg = "Cannot parse request body" if settings.DEBUG: msg += f" ({e})" raise HttpError(400, msg) from e varname = getattr(cls, "__read_from_single_attr__", None) if varname: data = {varname: data} return data return None class FormModel(ParamModel): @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: list_fields = getattr(cls, "__ninja_collection_fields__", []) return api.parser.parse_querydict(request.POST, list_fields, request) class FileModel(ParamModel): @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: list_fields = getattr(cls, "__ninja_collection_fields__", []) return api.parser.parse_querydict(request.FILES, list_fields, request) class _HttpRequest(HttpRequest): body: bytes = b"" class _MultiPartBodyModel(BodyModel): __ninja_body_params__: DictStrAny @classmethod def get_request_data( cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny ) -> Optional[DictStrAny]: req = _HttpRequest() get_request_data = super().get_request_data results: DictStrAny = {} for name, annotation in cls.__ninja_body_params__.items(): if name in request.POST: data = request.POST[name] if annotation is str and data[0] != '"' and data[-1] != '"': data = f'"{data}"' req.body = data.encode() results[name] = get_request_data(req, api, path_params) return results class Param(FieldInfo): # type: ignore[misc] def __init__( self, default: Any, *, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, example: Optional[Any] = None, examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, include_in_schema: Optional[bool] = True, pattern: Union[str, Pattern[str], None] = None, # param_name: str = None, # param_type: Any = None, **extra: Any, ): self.deprecated = deprecated # self.param_name: str = None # self.param_type: Any = None self.model_field: Optional[FieldInfo] = None json_schema_extra = {} if example: json_schema_extra["example"] = example if examples: json_schema_extra["examples"] = examples if deprecated: json_schema_extra["deprecated"] = deprecated if not include_in_schema: json_schema_extra["include_in_schema"] = include_in_schema if alias and not extra.get("validation_alias"): extra["validation_alias"] = alias if alias and not extra.get("serialization_alias"): extra["serialization_alias"] = alias super().__init__( default=default, alias=alias, title=title, description=description, gt=gt, ge=ge, lt=lt, le=le, min_length=min_length, max_length=max_length, pattern=pattern, json_schema_extra=json_schema_extra, **extra, ) @classmethod def _param_source(cls) -> str: "Openapi param.in value or body type" return cls.__name__.lower() class Path(Param): # type: ignore[misc] _model = PathModel class Query(Param): # type: ignore[misc] _model = QueryModel class Header(Param): # type: ignore[misc] _model = HeaderModel class Cookie(Param): # type: ignore[misc] _model = CookieModel class Body(Param): # type: ignore[misc] _model = BodyModel class Form(Param): # type: ignore[misc] _model = FormModel class File(Param): # type: ignore[misc] _model = FileModel class _MultiPartBody(Param): # type: ignore[misc] _model = _MultiPartBodyModel @classmethod def _param_source(cls) -> str: return "body" vitalik-django-ninja-0b67d47/ninja/parser.py000066400000000000000000000013061515660254400210260ustar00rootroot00000000000000import json from typing import List, cast from django.http import HttpRequest from django.utils.datastructures import MultiValueDict from ninja.types import DictStrAny __all__ = ["Parser"] class Parser: "Default json parser" def parse_body(self, request: HttpRequest) -> DictStrAny: return cast(DictStrAny, json.loads(request.body)) def parse_querydict( self, data: MultiValueDict, list_fields: List[str], request: HttpRequest ) -> DictStrAny: result: DictStrAny = {} for key in data.keys(): if key in list_fields: result[key] = data.getlist(key) else: result[key] = data[key] return result vitalik-django-ninja-0b67d47/ninja/patch_dict.py000066400000000000000000000043361515660254400216420ustar00rootroot00000000000000from typing import ( TYPE_CHECKING, Any, Dict, Generic, Optional, Type, TypeVar, ) from pydantic import BaseModel from pydantic_core import core_schema from ninja import Body from ninja.orm import ModelSchema from ninja.schema import Schema from ninja.utils import is_optional_type class ModelToDict(dict): _wrapped_model: Any = None _wrapped_model_dump_params: Dict[str, Any] = {} @classmethod def __get_pydantic_core_schema__(cls, _source: Any, _handler: Any) -> Any: return core_schema.no_info_after_validator_function( cls._validate, cls._wrapped_model.__pydantic_core_schema__, ) @classmethod def _validate(cls, input_value: Any) -> Any: return input_value.model_dump(**cls._wrapped_model_dump_params) def get_schema_annotations(schema_cls: Type[Any]) -> Dict[str, Any]: annotations: Dict[str, Any] = {} excluded_bases = {Schema, ModelSchema, BaseModel} bases = schema_cls.mro()[:-1] final_bases = reversed([b for b in bases if b not in excluded_bases]) for base in final_bases: annotations.update(getattr(base, "__annotations__", {})) return annotations def create_patch_schema(schema_cls: Type[Any]) -> Type[ModelToDict]: schema_annotations = get_schema_annotations(schema_cls) values, annotations = {}, {} # assert False, f"{schema_cls} - {schema_cls.model_fields}" for f in schema_cls.model_fields.keys(): t = schema_annotations[f] if not is_optional_type(t): values[f] = getattr(schema_cls, f, None) annotations[f] = Optional[t] values["__annotations__"] = annotations OptionalSchema = type(f"{schema_cls.__name__}Patch", (schema_cls,), values) class OptionalDictSchema(ModelToDict): _wrapped_model = OptionalSchema _wrapped_model_dump_params = {"exclude_unset": True} return OptionalDictSchema class PatchDictUtil: def __getitem__(self, schema_cls: Any) -> Any: new_cls = create_patch_schema(schema_cls) return Body[new_cls] # type: ignore if TYPE_CHECKING: # pragma: nocover T = TypeVar("T") class PatchDict(Dict[Any, Any], Generic[T]): pass else: PatchDict = PatchDictUtil() vitalik-django-ninja-0b67d47/ninja/py.typed000066400000000000000000000000011515660254400206460ustar00rootroot00000000000000 vitalik-django-ninja-0b67d47/ninja/renderers.py000066400000000000000000000014151515660254400215240ustar00rootroot00000000000000import json from typing import Any, Mapping, Optional, Type from django.http import HttpRequest from ninja.responses import NinjaJSONEncoder __all__ = ["BaseRenderer", "JSONRenderer"] class BaseRenderer: media_type: Optional[str] = None charset: str = "utf-8" def render(self, request: HttpRequest, data: Any, *, response_status: int) -> Any: raise NotImplementedError("Please implement .render() method") class JSONRenderer(BaseRenderer): media_type = "application/json" encoder_class: Type[json.JSONEncoder] = NinjaJSONEncoder json_dumps_params: Mapping[str, Any] = {} def render(self, request: HttpRequest, data: Any, *, response_status: int) -> Any: return json.dumps(data, cls=self.encoder_class, **self.json_dumps_params) vitalik-django-ninja-0b67d47/ninja/responses.py000066400000000000000000000033611515660254400215560ustar00rootroot00000000000000from enum import Enum from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network from typing import Any, FrozenSet, Generic, TypeVar from django.core.serializers.json import DjangoJSONEncoder from django.http import JsonResponse from pydantic import AnyUrl, BaseModel from pydantic_core import Url __all__ = [ "NinjaJSONEncoder", "Response", "Status", "codes_1xx", "codes_2xx", "codes_3xx", "codes_4xx", "codes_5xx", ] T = TypeVar("T") class Status(Generic[T]): """Return a response with an explicit HTTP status code. Usage: return Status(200, {"key": "value"}) return Status(204, None) """ __slots__ = ("status_code", "value") def __init__(self, status_code: int, value: T): self.status_code = status_code self.value = value class NinjaJSONEncoder(DjangoJSONEncoder): def default(self, o: Any) -> Any: if isinstance(o, BaseModel): return o.model_dump() if isinstance(o, (Url, AnyUrl)): return str(o) if isinstance(o, (IPv4Address, IPv4Network, IPv6Address, IPv6Network)): return str(o) if isinstance(o, Enum): return str(o) return super().default(o) class Response(JsonResponse): def __init__(self, data: Any, **kwargs: Any) -> None: super().__init__(data, encoder=NinjaJSONEncoder, safe=False, **kwargs) def resp_codes(from_code: int, to_code: int) -> FrozenSet[int]: return frozenset(range(from_code, to_code + 1)) # most common http status codes codes_1xx = resp_codes(100, 101) codes_2xx = resp_codes(200, 206) codes_3xx = resp_codes(300, 308) codes_4xx = resp_codes(400, 412) | frozenset({416, 418, 425, 429, 451}) codes_5xx = resp_codes(500, 504) vitalik-django-ninja-0b67d47/ninja/router.py000066400000000000000000000637351515660254400210700ustar00rootroot00000000000000import re from dataclasses import dataclass, field from typing import ( TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Optional, Tuple, Union, ) from django.urls import URLPattern from django.urls import path as django_path from django.utils.module_loading import import_string from ninja.constants import NOT_SET, NOT_SET_TYPE from ninja.decorators import DecoratorMode from ninja.errors import ConfigError from ninja.operation import PathView from ninja.throttling import BaseThrottle from ninja.types import TCallable from ninja.utils import normalize_path, replace_path_param_notation if TYPE_CHECKING: from ninja import NinjaAPI # pragma: no cover __all__ = ["Router", "RouterMount", "BoundRouter"] @dataclass class RouterMount: """ Configuration for how a Router template is mounted to an API. This class stores the mount-time configuration without mutating the original Router template, enabling router reuse across multiple APIs or multiple mount points within the same API. """ template: "Router" prefix: str url_name_prefix: Optional[str] = None auth: Any = NOT_SET throttle: Any = NOT_SET tags: Optional[List[str]] = None inherited_decorators: List[Tuple[Callable, DecoratorMode]] = field( default_factory=list ) # Inherited auth/throttle/tags from parent routers (for nested router inheritance) inherited_auth: Any = NOT_SET inherited_throttle: Any = NOT_SET inherited_tags: Optional[List[str]] = None class BoundRouter: """ A Router template bound to a specific API instance. Contains cloned operations with decorators applied. Each mount of a router creates a new BoundRouter instance, ensuring complete isolation between mounts. """ def __init__(self, mount: RouterMount, api: "NinjaAPI") -> None: self.mount = mount self.template = mount.template self.api = api self.prefix = mount.prefix self.url_name_prefix = mount.url_name_prefix # Effective settings priority: # 1. mount override (from api.add_router auth/throttle/tags params on this specific mount) # 2. template's own settings (set on the Router itself) # 3. inherited from parent (for nested routers where parent has auth) if mount.auth is not NOT_SET: self.auth = mount.auth elif mount.template.auth is not NOT_SET: self.auth = mount.template.auth elif mount.inherited_auth is not NOT_SET: self.auth = mount.inherited_auth else: self.auth = NOT_SET if mount.throttle is not NOT_SET: self.throttle = mount.throttle elif mount.template.throttle is not NOT_SET: self.throttle = mount.template.throttle elif mount.inherited_throttle is not NOT_SET: self.throttle = mount.inherited_throttle else: self.throttle = NOT_SET # Tags handling (issue #794): # - mount.tags (from add_router call) = explicit override, use as-is # - Otherwise, accumulate: inherited tags + template's own tags self.tags: Optional[List[str]] if mount.tags is not None: # Explicit tags from add_router() call - use as override self.tags = mount.tags else: # Accumulate inherited tags with template's own tags accumulated_tags: List[str] = [] if mount.inherited_tags is not None: accumulated_tags.extend(mount.inherited_tags) if mount.template.tags is not None: accumulated_tags.extend(mount.template.tags) self.tags = accumulated_tags or None # Clone operations and apply decorators self.path_operations: Dict[str, PathView] = {} self._bind_operations() def _bind_operations(self) -> None: """Clone operations from template and apply effective settings.""" effective_decorators = ( self.mount.inherited_decorators + self.template._decorators ) for path, path_view in self.template.path_operations.items(): cloned_view = path_view.clone() for operation in cloned_view.operations: # Bind to API operation.api = self.api # Apply auth inheritance if operation.auth_param == NOT_SET: if self.auth != NOT_SET: operation._set_auth(self.auth) elif self.api.auth != NOT_SET: operation._set_auth(self.api.auth) # Apply throttle inheritance if operation.throttle_param == NOT_SET: if self.api.throttle != NOT_SET: throttle = self.api.throttle operation.throttle_objects = ( isinstance(throttle, BaseThrottle) and [throttle] or throttle # type: ignore ) if self.throttle != NOT_SET: throttle = self.throttle operation.throttle_objects = ( isinstance(throttle, BaseThrottle) and [throttle] or throttle # type: ignore ) # Apply tags inheritance if operation.tags is None and self.tags is not None: # type: ignore[has-type] operation.tags = self.tags # type: ignore[has-type] # Apply decorators (fresh application - no tracking needed) for decorator, mode in effective_decorators: if mode == "view": operation.run = decorator(operation.run) # type: ignore elif mode == "operation": operation.view_func = decorator(operation.view_func) else: raise ValueError( f"Invalid decorator mode: {mode}" ) # pragma: no cover self.path_operations[path] = cloned_view def urls_paths(self, prefix: str) -> Iterator[URLPattern]: """Generate URL patterns for this bound router.""" prefix = replace_path_param_notation(prefix) for path, path_view in self.path_operations.items(): path = replace_path_param_notation(path) route = "/".join([i for i in (prefix, path) if i]) route = normalize_path(route) route = route.lstrip("/") for operation in path_view.operations: url_name = getattr(operation, "url_name", "") if not url_name: url_name = self.api.get_operation_url_name( operation, router=self.template ) # Apply url_name_prefix if specified if self.url_name_prefix and url_name: url_name = f"{self.url_name_prefix}_{url_name}" yield django_path(route, path_view.get_view(), name=url_name) class Router: def __init__( self, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, tags: Optional[List[str]] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, ) -> None: self._frozen = False self.auth = auth self.throttle = throttle self.tags = tags self.by_alias = by_alias self.exclude_unset = exclude_unset self.exclude_defaults = exclude_defaults self.exclude_none = exclude_none self.path_operations: Dict[str, PathView] = {} self._routers: List[Tuple[str, Router, Optional[List[str]]]] = [] self._decorators: List[Tuple[Callable, DecoratorMode]] = [] def _freeze(self) -> None: """Mark router as frozen - no more modifications allowed.""" self._frozen = True for _, child_router, _ in self._routers: child_router._freeze() def _check_not_frozen(self) -> None: """Raise error if attempting to modify a frozen router.""" if self._frozen: raise ConfigError( "Cannot modify router after URLs have been generated. " "Routers become frozen when api.urls is accessed." ) def get( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: return self.api_operation( ["GET"], path, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def post( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: return self.api_operation( ["POST"], path, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def delete( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: return self.api_operation( ["DELETE"], path, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def patch( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: return self.api_operation( ["PATCH"], path, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def put( self, path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: return self.api_operation( ["PUT"], path, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) def api_operation( self, methods: List[str], path: str, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> Callable[[TCallable], TCallable]: def decorator(view_func: TCallable) -> TCallable: self.add_api_operation( path, methods, view_func, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) return view_func return decorator def add_api_operation( self, path: str, methods: List[str], view_func: Callable, *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, response: Any = NOT_SET, operation_id: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, deprecated: Optional[bool] = None, by_alias: Optional[bool] = None, exclude_unset: Optional[bool] = None, exclude_defaults: Optional[bool] = None, exclude_none: Optional[bool] = None, url_name: Optional[str] = None, include_in_schema: bool = True, openapi_extra: Optional[Dict[str, Any]] = None, ) -> None: self._check_not_frozen() path = re.sub(r"\{uuid:(\w+)\}", r"{uuidstr:\1}", path, flags=re.IGNORECASE) # django by default convert strings to UUIDs # but we want to keep them as strings to let pydantic handle conversion/validation # if user whants UUID object # uuidstr is custom registered converter # No decoration here - will be done in build_routers if path not in self.path_operations: path_view = PathView() self.path_operations[path] = path_view else: path_view = self.path_operations[path] by_alias = by_alias is None and self.by_alias or by_alias exclude_unset = exclude_unset is None and self.exclude_unset or exclude_unset exclude_defaults = ( exclude_defaults is None and self.exclude_defaults or exclude_defaults ) exclude_none = exclude_none is None and self.exclude_none or exclude_none path_view.add_operation( path=path, methods=methods, view_func=view_func, auth=auth, throttle=throttle, response=response, operation_id=operation_id, summary=summary, description=description, tags=tags, deprecated=deprecated, by_alias=by_alias, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, url_name=url_name, include_in_schema=include_in_schema, openapi_extra=openapi_extra, ) # Note: API binding is now done via BoundRouter when urls are generated return None def urls_paths( self, prefix: str, api: Optional["NinjaAPI"] = None ) -> Iterator[URLPattern]: """ Generate URL patterns for this router. Note: This method is primarily for internal use. For mounting routers to APIs, use NinjaAPI.add_router() which handles proper binding via BoundRouter. Args: prefix: URL prefix for all paths api: Optional API instance for generating URL names (for backward compat) """ # Ensure decorators are applied before generating URLs self._apply_decorators_to_operations() prefix = replace_path_param_notation(prefix) for path, path_view in self.path_operations.items(): for operation in path_view.operations: path = replace_path_param_notation(path) route = "/".join([i for i in (prefix, path) if i]) # to skip lot of checks we simply treat double slash as a mistake: route = normalize_path(route) route = route.lstrip("/") url_name = getattr(operation, "url_name", "") if not url_name and api: url_name = api.get_operation_url_name(operation, router=self) yield django_path(route, path_view.get_view(), name=url_name) def add_router( self, prefix: str, router: Union["Router", str], *, auth: Any = NOT_SET, throttle: Union[BaseThrottle, List[BaseThrottle], NOT_SET_TYPE] = NOT_SET, tags: Optional[List[str]] = None, ) -> None: self._check_not_frozen() if isinstance(router, str): router = import_string(router) assert isinstance(router, Router) # Store child router with its mount-time configuration # Auth/throttle are stored on the child router template, # but tags from add_router are stored separately to distinguish from Router(tags=...) if auth != NOT_SET: router.auth = auth if throttle != NOT_SET: router.throttle = throttle # Store as (prefix, router, tags) - tags here are mount-level overrides self._routers.append((prefix, router, tags)) def add_decorator( self, decorator: Callable, mode: DecoratorMode = "operation", ) -> None: """ Add a decorator to be applied to all operations in this router. Args: decorator: The decorator function to apply mode: "operation" (default) applies after validation, "view" applies before validation """ self._check_not_frozen() if mode not in ("view", "operation"): raise ValueError(f"Invalid decorator mode: {mode}") self._decorators.append((decorator, mode)) def build_routers( self, prefix: str, inherited_decorators: Optional[List[Tuple[Callable, DecoratorMode]]] = None, inherited_auth: Any = NOT_SET, inherited_throttle: Any = NOT_SET, inherited_tags: Optional[List[str]] = None, ) -> List[RouterMount]: """ Build mount configurations for this router and all child routers. This method does NOT mutate any router state - it returns a list of RouterMount objects that describe how to bind routers to an API. Args: prefix: The URL prefix for this router inherited_decorators: Decorators inherited from parent routers/API inherited_auth: Auth inherited from parent routers inherited_throttle: Throttle inherited from parent routers inherited_tags: Tags inherited from parent routers Returns: List of RouterMount configurations for this router and all descendants """ if inherited_decorators is None: inherited_decorators = [] # Create mount configuration for this router mount = RouterMount( template=self, prefix=prefix, inherited_decorators=list(inherited_decorators), inherited_auth=inherited_auth, inherited_throttle=inherited_throttle, inherited_tags=inherited_tags, ) # Calculate values to pass to children child_decorators = inherited_decorators + self._decorators # For auth/throttle/tags, effective value is used for children: # priority: this router's own setting > inherited child_auth = self.auth if self.auth is not NOT_SET else inherited_auth child_throttle = ( self.throttle if self.throttle is not NOT_SET else inherited_throttle ) child_tags = self.tags if self.tags is not None else inherited_tags # Build mounts for child routers child_mounts: List[RouterMount] = [] for child_prefix, child_router, child_mount_tags in self._routers: child_path = normalize_path("/".join((prefix, child_prefix))).lstrip("/") mounts = child_router.build_routers( child_path, child_decorators, child_auth, child_throttle, child_tags, ) # Apply mount-level tags override to the first mount (the child router itself) if mounts and child_mount_tags is not None: mounts[0].tags = child_mount_tags child_mounts.extend(mounts) return [mount, *child_mounts] def _apply_decorators_to_operations(self) -> None: """Apply all stored decorators to operations in this router""" for path_view in self.path_operations.values(): for operation in path_view.operations: # Track what decorators have already been applied to avoid duplicates applied_decorators = getattr(operation, "_applied_decorators", []) # Apply decorators that haven't been applied yet for decorator, mode in self._decorators: if (decorator, mode) not in applied_decorators: if mode == "view": operation.run = decorator(operation.run) # type: ignore elif mode == "operation": operation.view_func = decorator(operation.view_func) else: raise ValueError( f"Invalid decorator mode: {mode}" ) # pragma: no cover applied_decorators.append((decorator, mode)) # Store what decorators have been applied operation._applied_decorators = applied_decorators # type: ignore[attr-defined] vitalik-django-ninja-0b67d47/ninja/schema.py000066400000000000000000000205041515660254400207730ustar00rootroot00000000000000""" Since "Model" word would be very confusing when used in django context, this module basically makes an alias for it named "Schema" and adds extra whistles to be able to work with django querysets and managers. The schema is a bit smarter than a standard pydantic Model because it can handle dotted attributes and resolver methods. For example:: class UserSchema(User): name: str initials: str boss: str = Field(None, alias="boss.first_name") @staticmethod def resolve_name(obj): return f"{obj.first_name} {obj.last_name}" """ import warnings from typing import ( Any, Callable, Dict, Type, TypeVar, Union, no_type_check, ) import pydantic from django.db.models import Manager, QuerySet from django.db.models.fields.files import FieldFile from django.template import Variable, VariableDoesNotExist from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, model_validator from pydantic._internal._model_construction import ModelMetaclass from pydantic.functional_validators import ModelWrapValidatorHandler from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue from typing_extensions import dataclass_transform from ninja.signature.utils import get_args_names, has_kwargs from ninja.types import DictStrAny pydantic_version = list(map(int, pydantic.VERSION.split(".")[:2])) assert pydantic_version >= [2, 0], "Pydantic 2.0+ required" __all__ = ["BaseModel", "Field", "DjangoGetter", "Schema"] S = TypeVar("S", bound="Schema") class DjangoGetter: __slots__ = ("_obj", "_schema_cls", "_context", "__dict__") def __init__(self, obj: Any, schema_cls: Type[S], context: Any = None): self._obj = obj self._schema_cls = schema_cls self._context = context def __getattr__(self, key: str) -> Any: # if key.startswith("__pydantic"): # return getattr(self._obj, key) resolver = self._schema_cls._ninja_resolvers.get(key) if resolver: value = resolver(getter=self) else: if isinstance(self._obj, dict): if key not in self._obj: raise AttributeError(key) value = self._obj[key] else: try: value = getattr(self._obj, key) except AttributeError: try: # value = attrgetter(key)(self._obj) value = Variable(key).resolve(self._obj) # TODO: Variable(key) __init__ is actually slower than # Variable.resolve - so it better be cached except VariableDoesNotExist as e: raise AttributeError(key) from e return self._convert_result(value) # def get(self, key: Any, default: Any = None) -> Any: # try: # return self[key] # except KeyError: # return default def _convert_result(self, result: Any) -> Any: if isinstance(result, Manager): return list(result.all()) elif isinstance(result, getattr(QuerySet, "__origin__", QuerySet)): return list(result) if callable(result): return result() elif isinstance(result, FieldFile): if not result: return None return result.url return result def __repr__(self) -> str: return f"" class Resolver: __slots__ = ("_func", "_static", "_takes_context") _static: bool _func: Any _takes_context: bool def __init__(self, func: Union[Callable, staticmethod]): if isinstance(func, staticmethod): self._static = True self._func = func.__func__ else: self._static = False self._func = func arg_names = get_args_names(self._func) self._takes_context = has_kwargs(self._func) or "context" in arg_names def __call__(self, getter: DjangoGetter) -> Any: kwargs = {} if self._takes_context: kwargs["context"] = getter._context if self._static: return self._func(getter._obj, **kwargs) raise NotImplementedError( "Non static resolves are not supported yet" ) # pragma: no cover # return self._func(self._fake_instance(getter), getter._obj) # def _fake_instance(self, getter: DjangoGetter) -> "Schema": # """ # Generate a partial schema instance that can be used as the ``self`` # attribute of resolver functions. # """ # class PartialSchema(Schema): # def __getattr__(self, key: str) -> Any: # value = getattr(getter, key) # field = getter._schema_cls.model_fields[key] # value = field.validate(value, values={}, loc=key, cls=None)[0] # return value # return PartialSchema() @dataclass_transform(kw_only_default=True, field_specifiers=(Field,)) class ResolverMetaclass(ModelMetaclass): _ninja_resolvers: Dict[str, Resolver] @no_type_check def __new__(cls, name, bases, namespace, **kwargs): resolvers = {} for base in reversed(bases): base_resolvers = getattr(base, "_ninja_resolvers", None) if base_resolvers: resolvers.update(base_resolvers) for attr, resolve_func in namespace.items(): if not attr.startswith("resolve_"): continue if ( not callable(resolve_func) # A staticmethod isn't directly callable in Python <=3.9. and not isinstance(resolve_func, staticmethod) ): continue # pragma: no cover resolvers[attr[8:]] = Resolver(resolve_func) result = super().__new__(cls, name, bases, namespace, **kwargs) result._ninja_resolvers = resolvers return result class NinjaGenerateJsonSchema(GenerateJsonSchema): def default_schema(self, schema: Any) -> JsonSchemaValue: # Pydantic default actually renders null's and default_factory's # which really breaks swagger and django model callable defaults # so here we completely override behavior json_schema = self.generate_inner(schema["schema"]) default = None if "default" in schema and schema["default"] is not None: default = self.encode_default(schema["default"]) if "$ref" in json_schema: # Since reference schemas do not support child keys, we wrap the reference schema in a single-case allOf: result = {"allOf": [json_schema]} else: result = json_schema if default is not None: result["default"] = default return result class Schema(BaseModel, metaclass=ResolverMetaclass): model_config = ConfigDict(from_attributes=True) @model_validator(mode="wrap") @classmethod def _run_root_validator( cls, values: Any, handler: ModelWrapValidatorHandler[S], info: ValidationInfo ) -> Any: # If Pydantic intends to validate against the __dict__ of the immediate Schema # object, then we need to call `handler` directly on `values` before the conversion # to DjangoGetter, since any checks or modifications on DjangoGetter's __dict__ # will not persist to the original object. forbids_extra = cls.model_config.get("extra") == "forbid" should_validate_assignment = cls.model_config.get("validate_assignment", False) if forbids_extra or should_validate_assignment: handler(values) values = DjangoGetter(values, cls, info.context) return handler(values) @classmethod def from_orm(cls: Type[S], obj: Any, **kw: Any) -> S: return cls.model_validate(obj, **kw) def dict(self, *a: Any, **kw: Any) -> DictStrAny: "Backward compatibility with pydantic 1.x" return self.model_dump(*a, **kw) @classmethod def json_schema(cls) -> DictStrAny: return cls.model_json_schema(schema_generator=NinjaGenerateJsonSchema) @classmethod def schema(cls) -> DictStrAny: # type: ignore warnings.warn( ".schema() is deprecated, use .json_schema() instead", DeprecationWarning, stacklevel=2, ) return cls.json_schema() vitalik-django-ninja-0b67d47/ninja/security/000077500000000000000000000000001515660254400210275ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/security/__init__.py000066400000000000000000000011011515660254400231310ustar00rootroot00000000000000from ninja.security.apikey import APIKeyCookie, APIKeyHeader, APIKeyQuery from ninja.security.http import HttpBasicAuth, HttpBearer from ninja.security.session import SessionAuth, SessionAuthIsStaff, SessionAuthSuperUser __all__ = [ "APIKeyCookie", "APIKeyHeader", "APIKeyQuery", "HttpBasicAuth", "HttpBearer", "SessionAuth", "SessionAuthSuperUser", "django_auth", "django_auth_superuser", "django_auth_is_staff", ] django_auth = SessionAuth() django_auth_superuser = SessionAuthSuperUser() django_auth_is_staff = SessionAuthIsStaff() vitalik-django-ninja-0b67d47/ninja/security/apikey.py000066400000000000000000000035621515660254400226710ustar00rootroot00000000000000from abc import ABC, abstractmethod from typing import Any, Optional from django.http import HttpRequest from ninja.errors import HttpError from ninja.security.base import AuthBase from ninja.utils import check_csrf __all__ = ["APIKeyBase", "APIKeyQuery", "APIKeyCookie", "APIKeyHeader"] class APIKeyBase(AuthBase, ABC): openapi_type: str = "apiKey" param_name: str = "key" def __init__(self) -> None: self.openapi_name = self.param_name # this sets the name of the security schema super().__init__() def __call__(self, request: HttpRequest) -> Optional[Any]: key = self._get_key(request) return self.authenticate(request, key) @abstractmethod def _get_key(self, request: HttpRequest) -> Optional[str]: pass # pragma: no cover @abstractmethod def authenticate(self, request: HttpRequest, key: Optional[str]) -> Optional[Any]: pass # pragma: no cover class APIKeyQuery(APIKeyBase, ABC): openapi_in: str = "query" def _get_key(self, request: HttpRequest) -> Optional[str]: return request.GET.get(self.param_name) class APIKeyCookie(APIKeyBase, ABC): openapi_in: str = "cookie" def __init__(self, csrf: bool = True) -> None: self.csrf = csrf super().__init__() def _get_key(self, request: HttpRequest) -> Optional[str]: # Skip CSRF check if the operation is marked as csrf_exempt if self.csrf and not getattr(request, "_ninja_csrf_exempt", False): error_response = check_csrf(request) if error_response: raise HttpError(403, "CSRF check Failed") return request.COOKIES.get(self.param_name) class APIKeyHeader(APIKeyBase, ABC): openapi_in: str = "header" def _get_key(self, request: HttpRequest) -> Optional[str]: headers = request.headers return headers.get(self.param_name) vitalik-django-ninja-0b67d47/ninja/security/base.py000066400000000000000000000021051515660254400223110ustar00rootroot00000000000000from abc import ABC, abstractmethod from typing import Any, Optional from django.http import HttpRequest from ninja.errors import ConfigError from ninja.utils import is_async_callable __all__ = ["SecuritySchema", "AuthBase"] class SecuritySchema(dict): def __init__(self, type: str, **kwargs: Any) -> None: super().__init__(type=type, **kwargs) class AuthBase(ABC): def __init__(self) -> None: if not hasattr(self, "openapi_type"): raise ConfigError("If you extend AuthBase you need to define openapi_type") kwargs = {} for attr in dir(self): if attr.startswith("openapi_"): name = attr.replace("openapi_", "", 1) kwargs[name] = getattr(self, attr) self.openapi_security_schema = SecuritySchema(**kwargs) self.is_async = False if hasattr(self, "authenticate"): # pragma: no branch self.is_async = is_async_callable(self.authenticate) @abstractmethod def __call__(self, request: HttpRequest) -> Optional[Any]: pass # pragma: no cover vitalik-django-ninja-0b67d47/ninja/security/http.py000066400000000000000000000051661515660254400223700ustar00rootroot00000000000000import logging from abc import ABC, abstractmethod from base64 import b64decode from typing import Any, Optional, Tuple from urllib.parse import unquote from django.conf import settings from django.http import HttpRequest from ninja.security.base import AuthBase __all__ = ["HttpAuthBase", "HttpBearer", "DecodeError", "HttpBasicAuth"] logger = logging.getLogger("django") class HttpAuthBase(AuthBase, ABC): openapi_type: str = "http" class HttpBearer(HttpAuthBase, ABC): openapi_scheme: str = "bearer" header: str = "Authorization" def __call__(self, request: HttpRequest) -> Optional[Any]: headers = request.headers auth_value = headers.get(self.header) if not auth_value: return None parts = auth_value.split(" ") if parts[0].lower() != self.openapi_scheme: if settings.DEBUG: logger.error(f"Unexpected auth - '{auth_value}'") return None token = " ".join(parts[1:]) return self.authenticate(request, token) @abstractmethod def authenticate(self, request: HttpRequest, token: str) -> Optional[Any]: pass # pragma: no cover class DecodeError(Exception): pass class HttpBasicAuth(HttpAuthBase, ABC): # TODO: maybe HttpBasicAuthBase openapi_scheme = "basic" header = "Authorization" def __call__(self, request: HttpRequest) -> Optional[Any]: headers = request.headers auth_value = headers.get(self.header) if not auth_value: return None try: username, password = self.decode_authorization(auth_value) except DecodeError as e: if settings.DEBUG: logger.exception(e) return None return self.authenticate(request, username, password) @abstractmethod def authenticate( self, request: HttpRequest, username: str, password: str ) -> Optional[Any]: pass # pragma: no cover def decode_authorization(self, value: str) -> Tuple[str, str]: parts = value.split(" ") if len(parts) == 1: user_pass_encoded = parts[0] elif len(parts) == 2 and parts[0].lower() == "basic": user_pass_encoded = parts[1] else: raise DecodeError("Invalid Authorization header") try: username, password = b64decode(user_pass_encoded).decode().split(":", 1) return unquote(username), unquote(password) except Exception as e: # dear contributors please do not change to valueerror - here can be multiple exceptions raise DecodeError("Invalid Authorization header") from e vitalik-django-ninja-0b67d47/ninja/security/session.py000066400000000000000000000025311515660254400230650ustar00rootroot00000000000000from typing import Any, Optional from django.conf import settings from django.http import HttpRequest from ninja.security.apikey import APIKeyCookie __all__ = ["SessionAuth", "SessionAuthSuperUser", "SessionAuthIsStaff"] class SessionAuth(APIKeyCookie): "Reusing Django session authentication" param_name: str = settings.SESSION_COOKIE_NAME def authenticate(self, request: HttpRequest, key: Optional[str]) -> Optional[Any]: if request.user.is_authenticated: return request.user return None class SessionAuthSuperUser(APIKeyCookie): "Reusing Django session authentication & verify that the user is a super user" param_name: str = settings.SESSION_COOKIE_NAME def authenticate(self, request: HttpRequest, key: Optional[str]) -> Optional[Any]: is_superuser = getattr(request.user, "is_superuser", None) if request.user.is_authenticated and is_superuser: return request.user return None class SessionAuthIsStaff(SessionAuthSuperUser): def authenticate(self, request: HttpRequest, key: Optional[str]) -> Optional[Any]: result = super().authenticate(request, key) if result is not None: return result if request.user.is_authenticated and getattr(request.user, "is_staff", None): return request.user return None vitalik-django-ninja-0b67d47/ninja/signature/000077500000000000000000000000001515660254400211615ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/signature/__init__.py000066400000000000000000000002061515660254400232700ustar00rootroot00000000000000from ninja.signature.details import ViewSignature from ninja.signature.utils import is_async __all__ = ["ViewSignature", "is_async"] vitalik-django-ninja-0b67d47/ninja/signature/details.py000066400000000000000000000357201515660254400231670ustar00rootroot00000000000000import inspect import warnings from collections import defaultdict, namedtuple from sys import version_info from typing import Any, Callable, Dict, Generator, List, Optional, Tuple import pydantic from django.http import HttpResponse from pydantic.fields import FieldInfo from pydantic_core import PydanticUndefined from typing_extensions import Annotated, get_args, get_origin from ninja import UploadedFile from ninja.compatibility.util import UNION_TYPES from ninja.errors import ConfigError from ninja.params.models import ( Body, File, Form, Param, Path, Query, TModel, TModels, _MultiPartBody, ) from ninja.signature.utils import get_path_param_names, get_typed_signature from ninja.utils import is_optional_type __all__ = [ "ViewSignature", "is_pydantic_model", "is_collection_type", "detect_collection_fields", ] FuncParam = namedtuple( "FuncParam", ["name", "alias", "source", "annotation", "is_collection"] ) class ViewSignature: FLATTEN_PATH_SEP = ( "\x1e" # ASCII Record Separator. IE: not generally used in query names ) response_arg: Optional[str] = None def __init__(self, path: str, view_func: Callable[..., Any]) -> None: self.view_func = view_func self.signature = get_typed_signature(self.view_func) self.path = path self.path_params_names = get_path_param_names(path) self.docstring = inspect.cleandoc(view_func.__doc__ or "") self.has_kwargs = False self.params = [] for name, arg in self.signature.parameters.items(): if name == "request": # TODO: maybe better assert that 1st param is request or check by type? # maybe even have attribute like `has_request` # so that users can ignore passing request if not needed continue if arg.kind == arg.VAR_KEYWORD: # Skipping **kwargs self.has_kwargs = True continue if arg.kind == arg.VAR_POSITIONAL: # Skipping *args continue if arg.annotation is HttpResponse: self.response_arg = name continue if ( arg.annotation is inspect.Parameter.empty and isinstance(arg.default, type) and issubclass(arg.default, pydantic.BaseModel) ): raise ConfigError( f"Looks like you are using `{name}={arg.default.__name__}` instead of `{name}: {arg.default.__name__}` (annotation)" ) func_param = self._get_param_type(name, arg) self.params.append(func_param) if hasattr(view_func, "_ninja_contribute_args"): # _ninja_contribute_args is a special attribute # which allows developers to create custom function params # inside decorators or other functions for p_name, p_type, p_source in view_func._ninja_contribute_args: self.params.append( FuncParam(p_name, p_source.alias or p_name, p_source, p_type, False) ) self.models: TModels = self._create_models() self._validate_view_path_params() def _validate_view_path_params(self) -> None: """verify all path params are present in the path model fields""" if self.path_params_names: path_model = next( (m for m in self.models if m.__ninja_param_source__ == "path"), None ) missing = tuple( sorted( name for name in self.path_params_names if not (path_model and name in path_model.__ninja_flatten_map__) ) ) if missing: warnings.warn_explicit( UserWarning( f"Field(s) {missing} are in the view path, but were not found in the view signature." ), category=None, filename=inspect.getfile(self.view_func), lineno=inspect.getsourcelines(self.view_func)[1], source=None, ) def _create_models(self) -> TModels: params_by_source_cls: Dict[Any, List[FuncParam]] = defaultdict(list) for param in self.params: param_source_cls = type(param.source) params_by_source_cls[param_source_cls].append(param) is_multipart_response_with_body = Body in params_by_source_cls and ( File in params_by_source_cls or Form in params_by_source_cls ) if is_multipart_response_with_body: params_by_source_cls[_MultiPartBody] = params_by_source_cls.pop(Body) result = [] for param_cls, args in params_by_source_cls.items(): cls_name: str = param_cls.__name__ + "Params" attrs = {i.name: i.source for i in args} attrs["__ninja_param_source__"] = param_cls._param_source() attrs["__ninja_flatten_map_reverse__"] = {} if attrs["__ninja_param_source__"] == "file": pass elif attrs["__ninja_param_source__"] in { "form", "query", "header", "cookie", "path", }: flatten_map = self._args_flatten_map(args) attrs["__ninja_flatten_map__"] = flatten_map attrs["__ninja_flatten_map_reverse__"] = { v: (k,) for k, v in flatten_map.items() } else: assert attrs["__ninja_param_source__"] == "body" if is_multipart_response_with_body: attrs["__ninja_body_params__"] = { i.alias: i.annotation for i in args } else: # ::TODO:: this is still sus. build some test cases attrs["__read_from_single_attr__"] = ( args[0].name if len(args) == 1 else None ) # adding annotations attrs["__annotations__"] = {i.name: i.annotation for i in args} # collection fields: attrs["__ninja_collection_fields__"] = detect_collection_fields( args, attrs.get("__ninja_flatten_map__", {}) ) base_cls = param_cls._model model_cls = type(cls_name, (base_cls,), attrs) # TODO: https://pydantic-docs.helpmanual.io/usage/models/#dynamic-model-creation - check if anything special in create_model method that I did not use result.append(model_cls) return result def _args_flatten_map(self, args: List[FuncParam]) -> Dict[str, Tuple[str, ...]]: flatten_map = {} arg_names: Any = {} for arg in args: if is_pydantic_model(arg.annotation): for name, path in self._model_flatten_map(arg.annotation, arg.alias): if name in flatten_map: raise ConfigError( f"Duplicated name: '{name}' in params: '{arg_names[name]}' & '{arg.name}'" ) flatten_map[name] = tuple(path.split(self.FLATTEN_PATH_SEP)) arg_names[name] = arg.name else: name = arg.alias if name in flatten_map: raise ConfigError( f"Duplicated name: '{name}' also in '{arg_names[name]}'" ) flatten_map[name] = (name,) arg_names[name] = name return flatten_map def _model_flatten_map(self, model: TModel, prefix: str) -> Generator: model = _unwrap_union_model(model) field: FieldInfo for attr, field in model.model_fields.items(): field_name = field.alias or attr name = f"{prefix}{self.FLATTEN_PATH_SEP}{field_name}" if is_pydantic_model(field.annotation): yield from self._model_flatten_map(field.annotation, name) # type: ignore else: yield field_name, name def _get_param_type(self, name: str, arg: inspect.Parameter) -> FuncParam: # _EMPTY = self.signature.empty annotation = arg.annotation default = arg.default if get_origin(annotation) is Annotated: args = get_args(annotation) if isinstance(args[-1], Param): prev_default = default if len(args) == 2: annotation, default = args else: # TODO: Remove version check once support for <=3.8 is dropped. # Annotated[] is only available at runtime in 3.9+ per # https://docs.python.org/3/library/typing.html#typing.Annotated if version_info >= (3, 9): # NOTE: Annotated[args[:-1]] seems to have the same runtime # behavior as Annotated[*args[:-1]], but the latter is # invalid in Python < 3.11 because star expressions # were not allowed in index expressions. annotation, default = Annotated[args[:-1]], args[-1] else: # pragma: no cover -- requires specific Python versions raise NotImplementedError( "This definition requires Python version 3.9+" ) if prev_default != self.signature.empty: default.default = prev_default if annotation == self.signature.empty: if default == self.signature.empty: annotation = str else: if isinstance(default, Param): annotation = type(default.default) else: annotation = type(default) if annotation == PydanticUndefined.__class__: # TODO: ^ check why is that so annotation = str if annotation == type(None) or annotation == type(Ellipsis): # noqa annotation = str is_collection = is_collection_type(annotation) if annotation == UploadedFile or ( is_collection and annotation.__args__[0] == UploadedFile ): # People often forgot to mark UploadedFile as a File, so we better assign it automatically if default == self.signature.empty or default is None: default = default == self.signature.empty and ... or default return FuncParam(name, name, File(default), annotation, is_collection) # 1) if type of the param is defined as one of the Param's subclasses - we just use that definition if isinstance(default, Param): param_source = default # 2) if param name is a part of the path parameter elif name in self.path_params_names: assert ( default == self.signature.empty ), f"'{name}' is a path param, default not allowed" param_source = Path(...) # 3) if param is a collection, or annotation is part of pydantic model: elif is_collection or is_pydantic_model(annotation): if default == self.signature.empty: param_source = Body(...) else: param_source = Body(default) # 4) the last case is query param else: if default == self.signature.empty: param_source = Query(...) else: param_source = Query(default) # If default is None but annotation is not Optional, # wrap it in Optional to allow None values in Pydantic v2 if default is None and not is_optional_type(annotation): annotation = Optional[annotation] return FuncParam( name, param_source.alias or name, param_source, annotation, is_collection ) def _unwrap_union_model(annotation: Any) -> Any: """If annotation is a Union containing a pydantic model, return that model class.""" if get_origin(annotation) in UNION_TYPES: for arg in get_args(annotation): if arg is not type(None) and is_pydantic_model(arg): return arg return annotation def is_pydantic_model(cls: Any) -> bool: try: origin = get_origin(cls) # Handle Annotated types - extract the actual type if origin is Annotated: args = get_args(cls) return is_pydantic_model(args[0]) # Handle Union types if origin in UNION_TYPES: return any(issubclass(arg, pydantic.BaseModel) for arg in get_args(cls)) return issubclass(cls, pydantic.BaseModel) except TypeError: # pragma: no cover return False def is_collection_type(annotation: Any) -> bool: origin = get_origin(annotation) if origin in UNION_TYPES: for arg in get_args(annotation): if is_collection_type(arg): return True return False collection_types = (List, list, set, tuple) if origin is None: return ( isinstance(annotation, collection_types) if not isinstance(annotation, type) else issubclass(annotation, collection_types) ) else: return origin in collection_types # TODO: I guess we should handle only list def detect_collection_fields( args: List[FuncParam], flatten_map: Dict[str, Tuple[str, ...]] ) -> List[str]: """ Django QueryDict has values that are always lists, so we need to help django ninja to understand better the input parameters if it's a list or a single value This method detects attributes that should be treated by ninja as lists and returns this list as a result """ result = [i.alias or i.name for i in args if i.is_collection] if flatten_map: args_d = {arg.alias: arg for arg in args} for path in (p for p in flatten_map.values() if len(p) > 1): annotation_or_field: Any = args_d[path[0]].annotation for attr in path[1:]: if hasattr(annotation_or_field, "annotation"): annotation_or_field = annotation_or_field.annotation annotation_or_field = _unwrap_union_model(annotation_or_field) annotation_or_field = next( ( a for a in annotation_or_field.model_fields.values() if a.alias == attr ), annotation_or_field.model_fields.get(attr), ) # pragma: no cover annotation_or_field = getattr( annotation_or_field, "outer_type_", annotation_or_field ) # if hasattr(annotation_or_field, "annotation"): annotation_or_field = annotation_or_field.annotation if is_collection_type(annotation_or_field): result.append(path[-1]) return result vitalik-django-ninja-0b67d47/ninja/signature/utils.py000066400000000000000000000054341515660254400227010ustar00rootroot00000000000000import asyncio import inspect import re from sys import version_info from typing import Any, Callable, ForwardRef, List, Set from django.urls import register_converter from django.urls.converters import UUIDConverter from pydantic._internal._typing_extra import eval_type_lenient as evaluate_forwardref from ninja.types import DictStrAny __all__ = [ "get_typed_signature", "get_typed_annotation", "make_forwardref", "get_path_param_names", "is_async", ] def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: "Finds call signature and resolves all forwardrefs" signature = inspect.signature(call) globalns = getattr(call, "__globals__", {}) typed_params = [ inspect.Parameter( name=param.name, kind=param.kind, default=param.default, annotation=get_typed_annotation(param, globalns), ) for param in signature.parameters.values() ] typed_signature = inspect.Signature(typed_params) return typed_signature def get_typed_annotation(param: inspect.Parameter, globalns: DictStrAny) -> Any: annotation = param.annotation if isinstance(annotation, str): annotation = make_forwardref(annotation, globalns) return annotation def make_forwardref(annotation: str, globalns: DictStrAny) -> Any: # NOTE: in future versions of pydantic, the import may be changed to: # from pydantic._internal._typing_extra import try_eval_type # usage: # result, _ = try_eval_type(forward_ref, globalns, globalns) forward_ref = ForwardRef(annotation) return evaluate_forwardref(forward_ref, globalns, globalns) def get_path_param_names(path: str) -> Set[str]: """turns path string like /foo/{var}/path/{int:another}/end to set {'var', 'another'}""" return {item.strip("{}").split(":")[-1] for item in re.findall("{[^}]*}", path)} def is_async(callable: Callable[..., Any]) -> bool: # TODO: Drop this condition once support for <= 3.11 is dropped if version_info >= (3, 12): return inspect.iscoroutinefunction(callable) else: return asyncio.iscoroutinefunction(callable) # pragma: no cover def has_kwargs(func: Callable[..., Any]) -> bool: for param in inspect.signature(func).parameters.values(): if param.kind == param.VAR_KEYWORD: return True return False def get_args_names(func: Callable[..., Any]) -> List[str]: "returns list of function argument names" return list(inspect.signature(func).parameters.keys()) class UUIDStrConverter(UUIDConverter): """Return a path converted UUID as a str instead of the standard UUID""" def to_python(self, value: str) -> str: # type: ignore return value # return string value instead of UUID register_converter(UUIDStrConverter, "uuidstr") vitalik-django-ninja-0b67d47/ninja/static/000077500000000000000000000000001515660254400204475ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/static/ninja/000077500000000000000000000000001515660254400215465ustar00rootroot00000000000000vitalik-django-ninja-0b67d47/ninja/static/ninja/favicon.png000066400000000000000000000030251515660254400237010ustar00rootroot00000000000000PNG  IHDRHHUG pHYsodtEXtSoftwarewww.inkscape.org<IDATxiUUK>̧iR6IE`@QB(i/E"STJiҳ^Vf*Φ|>+\{;k3IE nm =B: =@` +a=Irr>(,Afx*Cf~ E`Hv|:y !x<Ђ{r`?X.hJ-j. 2~}!x@&fX,~#{Gel I 0Kqo;O?>i;1ρ9+?ͅjA@o5x b:֜:$GRt 2OQB oÑj1̛ø`Hr|><9*g}/5 \@"iouRf |e{,.?-XUl'E0BV^%LSpI'vōTVͩ:=ºsV@όBԩ1NV KPUGR*/jy39^I%= lKdBOjx$-&_MFt$~32tK QC,T%~0ff)%Gxq@GOFT ӹzy:^IHNu \VXpq(Igގz@w\5.EƉlC3 p ?ʸG;V'љukȁ%fF2]~_LGք ZW6w$bI]5f ]p-IP9P{E[{rIENDB`vitalik-django-ninja-0b67d47/ninja/static/ninja/favicon.svg000066400000000000000000000032031515660254400237120ustar00rootroot00000000000000 vitalik-django-ninja-0b67d47/ninja/static/ninja/redoc.standalone.js000066400000000000000000034540061515660254400253430ustar00rootroot00000000000000/*! For license information please see redoc.standalone.js.LICENSE.txt */ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):"function"==typeof define&&define.amd?define(["null"],t):"object"==typeof exports?exports.Redoc=t(require("null")):e.Redoc=t(e.null)}(this,(function(e){return function(){var t={854:function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:!0}),t.mapTypeToComponent=t.bundleDocument=t.bundleFromString=t.bundle=t.OasVersion=void 0;const i=n(8142),o=n(2928),s=n(2161),a=n(1990),l=n(5735),c=n(3101),u=n(3873),p=n(2900),d=n(3416),f=n(8209),h=n(4125),m=n(474),g=n(4335);var y;function b(e){return r(this,void 0,void 0,(function*(){const{document:t,config:n,customTypes:r,externalRefResolver:i,dereference:u=!1,skipRedoclyRegistryRefs:d=!1,removeUnusedComponents:f=!1,keepUrlRefs:h=!1}=e,y=(0,c.detectSpec)(t.parsed),b=(0,c.getMajorSpecVersion)(y),v=n.getRulesForOasVersion(b),w=(0,a.normalizeTypes)(n.extendTypes(null!=r?r:(0,c.getTypes)(y),y),n),k=(0,p.initRules)(v,n,"preprocessors",y),S=(0,p.initRules)(v,n,"decorators",y),E={problems:[],oasVersion:y,refTypes:new Map,visitorsData:{}};f&&S.push({severity:"error",ruleId:"remove-unused-components",visitor:b===c.SpecMajorVersion.OAS2?(0,m.RemoveUnusedComponents)({}):(0,g.RemoveUnusedComponents)({})});let O=yield(0,o.resolveDocument)({rootDocument:t,rootType:w.Root,externalRefResolver:i});k.length>0&&((0,l.walkDocument)({document:t,rootType:w.Root,normalizedVisitors:(0,s.normalizeVisitors)(k,w),resolvedRefMap:O,ctx:E}),O=yield(0,o.resolveDocument)({rootDocument:t,rootType:w.Root,externalRefResolver:i}));const _=(0,s.normalizeVisitors)([{severity:"error",ruleId:"bundler",visitor:x(b,u,d,t,O,h)},...S],w);return(0,l.walkDocument)({document:t,rootType:w.Root,normalizedVisitors:_,resolvedRefMap:O,ctx:E}),{bundle:t,problems:E.problems.map((e=>n.addProblemToIgnore(e))),fileDependencies:i.getFiles(),rootType:w.Root,refTypes:E.refTypes,visitorsData:E.visitorsData}}))}function v(e,t){switch(t){case c.SpecMajorVersion.OAS3:switch(e){case"Schema":return"schemas";case"Parameter":return"parameters";case"Response":return"responses";case"Example":return"examples";case"RequestBody":return"requestBodies";case"Header":return"headers";case"SecuritySchema":return"securitySchemes";case"Link":return"links";case"Callback":return"callbacks";default:return null}case c.SpecMajorVersion.OAS2:switch(e){case"Schema":return"definitions";case"Parameter":return"parameters";case"Response":return"responses";default:return null}case c.SpecMajorVersion.Async2:switch(e){case"Schema":return"schemas";case"Parameter":return"parameters";default:return null}}}function x(e,t,n,r,s,a){let l,p;const m={ref:{leave(i,l,c){if(!c.location||void 0===c.node)return void(0,d.reportUnresolvedRef)(c,l.report,l.location);if(c.location.source===r.source&&c.location.source===l.location.source&&"scalar"!==l.type.name&&!t)return;if(n&&(0,h.isRedoclyRegistryURL)(i.$ref))return;if(a&&(0,u.isAbsoluteUrl)(i.$ref))return;const p=v(l.type.name,e);p?t?(y(p,c,l),g(i,c,l)):(i.$ref=y(p,c,l),function(e,t,n){const i=(0,o.makeRefId)(n.location.source.absoluteRef,e.$ref);s.set(i,{document:r,isRemote:!1,node:t.node,nodePointer:e.$ref,resolved:!0})}(i,c,l)):g(i,c,l)}},Root:{enter(t,n){p=n.location,e===c.SpecMajorVersion.OAS3?l=t.components=t.components||{}:e===c.SpecMajorVersion.OAS2&&(l=t)}}};function g(e,t,n){if((0,f.isPlainObject)(t.node)){delete e.$ref;const n=Object.assign({},t.node,e);Object.assign(e,n)}else n.parent[n.key]=t.node}function y(t,n,r){l[t]=l[t]||{};const i=function(e,t,n){const[r,i]=[e.location.source.absoluteRef,e.location.pointer],o=l[t];let s="";const a=i.slice(2).split("/").filter(f.isTruthy);for(;a.length>0;)if(s=a.pop()+(s?`-${s}`:""),!o||!o[s]||b(o[s],e,n))return s;if(s=(0,u.refBaseName)(r)+(s?`_${s}`:""),!o[s]||b(o[s],e,n))return s;const c=s;let p=2;for(;o[s]&&!b(o[s],e,n);)s=`${c}-${p}`,p++;return o[s]||n.report({message:`Two schemas are referenced with the same name but different content. Renamed ${c} to ${s}.`,location:n.location,forceSeverity:"warn"}),s}(n,t,r);return l[t][i]=n.node,e===c.SpecMajorVersion.OAS3?`#/components/${t}/${i}`:`#/${t}/${i}`}function b(e,t,n){var r;return!(!(0,u.isRef)(e)||(null===(r=n.resolve(e,p.absolutePointer).location)||void 0===r?void 0:r.absolutePointer)!==t.location.absolutePointer)||i(e,t.node)}return e===c.SpecMajorVersion.OAS3&&(m.DiscriminatorMapping={leave(n,r){for(const i of Object.keys(n)){const o=n[i],s=r.resolve({$ref:o});if(!s.location||void 0===s.node)return void(0,d.reportUnresolvedRef)(s,r.report,r.location.child(i));const a=v("Schema",e);t?y(a,s,r):n[i]=y(a,s,r)}}}),m}!function(e){e.Version2="oas2",e.Version3_0="oas3_0",e.Version3_1="oas3_1"}(y||(t.OasVersion=y={})),t.bundle=function(e){return r(this,void 0,void 0,(function*(){const{ref:t,doc:n,externalRefResolver:r=new o.BaseResolver(e.config.resolve),base:i=null}=e;if(!t&&!n)throw new Error("Document or reference is required.\n");const s=void 0===n?yield r.resolveDocument(i,t,!0):n;if(s instanceof Error)throw s;return b(Object.assign(Object.assign({document:s},e),{config:e.config.styleguide,externalRefResolver:r}))}))},t.bundleFromString=function(e){return r(this,void 0,void 0,(function*(){const{source:t,absoluteRef:n,externalRefResolver:r=new o.BaseResolver(e.config.resolve)}=e,i=(0,o.makeDocumentFromString)(t,n||"/");return b(Object.assign(Object.assign({document:i},e),{externalRefResolver:r,config:e.config.styleguide}))}))},t.bundleDocument=b,t.mapTypeToComponent=v},8921:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Config=t.StyleguideConfig=t.AVAILABLE_REGIONS=t.DOMAINS=t.DEFAULT_REGION=t.IGNORE_FILE=void 0;const r=n(7992),i=n(7975),o=n(970),s=n(8209),a=n(3101),l=n(1827),c=n(462),u=n(3873);t.IGNORE_FILE=".redocly.lint-ignore.yaml",t.DEFAULT_REGION="us",t.DOMAINS=function(){const e={us:"redocly.com",eu:"eu.redocly.com"},t=l.env.REDOCLY_DOMAIN;return(null==t?void 0:t.endsWith(".redocly.host"))&&(e[t.split(".")[0]]=t),"redoc.online"===t&&(e[t]=t),e}(),t.AVAILABLE_REGIONS=Object.keys(t.DOMAINS);class p{constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},this._usedRules=new Set,this._usedVersions=new Set,this.plugins=e.plugins||[],this.doNotResolveExamples=!!e.doNotResolveExamples,this.recommendedFallback=e.recommendedFallback||!1,this.rules={[a.SpecVersion.OAS2]:Object.assign(Object.assign({},e.rules),e.oas2Rules),[a.SpecVersion.OAS3_0]:Object.assign(Object.assign({},e.rules),e.oas3_0Rules),[a.SpecVersion.OAS3_1]:Object.assign(Object.assign({},e.rules),e.oas3_1Rules),[a.SpecVersion.Async2]:Object.assign(Object.assign({},e.rules),e.async2Rules)},this.preprocessors={[a.SpecVersion.OAS2]:Object.assign(Object.assign({},e.preprocessors),e.oas2Preprocessors),[a.SpecVersion.OAS3_0]:Object.assign(Object.assign({},e.preprocessors),e.oas3_0Preprocessors),[a.SpecVersion.OAS3_1]:Object.assign(Object.assign({},e.preprocessors),e.oas3_1Preprocessors),[a.SpecVersion.Async2]:Object.assign(Object.assign({},e.preprocessors),e.async2Preprocessors)},this.decorators={[a.SpecVersion.OAS2]:Object.assign(Object.assign({},e.decorators),e.oas2Decorators),[a.SpecVersion.OAS3_0]:Object.assign(Object.assign({},e.decorators),e.oas3_0Decorators),[a.SpecVersion.OAS3_1]:Object.assign(Object.assign({},e.decorators),e.oas3_1Decorators),[a.SpecVersion.Async2]:Object.assign(Object.assign({},e.decorators),e.async2Decorators)},this.extendPaths=e.extendPaths||[],this.pluginPaths=e.pluginPaths||[],this.resolveIgnore(function(e){return e?(0,s.doesYamlFileExist)(e)?i.join(i.dirname(e),t.IGNORE_FILE):i.join(e,t.IGNORE_FILE):l.isBrowser?void 0:i.join(process.cwd(),t.IGNORE_FILE)}(n))}resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.parseYaml)(r.readFileSync(e,"utf-8"))||{};for(const t of Object.keys(this.ignore)){this.ignore[(0,u.isAbsoluteUrl)(t)?t:i.resolve(i.dirname(e),t)]=this.ignore[t];for(const e of Object.keys(this.ignore[t]))this.ignore[t][e]=new Set(this.ignore[t][e]);(0,u.isAbsoluteUrl)(t)||delete this.ignore[t]}}}saveIgnore(){const e=this.configFile?i.dirname(this.configFile):process.cwd(),n=i.join(e,t.IGNORE_FILE),a={};for(const t of Object.keys(this.ignore)){const n=a[(0,u.isAbsoluteUrl)(t)?t:(0,s.slash)(i.relative(e,t))]=this.ignore[t];for(const e of Object.keys(n))n[e]=Array.from(n[e])}r.writeFileSync(n,"# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n# See https://redoc.ly/docs/cli/ for more information.\n"+(0,o.stringifyYaml)(a))}addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer)return;const r=t[n.source.absoluteRef]=t[n.source.absoluteRef]||{};(r[e.ruleId]=r[e.ruleId]||new Set).add(n.pointer)}addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)return e;const n=(this.ignore[t.source.absoluteRef]||{})[e.ruleId],r=n&&n.has(t.pointer);return r?Object.assign(Object.assign({},e),{ignored:r}):e}extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typeExtension)switch(t){case a.SpecVersion.OAS3_0:case a.SpecVersion.OAS3_1:if(!e.typeExtension.oas3)continue;n=e.typeExtension.oas3(n,t);break;case a.SpecVersion.OAS2:if(!e.typeExtension.oas2)continue;n=e.typeExtension.oas2(n,t);break;case a.SpecVersion.Async2:if(!e.typeExtension.async2)continue;n=e.typeExtension.async2(n,t);break;default:throw new Error("Not implemented")}return n}getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);const n=this.rules[t][e]||"off";return"string"==typeof n?{severity:n}:Object.assign({severity:"error"},n)}getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);const n=this.preprocessors[t][e]||"off";return"string"==typeof n?{severity:"on"===n?"error":n}:Object.assign({severity:"error"},n)}getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);const n=this.decorators[t][e]||"off";return"string"==typeof n?{severity:"on"===n?"error":n}:Object.assign({severity:"error"},n)}getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._usedVersions))e.push(...Object.keys(this.rules[r]).filter((e=>!this._usedRules.has(e)))),t.push(...Object.keys(this.decorators[r]).filter((e=>!this._usedRules.has(e)))),n.push(...Object.keys(this.preprocessors[r]).filter((e=>!this._usedRules.has(e))));return{rules:e,preprocessors:n,decorators:t}}getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const e=[];return this.plugins.forEach((t=>{var n;return(null===(n=t.preprocessors)||void 0===n?void 0:n.oas3)&&e.push(t.preprocessors.oas3)})),this.plugins.forEach((t=>{var n;return(null===(n=t.rules)||void 0===n?void 0:n.oas3)&&e.push(t.rules.oas3)})),this.plugins.forEach((t=>{var n;return(null===(n=t.decorators)||void 0===n?void 0:n.oas3)&&e.push(t.decorators.oas3)})),e;case a.SpecMajorVersion.OAS2:const t=[];return this.plugins.forEach((e=>{var n;return(null===(n=e.preprocessors)||void 0===n?void 0:n.oas2)&&t.push(e.preprocessors.oas2)})),this.plugins.forEach((e=>{var n;return(null===(n=e.rules)||void 0===n?void 0:n.oas2)&&t.push(e.rules.oas2)})),this.plugins.forEach((e=>{var n;return(null===(n=e.decorators)||void 0===n?void 0:n.oas2)&&t.push(e.decorators.oas2)})),t;case a.SpecMajorVersion.Async2:const n=[];return this.plugins.forEach((e=>{var t;return(null===(t=e.preprocessors)||void 0===t?void 0:t.async2)&&n.push(e.preprocessors.async2)})),this.plugins.forEach((e=>{var t;return(null===(t=e.rules)||void 0===t?void 0:t.async2)&&n.push(e.rules.async2)})),this.plugins.forEach((e=>{var t;return(null===(t=e.decorators)||void 0===t?void 0:t.async2)&&n.push(e.decorators.async2)})),n}}skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecVersion))this.rules[e][t]&&(this.rules[e][t]="off")}skipPreprocessors(e){for(const t of e||[])for(const e of Object.values(a.SpecVersion))this.preprocessors[e][t]&&(this.preprocessors[e][t]="off")}skipDecorators(e){for(const t of e||[])for(const e of Object.values(a.SpecVersion))this.decorators[e][t]&&(this.decorators[e][t]="off")}}t.StyleguideConfig=p,t.Config=class{constructor(e,t){this.rawConfig=e,this.configFile=t,this.apis=e.apis||{},this.styleguide=new p(e.styleguide||{},t),this.theme=e.theme||{},this.resolve=(0,c.getResolveConfig)(null==e?void 0:e.resolve),this.region=e.region,this.organization=e.organization,this.files=e.files||[],this.telemetry=e.telemetry}}},2900:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.initRules=void 0;const r=n(8209);t.initRules=function(e,t,n,i){return e.flatMap((e=>Object.keys(e).map((r=>{const o=e[r],s="rules"===n?t.getRuleSettings(r,i):"preprocessors"===n?t.getPreprocessorSettings(r,i):t.getDecoratorSettings(r,i);if("off"===s.severity)return;const a=s.severity,l=o(s);return Array.isArray(l)?l.map((e=>({severity:a,ruleId:r,visitor:e}))):{severity:a,ruleId:r,visitor:l}})))).flatMap((e=>e)).filter(r.isDefined)}},462:function(e,t,n){"use strict";var r=this&&this.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);it[e]));n[e]&&null===t&&(0,i.showWarningForDeprecatedField)(e),n[e]&&t&&n[t]&&(0,i.showErrorForDeprecatedField)(e,t),n[e]&&r&&n[r]&&(0,i.showErrorForDeprecatedField)(e,t,r),(n[e]||o)&&(0,i.showWarningForDeprecatedField)(e,t,r)}t.parsePresetName=function(e){if(e.indexOf("/")>-1){const[t,n]=e.split("/");return{pluginId:t,configName:n}}return{pluginId:"",configName:e}},t.transformApiDefinitionsToApis=a,t.prefixRules=function(e,t){if(!t)return e;const n={};for(const r of Object.keys(e))n[`${t}/${r}`]=e[r];return n},t.mergeExtends=function(e){const t={rules:{},oas2Rules:{},oas3_0Rules:{},oas3_1Rules:{},async2Rules:{},preprocessors:{},oas2Preprocessors:{},oas3_0Preprocessors:{},oas3_1Preprocessors:{},async2Preprocessors:{},decorators:{},oas2Decorators:{},oas3_0Decorators:{},oas3_1Decorators:{},async2Decorators:{},plugins:[],pluginPaths:[],extendPaths:[]};for(const n of e){if(n.extends)throw new Error(`'extends' is not supported in shared configs yet: ${JSON.stringify(n,null,2)}.`);Object.assign(t.rules,n.rules),Object.assign(t.oas2Rules,n.oas2Rules),(0,i.assignExisting)(t.oas2Rules,n.rules||{}),Object.assign(t.oas3_0Rules,n.oas3_0Rules),(0,i.assignExisting)(t.oas3_0Rules,n.rules||{}),Object.assign(t.oas3_1Rules,n.oas3_1Rules),(0,i.assignExisting)(t.oas3_1Rules,n.rules||{}),Object.assign(t.async2Rules,n.async2Rules),(0,i.assignExisting)(t.async2Rules,n.rules||{}),Object.assign(t.preprocessors,n.preprocessors),Object.assign(t.oas2Preprocessors,n.oas2Preprocessors),(0,i.assignExisting)(t.oas2Preprocessors,n.preprocessors||{}),Object.assign(t.oas3_0Preprocessors,n.oas3_0Preprocessors),(0,i.assignExisting)(t.oas3_0Preprocessors,n.preprocessors||{}),Object.assign(t.oas3_1Preprocessors,n.oas3_1Preprocessors),(0,i.assignExisting)(t.oas3_1Preprocessors,n.preprocessors||{}),Object.assign(t.async2Preprocessors,n.async2Preprocessors),(0,i.assignExisting)(t.async2Preprocessors,n.preprocessors||{}),Object.assign(t.decorators,n.decorators),Object.assign(t.oas2Decorators,n.oas2Decorators),(0,i.assignExisting)(t.oas2Decorators,n.decorators||{}),Object.assign(t.oas3_0Decorators,n.oas3_0Decorators),(0,i.assignExisting)(t.oas3_0Decorators,n.decorators||{}),Object.assign(t.oas3_1Decorators,n.oas3_1Decorators),(0,i.assignExisting)(t.oas3_1Decorators,n.decorators||{}),Object.assign(t.async2Decorators,n.async2Decorators),(0,i.assignExisting)(t.async2Decorators,n.decorators||{}),t.plugins.push(...n.plugins||[]),t.pluginPaths.push(...n.pluginPaths||[]),t.extendPaths.push(...new Set(n.extendPaths))}return t},t.getMergedConfig=function(e,t){var n,r,s,a,l,c,u,p;const d=[...Object.values(e.apis).map((e=>{var t;return null===(t=null==e?void 0:e.styleguide)||void 0===t?void 0:t.extendPaths})),null===(r=null===(n=e.rawConfig)||void 0===n?void 0:n.styleguide)||void 0===r?void 0:r.extendPaths].flat().filter(i.isTruthy),f=[...Object.values(e.apis).map((e=>{var t;return null===(t=null==e?void 0:e.styleguide)||void 0===t?void 0:t.pluginPaths})),null===(a=null===(s=e.rawConfig)||void 0===s?void 0:s.styleguide)||void 0===a?void 0:a.pluginPaths].flat().filter(i.isTruthy);return t?new o.Config(Object.assign(Object.assign({},e.rawConfig),{styleguide:Object.assign(Object.assign({},e.apis[t]?e.apis[t].styleguide:e.rawConfig.styleguide),{extendPaths:d,pluginPaths:f}),theme:Object.assign(Object.assign({},e.rawConfig.theme),null===(l=e.apis[t])||void 0===l?void 0:l.theme),files:[...e.files,...null!==(p=null===(u=null===(c=e.apis)||void 0===c?void 0:c[t])||void 0===u?void 0:u.files)&&void 0!==p?p:[]]}),e.configFile):e},t.checkForDeprecatedFields=u,t.transformConfig=function(e){var t,n;const i=[["apiDefinitions","apis",void 0],["referenceDocs","openapi","theme"],["lint",void 0,void 0],["styleguide",void 0,void 0],["features.openapi","openapi","theme"]];for(const[t,n,r]of i)u(t,n,e,r);const{apis:o,apiDefinitions:p,referenceDocs:d,lint:f}=e,h=r(e,["apis","apiDefinitions","referenceDocs","lint"]),{styleguideConfig:m,rawConfigRest:g}=l(h),y=Object.assign({theme:{openapi:Object.assign(Object.assign(Object.assign({},d),e["features.openapi"]),null===(t=e.theme)||void 0===t?void 0:t.openapi),mockServer:Object.assign(Object.assign({},e["features.mockServer"]),null===(n=e.theme)||void 0===n?void 0:n.mockServer)},apis:c(o)||a(p),styleguide:m||f},g);return function(e){var t,n;let r=Object.assign({},null===(t=e.styleguide)||void 0===t?void 0:t.rules);for(const t of Object.values(e.apis||{}))r=Object.assign(Object.assign({},r),null===(n=null==t?void 0:t.styleguide)||void 0===n?void 0:n.rules);for(const e of Object.keys(r))e.startsWith("assert/")&&s.logger.warn(`\nThe 'assert/' syntax in ${e} is deprecated. Update your configuration to use 'rule/' instead. Examples and more information: https://redocly.com/docs/cli/rules/configurable-rules/\n`)}(y),y},t.getResolveConfig=function(e){var t,n;return{http:{headers:null!==(n=null===(t=null==e?void 0:e.http)||void 0===t?void 0:t.headers)&&void 0!==n?n:[],customFetch:void 0}}},t.getUniquePlugins=function(e){const t=new Set,n=[];for(const r of e)t.has(r.id)?r.id&&s.logger.warn(`Duplicate plugin id "${s.colorize.red(r.id)}".\n`):(n.push(r),t.add(r.id));return n};class p extends Error{}t.ConfigValidationError=p},1827:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.env=t.isBrowser=void 0,t.isBrowser="undefined"!=typeof window||"undefined"!=typeof self||"undefined"==typeof process,t.env=t.isBrowser?{}:{}||{}},970:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.stringifyYaml=t.parseYaml=void 0;const r=n(7210),i=r.JSON_SCHEMA.extend({implicit:[r.types.merge],explicit:[r.types.binary,r.types.omap,r.types.pairs,r.types.set]});t.parseYaml=(e,t)=>(0,r.load)(e,Object.assign({schema:i},t)),t.stringifyYaml=(e,t)=>(0,r.dump)(e,t)},2678:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.logger=t.colorize=t.colorOptions=void 0;const r=n(8825);var i=n(8825);Object.defineProperty(t,"colorOptions",{enumerable:!0,get:function(){return i.options}});const o=n(1827),s=n(8209);t.colorize=new Proxy(r,{get(e,t){return o.isBrowser?s.identity:e[t]}}),t.logger=new class{stderr(e){return process.stderr.write(e)}info(e){return o.isBrowser?console.log(e):this.stderr(e)}warn(e){return o.isBrowser?console.warn(e):this.stderr(t.colorize.yellow(e))}error(e){return o.isBrowser?console.error(e):this.stderr(t.colorize.red(e))}}},3101:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getTypes=t.getMajorSpecVersion=t.detectSpec=t.SpecMajorVersion=t.SpecVersion=void 0;const r=n(4409),i=n(4154),o=n(2082),s=n(264);var a,l;!function(e){e.OAS2="oas2",e.OAS3_0="oas3_0",e.OAS3_1="oas3_1",e.Async2="async2"}(a||(t.SpecVersion=a={})),function(e){e.OAS2="oas2",e.OAS3="oas3",e.Async2="async2"}(l||(t.SpecMajorVersion=l={}));const c={[a.OAS2]:r.Oas2Types,[a.OAS3_0]:i.Oas3Types,[a.OAS3_1]:o.Oas3_1Types,[a.Async2]:s.AsyncApi2Types};t.detectSpec=function(e){if("object"!=typeof e)throw new Error("Document must be JSON object, got "+typeof e);if(e.openapi&&"string"!=typeof e.openapi)throw new Error(`Invalid OpenAPI version: should be a string but got "${typeof e.openapi}"`);if(e.openapi&&e.openapi.startsWith("3.0"))return a.OAS3_0;if(e.openapi&&e.openapi.startsWith("3.1"))return a.OAS3_1;if(e.swagger&&"2.0"===e.swagger)return a.OAS2;if(e.openapi||e.swagger)throw new Error(`Unsupported OpenAPI version: ${e.openapi||e.swagger}`);if(e.asyncapi&&e.asyncapi.startsWith("2."))return a.Async2;if(e.asyncapi)throw new Error(`Unsupported AsyncAPI version: ${e.asyncapi}`);throw new Error("Unsupported specification")},t.getMajorSpecVersion=function(e){return e===a.OAS2?l.OAS2:e===a.Async2?l.Async2:l.OAS3},t.getTypes=function(e){return c[e]}},4125:function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:!0}),t.isRedoclyRegistryURL=t.RedoclyClient=void 0;const i=n(3986),o=n(7975),s=n(2941),a=n(919),l=n(8921),c=n(1827),u=n(8209),p=n(2678),d=".redocly-config.json";t.RedoclyClient=class{constructor(e){this.accessTokens={},this.region=this.loadRegion(e),this.loadTokens(),this.domain=e?l.DOMAINS[e]:c.env.REDOCLY_DOMAIN||l.DOMAINS[l.DEFAULT_REGION],c.env.REDOCLY_DOMAIN=this.domain,this.registryApi=new a.RegistryApi(this.accessTokens,this.region)}loadRegion(e){if(e&&!l.DOMAINS[e])throw new Error(`Invalid argument: region in config file.\nGiven: ${p.colorize.green(e)}, choices: "us", "eu".`);return c.env.REDOCLY_DOMAIN?l.AVAILABLE_REGIONS.find((e=>l.DOMAINS[e]===c.env.REDOCLY_DOMAIN))||l.DEFAULT_REGION:e||l.DEFAULT_REGION}getRegion(){return this.region}hasTokens(){return(0,u.isNotEmptyObject)(this.accessTokens)}hasToken(){return!!this.accessTokens[this.region]}getAuthorizationHeader(){return r(this,void 0,void 0,(function*(){return this.accessTokens[this.region]}))}setAccessTokens(e){this.accessTokens=e}loadTokens(){const e=(0,o.resolve)((0,s.homedir)(),d),t=this.readCredentialsFile(e);(0,u.isNotEmptyObject)(t)&&this.setAccessTokens(Object.assign(Object.assign({},t),t.token&&!t[this.region]&&{[this.region]:t.token})),c.env.REDOCLY_AUTHORIZATION&&this.setAccessTokens(Object.assign(Object.assign({},this.accessTokens),{[this.region]:c.env.REDOCLY_AUTHORIZATION}))}getAllTokens(){return Object.entries(this.accessTokens).filter((([e])=>l.AVAILABLE_REGIONS.includes(e))).map((([e,t])=>({region:e,token:t})))}getValidTokens(){return r(this,void 0,void 0,(function*(){const e=this.getAllTokens(),t=yield Promise.allSettled(e.map((({token:e,region:t})=>this.verifyToken(e,t))));return e.filter(((e,n)=>"fulfilled"===t[n].status)).map((({token:e,region:t})=>({token:e,region:t,valid:!0})))}))}getTokens(){return r(this,void 0,void 0,(function*(){return this.hasTokens()?yield this.getValidTokens():[]}))}isAuthorizedWithRedoclyByRegion(){return r(this,void 0,void 0,(function*(){if(!this.hasTokens())return!1;const e=this.accessTokens[this.region];if(!e)return!1;try{return yield this.verifyToken(e,this.region),!0}catch(e){return!1}}))}isAuthorizedWithRedocly(){return r(this,void 0,void 0,(function*(){return this.hasTokens()&&(0,u.isNotEmptyObject)(yield this.getValidTokens())}))}readCredentialsFile(e){return(0,i.existsSync)(e)?JSON.parse((0,i.readFileSync)(e,"utf-8")):{}}verifyToken(e,t,n=!1){return r(this,void 0,void 0,(function*(){return this.registryApi.authStatus(e,t,n)}))}login(e,t=!1){return r(this,void 0,void 0,(function*(){const n=(0,o.resolve)((0,s.homedir)(),d);try{yield this.verifyToken(e,this.region,t)}catch(e){throw new Error("Authorization failed. Please check if you entered a valid API key.")}const r=Object.assign(Object.assign({},this.readCredentialsFile(n)),{[this.region]:e,token:e});this.accessTokens=r,this.registryApi.setAccessTokens(r),(0,i.writeFileSync)(n,JSON.stringify(r,null,2))}))}logout(){const e=(0,o.resolve)((0,s.homedir)(),d);(0,i.existsSync)(e)&&(0,i.unlinkSync)(e)}},t.isRedoclyRegistryURL=function(e){const t=c.env.REDOCLY_DOMAIN||l.DOMAINS[l.DEFAULT_REGION],n="redocly.com"===t?"redoc.ly":t;return!(!e.startsWith(`https://api.${t}/registry/`)&&!e.startsWith(`https://api.${n}/registry/`))}},919:function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:!0}),t.RegistryApi=void 0;const i=n(8381),o=n(8921),s=n(8209),a=n(2079).rE;t.RegistryApi=class{constructor(e,t){this.accessTokens=e,this.region=t}get accessToken(){return(0,s.isNotEmptyObject)(this.accessTokens)&&this.accessTokens[this.region]}getBaseUrl(e=o.DEFAULT_REGION){return`https://api.${o.DOMAINS[e]}/registry`}setAccessTokens(e){return this.accessTokens=e,this}request(e="",t={},n){var o,s;return r(this,void 0,void 0,(function*(){const r="undefined"!=typeof process&&(null===(o={})||void 0===o?void 0:o.REDOCLY_CLI_COMMAND)||"",l="undefined"!=typeof process&&(null===(s={})||void 0===s?void 0:s.REDOCLY_ENVIRONMENT)||"",c=Object.assign({},t.headers||{},{"x-redocly-cli-version":a,"user-agent":`redocly-cli / ${a} ${r} ${l}`});if(!c.hasOwnProperty("authorization"))throw new Error("Unauthorized");const u=yield(0,i.default)(`${this.getBaseUrl(n)}${e}`,Object.assign({},t,{headers:c}));if(401===u.status)throw new Error("Unauthorized");if(404===u.status){const e=yield u.json();throw new Error(e.code)}return u}))}authStatus(e,t,n=!1){return r(this,void 0,void 0,(function*(){try{const n=yield this.request("",{headers:{authorization:e}},t);return yield n.json()}catch(e){throw n&&console.log(e),e}}))}prepareFileUpload({organizationId:e,name:t,version:n,filesHash:i,filename:o,isUpsert:s}){return r(this,void 0,void 0,(function*(){const r=yield this.request(`/${e}/${t}/${n}/prepare-file-upload`,{method:"POST",headers:{"content-type":"application/json",authorization:this.accessToken},body:JSON.stringify({filesHash:i,filename:o,isUpsert:s})},this.region);if(r.ok)return r.json();throw new Error("Could not prepare file upload")}))}pushApi({organizationId:e,name:t,version:n,rootFilePath:i,filePaths:o,branch:s,isUpsert:a,isPublic:l,batchId:c,batchSize:u}){return r(this,void 0,void 0,(function*(){if(!(yield this.request(`/${e}/${t}/${n}`,{method:"PUT",headers:{"content-type":"application/json",authorization:this.accessToken},body:JSON.stringify({rootFilePath:i,filePaths:o,branch:s,isUpsert:a,isPublic:l,batchId:c,batchSize:u})},this.region)).ok)throw new Error("Could not push api")}))}}},3873:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isAnchor=t.isMappingRef=t.isAbsoluteUrl=t.refBaseName=t.pointerBaseName=t.parsePointer=t.parseRef=t.escapePointer=t.unescapePointer=t.Location=t.isRef=t.joinPointer=void 0;const r=n(8209);function i(e,t){return""===e&&(e="#/"),"/"===e[e.length-1]?e+t:e+"/"+t}t.joinPointer=i,t.isRef=function(e){return e&&"string"==typeof e.$ref};class o{constructor(e,t){this.source=e,this.pointer=t}child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[e]).map(a).join("/")))}key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}get absolutePointer(){return this.source.absoluteRef+("#/"===this.pointer?"":this.pointer)}}function s(e){return decodeURIComponent(e.replace(/~1/g,"/").replace(/~0/g,"~"))}function a(e){return"number"==typeof e?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}t.Location=o,t.unescapePointer=s,t.escapePointer=a,t.parseRef=function(e){const[t,n]=e.split("#/");return{uri:t||null,pointer:n?n.split("/").map(s).filter(r.isTruthy):[]}},t.parsePointer=function(e){return e.substr(2).split("/").map(s)},t.pointerBaseName=function(e){const t=e.split("/");return t[t.length-1]},t.refBaseName=function(e){const t=e.split(/[\/\\]/);return t[t.length-1].replace(/\.[^.]+$/,"")},t.isAbsoluteUrl=function(e){return e.startsWith("http://")||e.startsWith("https://")},t.isMappingRef=function(e){return e.startsWith("#")||e.startsWith("https://")||e.startsWith("http://")||e.startsWith("./")||e.startsWith("../")||e.indexOf("/")>-1},t.isAnchor=function(e){return/^#[A-Za-z][A-Za-z0-9\-_:.]*$/.test(e)}},2928:function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:!0}),t.resolveDocument=t.BaseResolver=t.makeDocumentFromString=t.makeRefId=t.YamlParseError=t.ResolveError=t.Source=void 0;const i=n(7411),o=n(7975),s=n(3873),a=n(1990),l=n(8209);class c{constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this.body,{filename:this.absoluteRef}))&&void 0!==t?t:void 0,this._ast&&0===this._ast.kind&&""===this._ast.value&&1!==this._ast.startPosition&&(this._ast.startPosition=1,this._ast.endPosition=1)),this._ast}getLines(){return void 0===this._lines&&(this._lines=this.body.split(/\r\n|[\n\r]/g)),this._lines}}t.Source=c;class u extends Error{constructor(e){super(e.message),this.originalError=e,Object.setPrototypeOf(this,u.prototype)}}t.ResolveError=u;const p=/\((\d+):(\d+)\)$/;class d extends Error{constructor(e,t){super(e.message.split("\n")[0]),this.originalError=e,this.source=t,Object.setPrototypeOf(this,d.prototype);const[,n,r]=this.message.match(p)||[];this.line=parseInt(n,10),this.col=parseInt(r,10)}}function f(e,t){return e+"::"+t}function h(e,t){return{prev:e,node:t}}t.YamlParseError=d,t.makeRefId=f,t.makeDocumentFromString=function(e,t){const n=new c(t,e);try{return{source:n,parsed:(0,l.parseYaml)(e,{filename:t})}}catch(e){throw new d(e,n)}},t.BaseResolver=class{constructor(e={http:{headers:[]}}){this.config=e,this.cache=new Map}getFiles(){return new Set(Array.from(this.cache.keys()))}resolveExternalRef(e,t){return(0,s.isAbsoluteUrl)(t)?t:e&&(0,s.isAbsoluteUrl)(e)?new URL(t,e).href:o.resolve(e?o.dirname(e):process.cwd(),t)}loadExternalRef(e){return r(this,void 0,void 0,(function*(){try{if((0,s.isAbsoluteUrl)(e)){const{body:t,mimeType:n}=yield(0,l.readFileFromUrl)(e,this.config.http);return new c(e,t,n)}{if(i.lstatSync(e).isDirectory())throw new Error(`Expected a file but received a folder at ${e}`);const t=yield i.promises.readFile(e,"utf-8");return new c(e,t.replace(/\r\n/g,"\n"))}}catch(e){throw e.message=e.message.replace(", lstat",""),new u(e)}}))}parseDocument(e,t=!1){var n;const r=e.absoluteRef.substr(e.absoluteRef.lastIndexOf("."));if(![".json",".json",".yml",".yaml"].includes(r)&&!(null===(n=e.mimeType)||void 0===n?void 0:n.match(/(json|yaml|openapi)/))&&!t)return{source:e,parsed:e.body};try{return{source:e,parsed:(0,l.parseYaml)(e.body,{filename:e.absoluteRef})}}catch(t){throw new d(t,e)}}resolveDocument(e,t,n=!1){return r(this,void 0,void 0,(function*(){const r=this.resolveExternalRef(e,t),i=this.cache.get(r);if(i)return i;const o=this.loadExternalRef(r).then((e=>this.parseDocument(e,n)));return this.cache.set(r,o),o}))}};const m={name:"unknown",properties:{}},g={name:"scalar",properties:{}};t.resolveDocument=function(e){return r(this,void 0,void 0,(function*(){const{rootDocument:t,externalRefResolver:n,rootType:i}=e,o=new Map,c=new Set,u=[];let p;!function e(t,i,p,d){const y=i.source.absoluteRef,b=new Map;function v(e,t,i){return r(this,void 0,void 0,(function*(){if(function(e,t){for(;e;){if(e.node===t)return!0;e=e.prev}return!1}(i.prev,t))throw new Error("Self-referencing circular pointer");if((0,s.isAnchor)(t.$ref)){yield(0,l.nextTick)();const n={resolved:!0,isRemote:!1,node:b.get(t.$ref),document:e,nodePointer:t.$ref},r=f(e.source.absoluteRef,t.$ref);return o.set(r,n),n}const{uri:r,pointer:a}=(0,s.parseRef)(t.$ref),c=null!==r;let u;try{u=c?yield n.resolveDocument(e.source.absoluteRef,r):e}catch(n){const r={resolved:!1,isRemote:c,document:void 0,error:n},i=f(e.source.absoluteRef,t.$ref);return o.set(i,r),r}let p={resolved:!0,document:u,isRemote:c,node:e.parsed,nodePointer:"#/"},d=u.parsed;const m=a;for(const e of m){if("object"!=typeof d){d=void 0;break}if(void 0!==d[e])d=d[e],p.nodePointer=(0,s.joinPointer)(p.nodePointer,(0,s.escapePointer)(e));else{if(!(0,s.isRef)(d)){d=void 0;break}if(p=yield v(u,d,h(i,d)),u=p.document||u,"object"!=typeof p.node){d=void 0;break}d=p.node[e],p.nodePointer=(0,s.joinPointer)(p.nodePointer,(0,s.escapePointer)(e))}}p.node=d,p.document=u;const g=f(e.source.absoluteRef,t.$ref);return p.document&&(0,s.isRef)(d)&&(p=yield v(p.document,d,h(i,d))),o.set(g,p),Object.assign({},p)}))}!function t(n,r,o){if("object"!=typeof n||null===n)return;const l=`${r.name}::${o}`;if(c.has(l))return;c.add(l);const[p,d]=Object.entries(n).find((([e])=>"$anchor"===e))||[];if(d&&b.set(`#${d}`,n),Array.isArray(n)){const e=r.items;if(void 0===e&&r!==m&&r!==a.SpecExtension)return;for(let r=0;r{t.resolved&&e(t.node,t.document,t.nodePointer,r)}));u.push(t)}}}(t,d,y+p)}(t.parsed,t,"#/",i);do{p=yield Promise.all(u)}while(u.length!==p.length);return o}))}},3416:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.reportUnresolvedRef=t.NoUnresolvedRefs=void 0;const r=n(2928);function i(e,t,n){var i;const o=e.error;o instanceof r.YamlParseError&&t({message:"Failed to parse: "+o.message,location:{source:o.source,pointer:void 0,start:{col:o.col,line:o.line}}});const s=null===(i=e.error)||void 0===i?void 0:i.message;t({location:n,message:"Can't resolve $ref"+(s?": "+s:"")})}t.NoUnresolvedRefs=()=>({ref:{leave(e,{report:t,location:n},r){void 0===r.node&&i(r,t,n)}},DiscriminatorMapping(e,{report:t,resolve:n,location:r}){for(const o of Object.keys(e)){const s=n({$ref:e[o]});if(void 0!==s.node)return;i(s,t,r.child(o))}}}),t.reportUnresolvedRef=i},474:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RemoveUnusedComponents=void 0;const r=n(8209);t.RemoveUnusedComponents=()=>{const e=new Map;function t(t,n,r){var i;e.set(t.absolutePointer,{used:(null===(i=e.get(t.absolutePointer))||void 0===i?void 0:i.used)||!1,componentType:n,name:r})}return{ref:{leave(t,{type:n,resolve:r,key:i}){if(["Schema","Parameter","Response","SecurityScheme"].includes(n.name)){const n=r(t);if(!n.location)return;const[o,s]=n.location.absolutePointer.split("#",2),a=`${o}#${s.split("/").slice(0,3).join("/")}`;e.set(a,{used:!0,name:i.toString()})}}},Root:{leave(t,n){const i=n.getVisitorData();i.removedCount=0;const o=new Set;e.forEach((e=>{const{used:n,name:r,componentType:s}=e;!n&&s&&(o.add(s),delete t[s][r],i.removedCount++)}));for(const e of o)(0,r.isEmptyObject)(t[e])&&delete t[e]}},NamedSchemas:{Schema(e,{location:n,key:r}){e.allOf||t(n,"definitions",r.toString())}},NamedParameters:{Parameter(e,{location:n,key:r}){t(n,"parameters",r.toString())}},NamedResponses:{Response(e,{location:n,key:r}){t(n,"responses",r.toString())}},NamedSecuritySchemes:{SecurityScheme(e,{location:n,key:r}){t(n,"securityDefinitions",r.toString())}}}}},4335:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RemoveUnusedComponents=void 0;const r=n(8209);t.RemoveUnusedComponents=()=>{const e=new Map;function t(t,n,r){var i;e.set(t.absolutePointer,{used:(null===(i=e.get(t.absolutePointer))||void 0===i?void 0:i.used)||!1,componentType:n,name:r})}return{ref:{leave(t,{type:n,resolve:r,key:i}){if(["Schema","Header","Parameter","Response","Example","RequestBody"].includes(n.name)){const n=r(t);if(!n.location)return;const[o,s]=n.location.absolutePointer.split("#",2),a=`${o}#${s.split("/").slice(0,4).join("/")}`;e.set(a,{used:!0,name:i.toString()})}}},Root:{leave(t,n){const i=n.getVisitorData();i.removedCount=0,e.forEach((e=>{const{used:n,componentType:o,name:s}=e;if(!n&&o&&t.components){const e=t.components[o];delete e[s],i.removedCount++,(0,r.isEmptyObject)(e)&&delete t.components[o]}})),(0,r.isEmptyObject)(t.components)&&delete t.components}},NamedSchemas:{Schema(e,{location:n,key:r}){e.allOf||t(n,"schemas",r.toString())}},NamedParameters:{Parameter(e,{location:n,key:r}){t(n,"parameters",r.toString())}},NamedResponses:{Response(e,{location:n,key:r}){t(n,"responses",r.toString())}},NamedExamples:{Example(e,{location:n,key:r}){t(n,"examples",r.toString())}},NamedRequestBodies:{RequestBody(e,{location:n,key:r}){t(n,"requestBodies",r.toString())}},NamedHeaders:{Header(e,{location:n,key:r}){t(n,"headers",r.toString())}}}}},264:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.AsyncApi2Types=void 0;const r=n(1990),i=n(3873),o={properties:{},allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt","mqtt5","nats","jms","sns","solace","sqs","stomp","redis","mercure","ibmmq","googlepubsub","pulsar"]},additionalProperties:{type:"object"}},s={properties:{},allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt","mqtt5","nats","jms","sns","solace","sqs","stomp","redis","mercure","ibmmq","googlepubsub","pulsar"]},additionalProperties:{type:"object"}},a={properties:{},allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt","mqtt5","nats","jms","sns","solace","sqs","stomp","redis","mercure","ibmmq","googlepubsub","pulsar"]},additionalProperties:{type:"object"}},l={properties:{},allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt","mqtt5","nats","jms","sns","solace","sqs","stomp","redis","mercure","ibmmq","googlepubsub","pulsar"]},additionalProperties:{type:"object"}},c={properties:{$id:{type:"string"},id:{type:"string"},$schema:{type:"string"},definitions:"NamedSchemas",$defs:"NamedSchemas",$vocabulary:{type:"string"},externalDocs:"ExternalDocs",discriminator:"Discriminator",myArbitraryKeyword:{type:"boolean"},title:{type:"string"},multipleOf:{type:"number",minimum:0},maximum:{type:"number"},minimum:{type:"number"},exclusiveMaximum:{type:"number"},exclusiveMinimum:{type:"number"},maxLength:{type:"integer",minimum:0},minLength:{type:"integer",minimum:0},pattern:{type:"string"},maxItems:{type:"integer",minimum:0},minItems:{type:"integer",minimum:0},uniqueItems:{type:"boolean"},maxProperties:{type:"integer",minimum:0},minProperties:{type:"integer",minimum:0},required:{type:"array",items:{type:"string"}},enum:{type:"array"},type:e=>Array.isArray(e)?{type:"array",items:{enum:["object","array","string","number","integer","boolean","null"]}}:{enum:["object","array","string","number","integer","boolean","null"]},allOf:(0,r.listOf)("Schema"),anyOf:(0,r.listOf)("Schema"),oneOf:(0,r.listOf)("Schema"),not:"Schema",if:"Schema",then:"Schema",else:"Schema",dependentSchemas:(0,r.listOf)("Schema"),prefixItems:(0,r.listOf)("Schema"),contains:"Schema",minContains:{type:"integer",minimum:0},maxContains:{type:"integer",minimum:0},patternProperties:{type:"object"},propertyNames:"Schema",unevaluatedItems:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",unevaluatedProperties:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",summary:{type:"string"},properties:"SchemaProperties",items:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",additionalProperties:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",description:{type:"string"},format:{type:"string"},contentEncoding:{type:"string"},contentMediaType:{type:"string"},default:null,readOnly:{type:"boolean"},writeOnly:{type:"boolean"},examples:{type:"array"},example:{isExample:!0},deprecated:{type:"boolean"},const:null,$comment:{type:"string"},dependencies:{type:"object"}}},u={properties:{},additionalProperties:e=>(0,i.isMappingRef)(e)?{type:"string",directResolveAs:"Schema"}:{type:"string"}},p={properties:{type:{enum:["userPassword","apiKey","X509","symmetricEncryption","asymmetricEncryption","httpApiKey","http","oauth2","openIdConnect","plain","scramSha256","scramSha512","gssapi"]},description:{type:"string"},name:{type:"string"},in:{type:"string",enum:["query","header","cookie","user","password"]},scheme:{type:"string"},bearerFormat:{type:"string"},flows:"SecuritySchemeFlows",openIdConnectUrl:{type:"string"}},required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","in"];case"httpApiKey":return["type","name","in"];case"http":return["type","scheme"];case"oauth2":return["type","flows"];case"openIdConnect":return["type","openIdConnectUrl"];default:return["type"]}},allowed(e){switch(null==e?void 0:e.type){case"apiKey":return["type","in","description"];case"httpApiKey":return["type","name","in","description"];case"http":return["type","scheme","bearerFormat","description"];case"oauth2":return["type","flows","description"];case"openIdConnect":return["type","openIdConnectUrl","description"];default:return["type","description"]}},extensionsPrefix:"x-"},d={properties:{}};o.properties.http=d;const f={properties:{}};s.properties.http=f;const h={properties:{headers:"Schema",bindingVersion:{type:"string"}}};a.properties.http=h;const m={properties:{type:{type:"string"},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS","CONNECT","TRACE"]},headers:"Schema",bindingVersion:{type:"string"}}};l.properties.http=m;const g={properties:{method:{type:"string"},query:"Schema",headers:"Schema",bindingVersion:{type:"string"}}};o.properties.ws=g;const y={properties:{}};s.properties.ws=y;const b={properties:{}};a.properties.ws=b;const v={properties:{}};l.properties.ws=v;const x={properties:{topic:{type:"string"},partitions:{type:"integer"},replicas:{type:"integer"},topicConfiguration:"KafkaTopicConfiguration",bindingVersion:{type:"string"}}};o.properties.kafka=x;const w={properties:{}};s.properties.kafka=w;const k={properties:{key:"Schema",schemaIdLocation:{type:"string"},schemaIdPayloadEncoding:{type:"string"},schemaLookupStrategy:{type:"string"},bindingVersion:{type:"string"}}};a.properties.kafka=k;const S={properties:{groupId:"Schema",clientId:"Schema",bindingVersion:{type:"string"}}};l.properties.kafka=S;const E={properties:{destination:{type:"string"},destinationType:{type:"string"},bindingVersion:{type:"string"}}};o.properties.anypointmq=E;const O={properties:{}};s.properties.anypointmq=O;const _={properties:{headers:"Schema",bindingVersion:{type:"string"}}};a.properties.anypointmq=_;const A={properties:{}};l.properties.anypointmq=A;const C={properties:{}};o.properties.amqp=C;const j={properties:{}};s.properties.amqp=j;const P={properties:{contentEncoding:{type:"string"},messageType:{type:"string"},bindingVersion:{type:"string"}}};a.properties.amqp=P;const T={properties:{expiration:{type:"integer"},userId:{type:"string"},cc:{type:"array",items:{type:"string"}},priority:{type:"integer"},deliveryMode:{type:"integer"},mandatory:{type:"boolean"},bcc:{type:"array",items:{type:"string"}},replyTo:{type:"string"},timestamp:{type:"boolean"},ack:{type:"boolean"},bindingVersion:{type:"string"}}};l.properties.amqp=T;const I={properties:{}};o.properties.amqp1=I;const R={properties:{}};s.properties.amqp1=R;const N={properties:{}};a.properties.amqp1=N;const $={properties:{}};l.properties.amqp1=$;const L={properties:{qos:{type:"integer"},retain:{type:"boolean"},bindingVersion:{type:"string"}}};o.properties.mqtt=L;const D={properties:{clientId:{type:"string"},cleanSession:{type:"boolean"},lastWill:"MqttServerBindingLastWill",keepAlive:{type:"integer"},bindingVersion:{type:"string"}}};s.properties.mqtt=D;const M={properties:{bindingVersion:{type:"string"}}};a.properties.mqtt=M;const F={properties:{qos:{type:"integer"},retain:{type:"boolean"},bindingVersion:{type:"string"}}};l.properties.mqtt=F;const z={properties:{}};o.properties.mqtt5=z;const B={properties:{}};s.properties.mqtt5=B;const U={properties:{}};a.properties.mqtt5=U;const q={properties:{}};l.properties.mqtt5=q;const V={properties:{}};o.properties.nats=V;const W={properties:{}};s.properties.nats=W;const H={properties:{}};a.properties.nats=H;const Y={properties:{queue:{type:"string"},bindingVersion:{type:"string"}}};l.properties.nats=Y;const G={properties:{destination:{type:"string"},destinationType:{type:"string"},bindingVersion:{type:"string"}}};o.properties.jms=G;const Q={properties:{}};s.properties.jms=Q;const X={properties:{headers:"Schema",bindingVersion:{type:"string"}}};a.properties.jms=X;const K={properties:{headers:"Schema",bindingVersion:{type:"string"}}};l.properties.jms=K;const Z={properties:{}};o.properties.solace=Z;const J={properties:{bindingVersion:{type:"string"},msgVpn:{type:"string"}}};s.properties.solace=J;const ee={properties:{}};a.properties.solace=ee;const te={properties:{bindingVersion:{type:"string"},destinations:(0,r.listOf)("SolaceDestination")}};l.properties.solace=te;const ne={properties:{}};o.properties.stomp=ne;const re={properties:{}};s.properties.stomp=re;const ie={properties:{}};a.properties.stomp=ie;const oe={properties:{}};l.properties.stomp=oe;const se={properties:{}};o.properties.redis=se;const ae={properties:{}};s.properties.redis=ae;const le={properties:{}};a.properties.redis=le;const ce={properties:{}};l.properties.redis=ce;const ue={properties:{}};o.properties.mercure=ue;const pe={properties:{}};s.properties.mercure=pe;const de={properties:{}};a.properties.mercure=de;const fe={properties:{}};l.properties.mercure=fe,t.AsyncApi2Types={Root:{properties:{asyncapi:null,info:"Info",id:{type:"string"},servers:"ServerMap",channels:"ChannelMap",components:"Components",tags:"TagList",externalDocs:"ExternalDocs",defaultContentType:{type:"string"}},required:["asyncapi","channels","info"]},Tag:{properties:{name:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs"},required:["name"]},TagList:(0,r.listOf)("Tag"),ServerMap:{properties:{},additionalProperties:(e,t)=>t.match(/^[A-Za-z0-9_\-]+$/)?"Server":void 0},ExternalDocs:{properties:{description:{type:"string"},url:{type:"string"}},required:["url"]},Server:{properties:{url:{type:"string"},protocol:{type:"string"},protocolVersion:{type:"string"},description:{type:"string"},variables:"ServerVariablesMap",security:"SecurityRequirementList",bindings:"ServerBindings",tags:"TagList"},required:["url","protocol"]},ServerVariable:{properties:{enum:{type:"array",items:{type:"string"}},default:{type:"string"},description:{type:"string"},examples:{type:"array",items:{type:"string"}}},required:[]},ServerVariablesMap:(0,r.mapOf)("ServerVariable"),SecurityRequirement:{properties:{},additionalProperties:{type:"array",items:{type:"string"}}},SecurityRequirementList:(0,r.listOf)("SecurityRequirement"),Info:{properties:{title:{type:"string"},version:{type:"string"},description:{type:"string"},termsOfService:{type:"string"},contact:"Contact",license:"License"},required:["title","version"]},Contact:{properties:{name:{type:"string"},url:{type:"string"},email:{type:"string"}}},License:{properties:{name:{type:"string"},url:{type:"string"}},required:["name"]},HttpServerBinding:f,HttpChannelBinding:d,HttpMessageBinding:h,HttpOperationBinding:m,WsServerBinding:y,WsChannelBinding:g,WsMessageBinding:b,WsOperationBinding:v,KafkaServerBinding:w,KafkaTopicConfiguration:{properties:{"cleanup.policy":{type:"array",items:{enum:["delete","compact"]}},"retention.ms":{type:"integer"},"retention.bytes":{type:"integer"},"delete.retention.ms":{type:"integer"},"max.message.bytes":{type:"integer"}}},KafkaChannelBinding:x,KafkaMessageBinding:k,KafkaOperationBinding:S,AnypointmqServerBinding:O,AnypointmqChannelBinding:E,AnypointmqMessageBinding:_,AnypointmqOperationBinding:A,AmqpServerBinding:j,AmqpChannelBinding:C,AmqpMessageBinding:P,AmqpOperationBinding:T,Amqp1ServerBinding:R,Amqp1ChannelBinding:I,Amqp1MessageBinding:N,Amqp1OperationBinding:$,MqttServerBindingLastWill:{properties:{topic:{type:"string"},qos:{type:"integer"},message:{type:"string"},retain:{type:"boolean"}}},MqttServerBinding:D,MqttChannelBinding:L,MqttMessageBinding:M,MqttOperationBinding:F,Mqtt5ServerBinding:B,Mqtt5ChannelBinding:z,Mqtt5MessageBinding:U,Mqtt5OperationBinding:q,NatsServerBinding:W,NatsChannelBinding:V,NatsMessageBinding:H,NatsOperationBinding:Y,JmsServerBinding:Q,JmsChannelBinding:G,JmsMessageBinding:X,JmsOperationBinding:K,SolaceServerBinding:J,SolaceChannelBinding:Z,SolaceMessageBinding:ee,SolaceDestination:{properties:{destinationType:{type:"string",enum:["queue","topic"]},deliveryMode:{type:"string",enum:["direct","persistent"]},"queue.name":{type:"string"},"queue.topicSubscriptions":{type:"array",items:{type:"string"}},"queue.accessType":{type:"string",enum:["exclusive","nonexclusive"]},"queue.maxMsgSpoolSize":{type:"string"},"queue.maxTtl":{type:"string"},"topic.topicSubscriptions":{type:"array",items:{type:"string"}}}},SolaceOperationBinding:te,StompServerBinding:re,StompChannelBinding:ne,StompMessageBinding:ie,StompOperationBinding:oe,RedisServerBinding:ae,RedisChannelBinding:se,RedisMessageBinding:le,RedisOperationBinding:ce,MercureServerBinding:pe,MercureChannelBinding:ue,MercureMessageBinding:de,MercureOperationBinding:fe,ServerBindings:s,ChannelBindings:o,ChannelMap:{properties:{},additionalProperties:"Channel"},Channel:{properties:{description:{type:"string"},subscribe:"Operation",publish:"Operation",parameters:"ParametersMap",bindings:"ChannelBindings",servers:{type:"array",items:{type:"string"}}}},Parameter:{properties:{description:{type:"string"},schema:"Schema",location:{type:"string"}}},ParametersMap:(0,r.mapOf)("Parameter"),Operation:{properties:{tags:{type:"array",items:{type:"string"}},summary:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs",operationId:{type:"string"},security:"SecurityRequirementList",bindings:"OperationBindings",traits:"OperationTraitList",message:"Message"},required:[]},Schema:c,MessageExample:{properties:{payload:{isExample:!0},summary:{type:"string"},name:{type:"string"},headers:{type:"object"}}},SchemaProperties:{properties:{},additionalProperties:e=>"boolean"==typeof e?{type:"boolean"}:"Schema"},DiscriminatorMapping:u,Discriminator:{properties:{propertyName:{type:"string"},mapping:"DiscriminatorMapping"},required:["propertyName"]},Components:{properties:{messages:"NamedMessages",parameters:"NamedParameters",schemas:"NamedSchemas",correlationIds:"NamedCorrelationIds",messageTraits:"NamedMessageTraits",operationTraits:"NamedOperationTraits",streamHeaders:"NamedStreamHeaders",securitySchemes:"NamedSecuritySchemes",servers:"ServerMap",serverVariables:"ServerVariablesMap",channels:"ChannelMap",serverBindings:"ServerBindings",channelBindings:"ChannelBindings",operationBindings:"OperationBindings",messageBindings:"MessageBindings"}},NamedSchemas:(0,r.mapOf)("Schema"),NamedMessages:(0,r.mapOf)("Message"),NamedMessageTraits:(0,r.mapOf)("MessageTrait"),NamedOperationTraits:(0,r.mapOf)("OperationTrait"),NamedParameters:(0,r.mapOf)("Parameter"),NamedSecuritySchemes:(0,r.mapOf)("SecurityScheme"),NamedCorrelationIds:(0,r.mapOf)("CorrelationId"),NamedStreamHeaders:(0,r.mapOf)("StreamHeader"),ImplicitFlow:{properties:{refreshUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},authorizationUrl:{type:"string"}},required:["authorizationUrl","scopes"]},PasswordFlow:{properties:{refreshUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},tokenUrl:{type:"string"}},required:["tokenUrl","scopes"]},ClientCredentials:{properties:{refreshUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},tokenUrl:{type:"string"}},required:["tokenUrl","scopes"]},AuthorizationCode:{properties:{refreshUrl:{type:"string"},authorizationUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},tokenUrl:{type:"string"}},required:["authorizationUrl","tokenUrl","scopes"]},SecuritySchemeFlows:{properties:{implicit:"ImplicitFlow",password:"PasswordFlow",clientCredentials:"ClientCredentials",authorizationCode:"AuthorizationCode"}},SecurityScheme:p,Message:{properties:{messageId:{type:"string"},headers:"Schema",payload:"Schema",correlationId:"CorrelationId",schemaFormat:{type:"string"},contentType:{type:"string"},name:{type:"string"},title:{type:"string"},summary:{type:"string"},description:{type:"string"},tags:"TagList",externalDocs:"ExternalDocs",bindings:"MessageBindings",traits:"MessageTraitList"},additionalProperties:{}},MessageBindings:a,OperationBindings:l,OperationTrait:{properties:{tags:{type:"array",items:{type:"string"}},summary:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs",operationId:{type:"string"},security:"SecurityRequirementList",bindings:"OperationBindings"},required:[]},OperationTraitList:(0,r.listOf)("OperationTrait"),MessageTrait:{properties:{messageId:{type:"string"},headers:"Schema",correlationId:"CorrelationId",schemaFormat:{type:"string"},contentType:{type:"string"},name:{type:"string"},title:{type:"string"},summary:{type:"string"},description:{type:"string"},tags:"TagList",externalDocs:"ExternalDocs",bindings:"MessageBindings"},additionalProperties:{}},MessageTraitList:(0,r.listOf)("MessageTrait"),CorrelationId:{properties:{description:{type:"string"},location:{type:"string"}},required:["location"]}}},1990:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isNamedType=t.normalizeTypes=t.SpecExtension=t.mapOf=t.listOf=void 0,t.listOf=function(e){return{name:`${e}List`,properties:{},items:e}},t.mapOf=function(e){return{name:`${e}Map`,properties:{},additionalProperties:()=>e}},t.SpecExtension={name:"SpecExtension",properties:{},additionalProperties:{resolvable:!0}},t.normalizeTypes=function(e,n={}){const r={};for(const t of Object.keys(e))r[t]=Object.assign(Object.assign({},e[t]),{name:t});for(const e of Object.values(r))i(e);return r.SpecExtension=t.SpecExtension,r;function i(e){if(e.additionalProperties&&(e.additionalProperties=o(e.additionalProperties)),e.items&&(e.items=o(e.items)),e.properties){const t={};for(const[r,i]of Object.entries(e.properties))t[r]=o(i),n.doNotResolveExamples&&i&&i.isExample&&(t[r]=Object.assign(Object.assign({},i),{resolvable:!1}));e.properties=t}}function o(e){if("string"==typeof e){if(!r[e])throw new Error(`Unknown type name found: ${e}`);return r[e]}return"function"==typeof e?(t,n)=>o(e(t,n)):e&&e.name?(i(e=Object.assign({},e)),e):e&&e.directResolveAs?Object.assign(Object.assign({},e),{directResolveAs:o(e.directResolveAs)}):e}},t.isNamedType=function(e){return"string"==typeof(null==e?void 0:e.name)}},4409:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Oas2Types=void 0;const r=n(1990),i=/^[0-9][0-9Xx]{2}$/,o={properties:{name:{type:"string"},in:{type:"string",enum:["query","header","path","formData","body"]},description:{type:"string"},required:{type:"boolean"},schema:"Schema",type:{type:"string",enum:["string","number","integer","boolean","array","file"]},format:{type:"string"},allowEmptyValue:{type:"boolean"},items:"ParameterItems",collectionFormat:{type:"string",enum:["csv","ssv","tsv","pipes","multi"]},default:null,maximum:{type:"integer"},exclusiveMaximum:{type:"boolean"},minimum:{type:"integer"},exclusiveMinimum:{type:"boolean"},maxLength:{type:"integer"},minLength:{type:"integer"},pattern:{type:"string"},maxItems:{type:"integer"},minItems:{type:"integer"},uniqueItems:{type:"boolean"},enum:{type:"array"},multipleOf:{type:"number"},"x-example":"Example","x-examples":"ExamplesMap"},required(e){return e&&e.in?"body"===e.in?["name","in","schema"]:"array"===e.type?["name","in","type","items"]:["name","in","type"]:["name","in"]},extensionsPrefix:"x-"},s={properties:{type:{type:"string",enum:["string","number","integer","boolean","array"]},format:{type:"string"},items:"ParameterItems",collectionFormat:{type:"string",enum:["csv","ssv","tsv","pipes","multi"]},default:null,maximum:{type:"integer"},exclusiveMaximum:{type:"boolean"},minimum:{type:"integer"},exclusiveMinimum:{type:"boolean"},maxLength:{type:"integer"},minLength:{type:"integer"},pattern:{type:"string"},maxItems:{type:"integer"},minItems:{type:"integer"},uniqueItems:{type:"boolean"},enum:{type:"array"},multipleOf:{type:"number"}},required(e){return e&&"array"===e.type?["type","items"]:["type"]},extensionsPrefix:"x-"},a={properties:{default:"Response"},additionalProperties:(e,t)=>i.test(t)?"Response":void 0},l={properties:{description:{type:"string"},schema:"Schema",headers:(0,r.mapOf)("Header"),examples:"Examples","x-summary":{type:"string"}},required:["description"],extensionsPrefix:"x-"},c={properties:{description:{type:"string"},type:{type:"string",enum:["string","number","integer","boolean","array"]},format:{type:"string"},items:"ParameterItems",collectionFormat:{type:"string",enum:["csv","ssv","tsv","pipes","multi"]},default:null,maximum:{type:"integer"},exclusiveMaximum:{type:"boolean"},minimum:{type:"integer"},exclusiveMinimum:{type:"boolean"},maxLength:{type:"integer"},minLength:{type:"integer"},pattern:{type:"string"},maxItems:{type:"integer"},minItems:{type:"integer"},uniqueItems:{type:"boolean"},enum:{type:"array"},multipleOf:{type:"number"}},required(e){return e&&"array"===e.type?["type","items"]:["type"]},extensionsPrefix:"x-"},u={properties:{format:{type:"string"},title:{type:"string"},description:{type:"string"},default:null,multipleOf:{type:"number"},maximum:{type:"number"},minimum:{type:"number"},exclusiveMaximum:{type:"boolean"},exclusiveMinimum:{type:"boolean"},maxLength:{type:"number"},minLength:{type:"number"},pattern:{type:"string"},maxItems:{type:"number"},minItems:{type:"number"},uniqueItems:{type:"boolean"},maxProperties:{type:"number"},minProperties:{type:"number"},required:{type:"array",items:{type:"string"}},enum:{type:"array"},type:{type:"string",enum:["object","array","string","number","integer","boolean","null"]},items:e=>Array.isArray(e)?(0,r.listOf)("Schema"):"Schema",allOf:(0,r.listOf)("Schema"),properties:"SchemaProperties",additionalProperties:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",discriminator:{type:"string"},readOnly:{type:"boolean"},xml:"Xml",externalDocs:"ExternalDocs",example:{isExample:!0},"x-tags":{type:"array",items:{type:"string"}},"x-nullable":{type:"boolean"},"x-extendedDiscriminator":{type:"string"},"x-additionalPropertiesName":{type:"string"},"x-explicitMappingOnly":{type:"boolean"},"x-enumDescriptions":"EnumDescriptions"},extensionsPrefix:"x-"},p={properties:{type:{enum:["basic","apiKey","oauth2"]},description:{type:"string"},name:{type:"string"},in:{type:"string",enum:["query","header"]},flow:{enum:["implicit","password","application","accessCode"]},authorizationUrl:{type:"string"},tokenUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},"x-defaultClientId":{type:"string"}},required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","name","in"];case"oauth2":switch(null==e?void 0:e.flow){case"implicit":return["type","flow","authorizationUrl","scopes"];case"accessCode":return["type","flow","authorizationUrl","tokenUrl","scopes"];case"application":case"password":return["type","flow","tokenUrl","scopes"];default:return["type","flow","scopes"]}default:return["type"]}},allowed(e){switch(null==e?void 0:e.type){case"basic":return["type","description"];case"apiKey":return["type","name","in","description"];case"oauth2":switch(null==e?void 0:e.flow){case"implicit":return["type","flow","authorizationUrl","description","scopes"];case"accessCode":return["type","flow","authorizationUrl","tokenUrl","description","scopes"];case"application":case"password":return["type","flow","tokenUrl","description","scopes"];default:return["type","flow","tokenUrl","authorizationUrl","description","scopes"]}default:return["type","description"]}},extensionsPrefix:"x-"};t.Oas2Types={Root:{properties:{swagger:{type:"string"},info:"Info",host:{type:"string"},basePath:{type:"string"},schemes:{type:"array",items:{type:"string"}},consumes:{type:"array",items:{type:"string"}},produces:{type:"array",items:{type:"string"}},paths:"Paths",definitions:"NamedSchemas",parameters:"NamedParameters",responses:"NamedResponses",securityDefinitions:"NamedSecuritySchemes",security:"SecurityRequirementList",tags:"TagList",externalDocs:"ExternalDocs","x-servers":"XServerList","x-tagGroups":"TagGroups","x-ignoredHeaderParameters":{type:"array",items:{type:"string"}}},required:["swagger","paths","info"],extensionsPrefix:"x-"},Tag:{properties:{name:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs","x-traitTag":{type:"boolean"},"x-displayName":{type:"string"}},required:["name"],extensionsPrefix:"x-"},TagList:(0,r.listOf)("Tag"),TagGroups:(0,r.listOf)("TagGroup"),TagGroup:{properties:{name:{type:"string"},tags:{type:"array",items:{type:"string"}}}},ExternalDocs:{properties:{description:{type:"string"},url:{type:"string"}},required:["url"],extensionsPrefix:"x-"},Example:{properties:{value:{isExample:!0},summary:{type:"string"},description:{type:"string"},externalValue:{type:"string"}},extensionsPrefix:"x-"},ExamplesMap:(0,r.mapOf)("Example"),EnumDescriptions:{properties:{},additionalProperties:{type:"string"}},SecurityRequirement:{properties:{},additionalProperties:{type:"array",items:{type:"string"}}},SecurityRequirementList:(0,r.listOf)("SecurityRequirement"),Info:{properties:{title:{type:"string"},description:{type:"string"},termsOfService:{type:"string"},contact:"Contact",license:"License",version:{type:"string"},"x-logo":"Logo"},required:["title","version"],extensionsPrefix:"x-"},Contact:{properties:{name:{type:"string"},url:{type:"string"},email:{type:"string"}},extensionsPrefix:"x-"},License:{properties:{name:{type:"string"},url:{type:"string"}},required:["name"],extensionsPrefix:"x-"},Logo:{properties:{url:{type:"string"},altText:{type:"string"},backgroundColor:{type:"string"},href:{type:"string"}},extensionsPrefix:"x-"},Paths:{properties:{},additionalProperties:(e,t)=>t.startsWith("/")?"PathItem":void 0},PathItem:{properties:{$ref:{type:"string"},parameters:"ParameterList",get:"Operation",put:"Operation",post:"Operation",delete:"Operation",options:"Operation",head:"Operation",patch:"Operation"},extensionsPrefix:"x-"},Parameter:o,ParameterItems:s,ParameterList:(0,r.listOf)("Parameter"),Operation:{properties:{tags:{type:"array",items:{type:"string"}},summary:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs",operationId:{type:"string"},consumes:{type:"array",items:{type:"string"}},produces:{type:"array",items:{type:"string"}},parameters:"ParameterList",responses:"Responses",schemes:{type:"array",items:{type:"string"}},deprecated:{type:"boolean"},security:"SecurityRequirementList","x-codeSamples":"XCodeSampleList","x-code-samples":"XCodeSampleList","x-hideTryItPanel":{type:"boolean"}},required:["responses"],extensionsPrefix:"x-"},Examples:{properties:{},additionalProperties:{isExample:!0}},Header:c,Responses:a,Response:l,Schema:u,Xml:{properties:{name:{type:"string"},namespace:{type:"string"},prefix:{type:"string"},attribute:{type:"boolean"},wrapped:{type:"boolean"}},extensionsPrefix:"x-"},SchemaProperties:{properties:{},additionalProperties:"Schema"},NamedSchemas:(0,r.mapOf)("Schema"),NamedResponses:(0,r.mapOf)("Response"),NamedParameters:(0,r.mapOf)("Parameter"),NamedSecuritySchemes:(0,r.mapOf)("SecurityScheme"),SecurityScheme:p,XCodeSample:{properties:{lang:{type:"string"},label:{type:"string"},source:{type:"string"}}},XCodeSampleList:(0,r.listOf)("XCodeSample"),XServerList:(0,r.listOf)("XServer"),XServer:{properties:{url:{type:"string"},description:{type:"string"}},required:["url"]}}},4154:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Oas3Types=void 0;const r=n(1990),i=n(3873),o=/^[0-9][0-9Xx]{2}$/,s={properties:{default:"Response"},additionalProperties:(e,t)=>o.test(t)?"Response":void 0},a={properties:{externalDocs:"ExternalDocs",discriminator:"Discriminator",title:{type:"string"},multipleOf:{type:"number",minimum:0},maximum:{type:"number"},minimum:{type:"number"},exclusiveMaximum:{type:"boolean"},exclusiveMinimum:{type:"boolean"},maxLength:{type:"integer",minimum:0},minLength:{type:"integer",minimum:0},pattern:{type:"string"},maxItems:{type:"integer",minimum:0},minItems:{type:"integer",minimum:0},uniqueItems:{type:"boolean"},maxProperties:{type:"integer",minimum:0},minProperties:{type:"integer",minimum:0},required:{type:"array",items:{type:"string"}},enum:{type:"array"},type:{enum:["object","array","string","number","integer","boolean","null"]},allOf:(0,r.listOf)("Schema"),anyOf:(0,r.listOf)("Schema"),oneOf:(0,r.listOf)("Schema"),not:"Schema",properties:"SchemaProperties",items:e=>Array.isArray(e)?(0,r.listOf)("Schema"):"Schema",additionalItems:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",additionalProperties:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",description:{type:"string"},format:{type:"string"},default:null,nullable:{type:"boolean"},readOnly:{type:"boolean"},writeOnly:{type:"boolean"},xml:"Xml",example:{isExample:!0},deprecated:{type:"boolean"},"x-tags":{type:"array",items:{type:"string"}},"x-additionalPropertiesName":{type:"string"},"x-explicitMappingOnly":{type:"boolean"}},extensionsPrefix:"x-"},l={properties:{},additionalProperties:e=>(0,i.isMappingRef)(e)?{type:"string",directResolveAs:"Schema"}:{type:"string"}},c={properties:{type:{enum:["apiKey","http","oauth2","openIdConnect"]},description:{type:"string"},name:{type:"string"},in:{type:"string",enum:["query","header","cookie"]},scheme:{type:"string"},bearerFormat:{type:"string"},flows:"OAuth2Flows",openIdConnectUrl:{type:"string"},"x-defaultClientId":{type:"string"}},required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","name","in"];case"http":return["type","scheme"];case"oauth2":return["type","flows"];case"openIdConnect":return["type","openIdConnectUrl"];default:return["type"]}},allowed(e){switch(null==e?void 0:e.type){case"apiKey":return["type","name","in","description"];case"http":return["type","scheme","bearerFormat","description"];case"oauth2":return["type","flows","description"];case"openIdConnect":return["type","openIdConnectUrl","description"];default:return["type","description"]}},extensionsPrefix:"x-"};t.Oas3Types={Root:{properties:{openapi:null,info:"Info",servers:"ServerList",security:"SecurityRequirementList",tags:"TagList",externalDocs:"ExternalDocs",paths:"Paths",components:"Components","x-webhooks":"WebhooksMap","x-tagGroups":"TagGroups","x-ignoredHeaderParameters":{type:"array",items:{type:"string"}}},required:["openapi","paths","info"],extensionsPrefix:"x-"},Tag:{properties:{name:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs","x-traitTag":{type:"boolean"},"x-displayName":{type:"string"}},required:["name"],extensionsPrefix:"x-"},TagList:(0,r.listOf)("Tag"),TagGroups:(0,r.listOf)("TagGroup"),TagGroup:{properties:{name:{type:"string"},tags:{type:"array",items:{type:"string"}}},extensionsPrefix:"x-"},ExternalDocs:{properties:{description:{type:"string"},url:{type:"string"}},required:["url"],extensionsPrefix:"x-"},Server:{properties:{url:{type:"string"},description:{type:"string"},variables:"ServerVariablesMap"},required:["url"],extensionsPrefix:"x-"},ServerList:(0,r.listOf)("Server"),ServerVariable:{properties:{enum:{type:"array",items:{type:"string"}},default:{type:"string"},description:{type:"string"}},required:["default"],extensionsPrefix:"x-"},ServerVariablesMap:(0,r.mapOf)("ServerVariable"),SecurityRequirement:{properties:{},additionalProperties:{type:"array",items:{type:"string"}}},SecurityRequirementList:(0,r.listOf)("SecurityRequirement"),Info:{properties:{title:{type:"string"},version:{type:"string"},description:{type:"string"},termsOfService:{type:"string"},contact:"Contact",license:"License","x-logo":"Logo"},required:["title","version"],extensionsPrefix:"x-"},Contact:{properties:{name:{type:"string"},url:{type:"string"},email:{type:"string"}},extensionsPrefix:"x-"},License:{properties:{name:{type:"string"},url:{type:"string"}},required:["name"],extensionsPrefix:"x-"},Paths:{properties:{},additionalProperties:(e,t)=>t.startsWith("/")?"PathItem":void 0},PathItem:{properties:{$ref:{type:"string"},servers:"ServerList",parameters:"ParameterList",summary:{type:"string"},description:{type:"string"},get:"Operation",put:"Operation",post:"Operation",delete:"Operation",options:"Operation",head:"Operation",patch:"Operation",trace:"Operation"},extensionsPrefix:"x-"},Parameter:{properties:{name:{type:"string"},in:{enum:["query","header","path","cookie"]},description:{type:"string"},required:{type:"boolean"},deprecated:{type:"boolean"},allowEmptyValue:{type:"boolean"},style:{enum:["form","simple","label","matrix","spaceDelimited","pipeDelimited","deepObject"]},explode:{type:"boolean"},allowReserved:{type:"boolean"},schema:"Schema",example:{isExample:!0},examples:"ExamplesMap",content:"MediaTypesMap"},required:["name","in"],requiredOneOf:["schema","content"],extensionsPrefix:"x-"},ParameterList:(0,r.listOf)("Parameter"),Operation:{properties:{tags:{type:"array",items:{type:"string"}},summary:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs",operationId:{type:"string"},parameters:"ParameterList",security:"SecurityRequirementList",servers:"ServerList",requestBody:"RequestBody",responses:"Responses",deprecated:{type:"boolean"},callbacks:"CallbacksMap","x-codeSamples":"XCodeSampleList","x-code-samples":"XCodeSampleList","x-hideTryItPanel":{type:"boolean"}},required:["responses"],extensionsPrefix:"x-"},Callback:(0,r.mapOf)("PathItem"),CallbacksMap:(0,r.mapOf)("Callback"),RequestBody:{properties:{description:{type:"string"},required:{type:"boolean"},content:"MediaTypesMap"},required:["content"],extensionsPrefix:"x-"},MediaTypesMap:{properties:{},additionalProperties:"MediaType"},MediaType:{properties:{schema:"Schema",example:{isExample:!0},examples:"ExamplesMap",encoding:"EncodingMap"},extensionsPrefix:"x-"},Example:{properties:{value:{isExample:!0},summary:{type:"string"},description:{type:"string"},externalValue:{type:"string"}},extensionsPrefix:"x-"},ExamplesMap:(0,r.mapOf)("Example"),Encoding:{properties:{contentType:{type:"string"},headers:"HeadersMap",style:{enum:["form","simple","label","matrix","spaceDelimited","pipeDelimited","deepObject"]},explode:{type:"boolean"},allowReserved:{type:"boolean"}},extensionsPrefix:"x-"},EncodingMap:(0,r.mapOf)("Encoding"),EnumDescriptions:{properties:{},additionalProperties:{type:"string"}},Header:{properties:{description:{type:"string"},required:{type:"boolean"},deprecated:{type:"boolean"},allowEmptyValue:{type:"boolean"},style:{enum:["form","simple","label","matrix","spaceDelimited","pipeDelimited","deepObject"]},explode:{type:"boolean"},allowReserved:{type:"boolean"},schema:"Schema",example:{isExample:!0},examples:"ExamplesMap",content:"MediaTypesMap"},requiredOneOf:["schema","content"],extensionsPrefix:"x-"},HeadersMap:(0,r.mapOf)("Header"),Responses:s,Response:{properties:{description:{type:"string"},headers:"HeadersMap",content:"MediaTypesMap",links:"LinksMap","x-summary":{type:"string"}},required:["description"],extensionsPrefix:"x-"},Link:{properties:{operationRef:{type:"string"},operationId:{type:"string"},parameters:null,requestBody:null,description:{type:"string"},server:"Server"},extensionsPrefix:"x-"},Logo:{properties:{url:{type:"string"},altText:{type:"string"},backgroundColor:{type:"string"},href:{type:"string"}}},Schema:a,Xml:{properties:{name:{type:"string"},namespace:{type:"string"},prefix:{type:"string"},attribute:{type:"boolean"},wrapped:{type:"boolean"}},extensionsPrefix:"x-"},SchemaProperties:{properties:{},additionalProperties:"Schema"},DiscriminatorMapping:l,Discriminator:{properties:{propertyName:{type:"string"},mapping:"DiscriminatorMapping"},required:["propertyName"],extensionsPrefix:"x-"},Components:{properties:{parameters:"NamedParameters",schemas:"NamedSchemas",responses:"NamedResponses",examples:"NamedExamples",requestBodies:"NamedRequestBodies",headers:"NamedHeaders",securitySchemes:"NamedSecuritySchemes",links:"NamedLinks",callbacks:"NamedCallbacks"},extensionsPrefix:"x-"},LinksMap:(0,r.mapOf)("Link"),NamedSchemas:(0,r.mapOf)("Schema"),NamedResponses:(0,r.mapOf)("Response"),NamedParameters:(0,r.mapOf)("Parameter"),NamedExamples:(0,r.mapOf)("Example"),NamedRequestBodies:(0,r.mapOf)("RequestBody"),NamedHeaders:(0,r.mapOf)("Header"),NamedSecuritySchemes:(0,r.mapOf)("SecurityScheme"),NamedLinks:(0,r.mapOf)("Link"),NamedCallbacks:(0,r.mapOf)("Callback"),ImplicitFlow:{properties:{refreshUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},authorizationUrl:{type:"string"}},required:["authorizationUrl","scopes"],extensionsPrefix:"x-"},PasswordFlow:{properties:{refreshUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},tokenUrl:{type:"string"}},required:["tokenUrl","scopes"],extensionsPrefix:"x-"},ClientCredentials:{properties:{refreshUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},tokenUrl:{type:"string"}},required:["tokenUrl","scopes"],extensionsPrefix:"x-"},AuthorizationCode:{properties:{refreshUrl:{type:"string"},authorizationUrl:{type:"string"},scopes:{type:"object",additionalProperties:{type:"string"}},tokenUrl:{type:"string"},"x-usePkce":e=>"boolean"==typeof e?{type:"boolean"}:"XUsePkce"},required:["authorizationUrl","tokenUrl","scopes"],extensionsPrefix:"x-"},OAuth2Flows:{properties:{implicit:"ImplicitFlow",password:"PasswordFlow",clientCredentials:"ClientCredentials",authorizationCode:"AuthorizationCode"},extensionsPrefix:"x-"},SecurityScheme:c,XCodeSample:{properties:{lang:{type:"string"},label:{type:"string"},source:{type:"string"}}},XCodeSampleList:(0,r.listOf)("XCodeSample"),XUsePkce:{properties:{disableManualConfiguration:{type:"boolean"},hideClientSecretInput:{type:"boolean"}}},WebhooksMap:{properties:{},additionalProperties:()=>"PathItem"}}},2082:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Oas3_1Types=void 0;const r=n(1990),i=n(4154),o={properties:{$id:{type:"string"},$anchor:{type:"string"},id:{type:"string"},$schema:{type:"string"},definitions:"NamedSchemas",$defs:"NamedSchemas",$vocabulary:{type:"string"},externalDocs:"ExternalDocs",discriminator:"Discriminator",title:{type:"string"},multipleOf:{type:"number",minimum:0},maximum:{type:"number"},minimum:{type:"number"},exclusiveMaximum:{type:"number"},exclusiveMinimum:{type:"number"},maxLength:{type:"integer",minimum:0},minLength:{type:"integer",minimum:0},pattern:{type:"string"},maxItems:{type:"integer",minimum:0},minItems:{type:"integer",minimum:0},uniqueItems:{type:"boolean"},maxProperties:{type:"integer",minimum:0},minProperties:{type:"integer",minimum:0},required:{type:"array",items:{type:"string"}},enum:{type:"array"},type:e=>Array.isArray(e)?{type:"array",items:{enum:["object","array","string","number","integer","boolean","null"]}}:{enum:["object","array","string","number","integer","boolean","null"]},allOf:(0,r.listOf)("Schema"),anyOf:(0,r.listOf)("Schema"),oneOf:(0,r.listOf)("Schema"),not:"Schema",if:"Schema",then:"Schema",else:"Schema",dependentSchemas:(0,r.listOf)("Schema"),prefixItems:(0,r.listOf)("Schema"),contains:"Schema",minContains:{type:"integer",minimum:0},maxContains:{type:"integer",minimum:0},patternProperties:{type:"object"},propertyNames:"Schema",unevaluatedItems:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",unevaluatedProperties:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",summary:{type:"string"},properties:"SchemaProperties",items:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",additionalProperties:e=>"boolean"==typeof e?{type:"boolean"}:"Schema",description:{type:"string"},format:{type:"string"},contentEncoding:{type:"string"},contentMediaType:{type:"string"},default:null,readOnly:{type:"boolean"},writeOnly:{type:"boolean"},xml:"Xml",examples:{type:"array"},example:{isExample:!0},deprecated:{type:"boolean"},const:null,$comment:{type:"string"},"x-tags":{type:"array",items:{type:"string"}}},extensionsPrefix:"x-"},s={properties:{type:{enum:["apiKey","http","oauth2","openIdConnect","mutualTLS"]},description:{type:"string"},name:{type:"string"},in:{type:"string",enum:["query","header","cookie"]},scheme:{type:"string"},bearerFormat:{type:"string"},flows:"OAuth2Flows",openIdConnectUrl:{type:"string"}},required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","name","in"];case"http":return["type","scheme"];case"oauth2":return["type","flows"];case"openIdConnect":return["type","openIdConnectUrl"];default:return["type"]}},allowed(e){switch(null==e?void 0:e.type){case"apiKey":return["type","name","in","description"];case"http":return["type","scheme","bearerFormat","description"];case"oauth2":switch(null==e?void 0:e.flows){case"implicit":return["type","flows","authorizationUrl","refreshUrl","description","scopes"];case"password":case"clientCredentials":return["type","flows","tokenUrl","refreshUrl","description","scopes"];default:return["type","flows","authorizationUrl","refreshUrl","tokenUrl","description","scopes"]}case"openIdConnect":return["type","openIdConnectUrl","description"];default:return["type","description"]}},extensionsPrefix:"x-"};t.Oas3_1Types=Object.assign(Object.assign({},i.Oas3Types),{Info:{properties:{title:{type:"string"},version:{type:"string"},description:{type:"string"},termsOfService:{type:"string"},summary:{type:"string"},contact:"Contact",license:"License","x-logo":"Logo"},required:["title","version"],extensionsPrefix:"x-"},Root:{properties:{openapi:null,info:"Info",servers:"ServerList",security:"SecurityRequirementList",tags:"TagList",externalDocs:"ExternalDocs",paths:"Paths",webhooks:"WebhooksMap",components:"Components",jsonSchemaDialect:{type:"string"}},required:["openapi","info"],requiredOneOf:["paths","components","webhooks"],extensionsPrefix:"x-"},Schema:o,License:{properties:{name:{type:"string"},url:{type:"string"},identifier:{type:"string"}},required:["name"],extensionsPrefix:"x-"},Components:{properties:{parameters:"NamedParameters",schemas:"NamedSchemas",responses:"NamedResponses",examples:"NamedExamples",requestBodies:"NamedRequestBodies",headers:"NamedHeaders",securitySchemes:"NamedSecuritySchemes",links:"NamedLinks",callbacks:"NamedCallbacks",pathItems:"NamedPathItems"},extensionsPrefix:"x-"},NamedPathItems:(0,r.mapOf)("PathItem"),SecurityScheme:s,Operation:{properties:{tags:{type:"array",items:{type:"string"}},summary:{type:"string"},description:{type:"string"},externalDocs:"ExternalDocs",operationId:{type:"string"},parameters:"ParameterList",security:"SecurityRequirementList",servers:"ServerList",requestBody:"RequestBody",responses:"Responses",deprecated:{type:"boolean"},callbacks:"CallbacksMap","x-codeSamples":"XCodeSampleList","x-code-samples":"XCodeSampleList","x-hideTryItPanel":{type:"boolean"}},extensionsPrefix:"x-"}})},8209:function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{l(r.next(e))}catch(e){o(e)}}function a(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}l((r=r.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:!0}),t.nextTick=t.pickDefined=t.keysOf=t.identity=t.isTruthy=t.showErrorForDeprecatedField=t.showWarningForDeprecatedField=t.doesYamlFileExist=t.isCustomRuleId=t.getMatchingStatusCodeRange=t.assignExisting=t.isNotString=t.isString=t.isNotEmptyObject=t.slash=t.isPathParameter=t.yamlAndJsonSyncReader=t.readFileAsStringSync=t.isSingular=t.validateMimeTypeOAS3=t.validateMimeType=t.splitCamelCaseIntoWords=t.omitObjectProps=t.pickObjectProps=t.readFileFromUrl=t.isEmptyArray=t.isEmptyObject=t.isPlainObject=t.isDefined=t.loadYaml=t.popStack=t.pushStack=t.stringifyYaml=t.parseYaml=void 0;const i=n(7411),o=n(7975),s=n(4536),a=n(8381),l=n(5127),c=n(970),u=n(1827),p=n(2678);var d=n(970);function f(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function h(e,t){return t.match(/^https?:\/\//)||(e=e.replace(/^https?:\/\//,"")),s(e,t)}function m(e){return"string"==typeof e}function g(e){return!!e}function y(e,t){return`${void 0!==t?`${t}.`:""}${e}`}Object.defineProperty(t,"parseYaml",{enumerable:!0,get:function(){return d.parseYaml}}),Object.defineProperty(t,"stringifyYaml",{enumerable:!0,get:function(){return d.stringifyYaml}}),t.pushStack=function(e,t){return{prev:e,value:t}},t.popStack=function(e){var t;return null!==(t=null==e?void 0:e.prev)&&void 0!==t?t:null},t.loadYaml=function(e){return r(this,void 0,void 0,(function*(){const t=yield i.promises.readFile(e,"utf-8");return(0,c.parseYaml)(t)}))},t.isDefined=function(e){return void 0!==e},t.isPlainObject=f,t.isEmptyObject=function(e){return f(e)&&0===Object.keys(e).length},t.isEmptyArray=function(e){return Array.isArray(e)&&0===e.length},t.readFileFromUrl=function(e,t){return r(this,void 0,void 0,(function*(){const n={};for(const r of t.headers)h(e,r.matches)&&(n[r.name]=void 0!==r.envVariable?u.env[r.envVariable]||"":r.value);const r=yield(t.customFetch||a.default)(e,{headers:n});if(!r.ok)throw new Error(`Failed to load ${e}: ${r.status} ${r.statusText}`);return{body:yield r.text(),mimeType:r.headers.get("content-type")}}))},t.pickObjectProps=function(e,t){return Object.fromEntries(t.filter((t=>t in e)).map((t=>[t,e[t]])))},t.omitObjectProps=function(e,t){return Object.fromEntries(Object.entries(e).filter((([e])=>!t.includes(e))))},t.splitCamelCaseIntoWords=function(e){const t=e.split(/(?:[-._])|([A-Z][a-z]+)/).filter(g).map((e=>e.toLocaleLowerCase())),n=e.split(/([A-Z]{2,})/).filter((e=>e&&e===e.toUpperCase())).map((e=>e.toLocaleLowerCase()));return new Set([...t,...n])},t.validateMimeType=function({type:e,value:t},{report:n,location:r},i){if(!i)throw new Error(`Parameter "allowedValues" is not provided for "${"consumes"===e?"request":"response"}-mime-type" rule`);if(t[e])for(const o of t[e])i.includes(o)||n({message:`Mime type "${o}" is not allowed`,location:r.child(t[e].indexOf(o)).key()})},t.validateMimeTypeOAS3=function({type:e,value:t},{report:n,location:r},i){if(!i)throw new Error(`Parameter "allowedValues" is not provided for "${"consumes"===e?"request":"response"}-mime-type" rule`);if(t.content)for(const e of Object.keys(t.content))i.includes(e)||n({message:`Mime type "${e}" is not allowed`,location:r.child("content").child(e).key()})},t.isSingular=function(e){return l.isSingular(e)},t.readFileAsStringSync=function(e){return i.readFileSync(e,"utf-8")},t.yamlAndJsonSyncReader=function(e){const t=i.readFileSync(e,"utf-8");return(0,c.parseYaml)(t)},t.isPathParameter=function(e){return e.startsWith("{")&&e.endsWith("}")},t.slash=function(e){return/^\\\\\?\\/.test(e)?e:e.replace(/\\/g,"/")},t.isNotEmptyObject=function(e){return!!e&&Object.keys(e).length>0},t.isString=m,t.isNotString=function(e){return!m(e)},t.assignExisting=function(e,t){for(const n of Object.keys(t))e.hasOwnProperty(n)&&(e[n]=t[n])},t.getMatchingStatusCodeRange=function(e){return`${e}`.replace(/^(\d)\d\d$/,((e,t)=>`${t}XX`))},t.isCustomRuleId=function(e){return e.includes("/")},t.doesYamlFileExist=function(e){return(".yaml"===(0,o.extname)(e)||".yml"===(0,o.extname)(e))&&i.hasOwnProperty("existsSync")&&i.existsSync(e)},t.showWarningForDeprecatedField=function(e,t,n){p.logger.warn(`The '${p.colorize.red(e)}' field is deprecated. ${t?`Use ${p.colorize.green(y(t,n))} instead. `:""}Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`)},t.showErrorForDeprecatedField=function(e,t,n){throw new Error(`Do not use '${e}' field. ${t?`Use '${y(t,n)}' instead. `:""}\n`)},t.isTruthy=g,t.identity=function(e){return e},t.keysOf=function(e){return e?Object.keys(e):[]},t.pickDefined=function(e){if(!e)return;const t={};for(const n in e)void 0!==e[n]&&(t[n]=e[n]);return t},t.nextTick=function(){new Promise((e=>{setTimeout(e)}))}},2161:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.normalizeVisitors=void 0;const r=n(1990),i={Root:"DefinitionRoot",ServerVariablesMap:"ServerVariableMap",Paths:["PathMap","PathsMap"],CallbacksMap:"CallbackMap",MediaTypesMap:"MediaTypeMap",ExamplesMap:"ExampleMap",EncodingMap:"EncodingsMap",HeadersMap:"HeaderMap",LinksMap:"LinkMap",OAuth2Flows:"SecuritySchemeFlows",Responses:"ResponsesMap"};t.normalizeVisitors=function(e,t){const n={any:{enter:[],leave:[]}};for(const e of Object.keys(t))n[e]={enter:[],leave:[]};n.ref={enter:[],leave:[]};for(const{ruleId:t,severity:n,visitor:r}of e)a({ruleId:t,severity:n},r,null);for(const e of Object.keys(n))n[e].enter.sort(((e,t)=>t.depth-e.depth)),n[e].leave.sort(((e,t)=>e.depth-t.depth));return n;function o(e,t,i,s,a=[]){if(a.includes(t))return;a=[...a,t];const l=new Set;for(const n of Object.values(t.properties))n!==i?"object"==typeof n&&null!==n&&n.name&&l.add(n):c(e,a);t.additionalProperties&&"function"!=typeof t.additionalProperties&&(t.additionalProperties===i?c(e,a):void 0!==t.additionalProperties.name&&l.add(t.additionalProperties)),t.items&&(t.items===i?c(e,a):void 0!==t.items.name&&l.add(t.items)),t.extensionsPrefix&&l.add(r.SpecExtension);for(const t of Array.from(l.values()))o(e,t,i,s,a);function c(e,t){for(const r of t.slice(1))n[r.name]=n[r.name]||{enter:[],leave:[]},n[r.name].enter.push(Object.assign(Object.assign({},e),{visit:()=>{},depth:0,context:{isSkippedLevel:!0,seen:new Set,parent:s}}))}}function s(e,t){if(Array.isArray(t)){const n=t.find((t=>e[t]))||void 0;return n&&e[n]}return e[t]}function a(e,r,l,c=0){const u=Object.keys(t);if(0===c)u.push("any"),u.push("ref");else{if(r.any)throw new Error("any() is allowed only on top level");if(r.ref)throw new Error("ref() is allowed only on top level")}for(const p of u){const u=r[p]||s(r,i[p]),d=n[p];if(!u)continue;let f,h,m;const g="object"==typeof u;if("ref"===p&&g&&u.skip)throw new Error("ref() visitor does not support skip");"function"==typeof u?f=u:g&&(f=u.enter,h=u.leave,m=u.skip);const y={activatedOn:null,type:t[p],parent:l,isSkippedLevel:!1};if("object"==typeof u&&a(e,u,y,c+1),l&&o(e,l.type,t[p],l),f||g){if(f&&"function"!=typeof f)throw new Error("DEV: should be function");d.enter.push(Object.assign(Object.assign({},e),{visit:f||(()=>{}),skip:m,depth:c,context:y}))}if(h){if("function"!=typeof h)throw new Error("DEV: should be function");d.leave.push(Object.assign(Object.assign({},e),{visit:h,depth:c,context:y}))}}}}},5735:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.walkDocument=void 0;const r=n(3873),i=n(8209),o=n(2928),s=n(1990);function a(e){var t,n;const r={};for(;e.parent;)(null===(t=e.parent.activatedOn)||void 0===t?void 0:t.value.location)&&(r[e.parent.type.name]=null===(n=e.parent.activatedOn)||void 0===n?void 0:n.value.location),e=e.parent;return r}t.walkDocument=function(e){const{document:t,rootType:n,normalizedVisitors:l,resolvedRefMap:c,ctx:u}=e,p={},d=new Set;!function e(t,n,f,h,m){var g,y,b,v,x,w,k,S,E,O,_;const A=(e,t=j.source.absoluteRef)=>{if(!(0,r.isRef)(e))return{location:f,node:e};const n=(0,o.makeRefId)(t,e.$ref),i=c.get(n);if(!i)return{location:void 0,node:void 0};const{resolved:s,node:a,document:l,nodePointer:u,error:p}=i;return{location:s?new r.Location(l.source,u):p instanceof o.YamlParseError?new r.Location(p.source,""):void 0,node:a,error:p}},C=f;let j=f;const{node:P,location:T,error:I}=A(t),R=new Set;if((0,r.isRef)(t)){const e=l.ref.enter;for(const{visit:r,ruleId:i,severity:o,context:s}of e)R.add(s),r(t,{report:$.bind(void 0,i,o),resolve:A,rawNode:t,rawLocation:C,location:f,type:n,parent:h,key:m,parentLocations:{},oasVersion:u.oasVersion,getVisitorData:L.bind(void 0,i)},{node:P,location:T,error:I}),(null==T?void 0:T.source.absoluteRef)&&u.refTypes&&u.refTypes.set(null==T?void 0:T.source.absoluteRef,n)}if(void 0!==P&&T&&"scalar"!==n.name){j=T;const o=null===(y=null===(g=p[n.name])||void 0===g?void 0:g.has)||void 0===y?void 0:y.call(g,P);let a=!1;const c=l.any.enter.concat((null===(b=l[n.name])||void 0===b?void 0:b.enter)||[]),u=[];for(const{context:e,visit:r,skip:s,ruleId:l,severity:p}of c){if(d.has(j.pointer))break;if(e.isSkippedLevel)!e.parent.activatedOn||e.parent.activatedOn.value.nextLevelTypeActivated||e.seen.has(t)||(e.seen.add(t),a=!0,u.push(e));else if(e.parent&&e.parent.activatedOn&&(null===(v=e.activatedOn)||void 0===v?void 0:v.value.withParentNode)!==e.parent.activatedOn.value.node&&(null===(x=e.parent.activatedOn.value.nextLevelTypeActivated)||void 0===x?void 0:x.value)!==n||!e.parent&&!o){u.push(e);const o={node:P,location:T,nextLevelTypeActivated:null,withParentNode:null===(k=null===(w=e.parent)||void 0===w?void 0:w.activatedOn)||void 0===k?void 0:k.value.node,skipped:null!==(O=(null===(E=null===(S=e.parent)||void 0===S?void 0:S.activatedOn)||void 0===E?void 0:E.value.skipped)||(null==s?void 0:s(P,m,{location:f,rawLocation:C,resolve:A,rawNode:t})))&&void 0!==O&&O};e.activatedOn=(0,i.pushStack)(e.activatedOn,o);let c=e.parent;for(;c;)c.activatedOn.value.nextLevelTypeActivated=(0,i.pushStack)(c.activatedOn.value.nextLevelTypeActivated,n),c=c.parent;o.skipped||(a=!0,R.add(e),N(r,P,t,e,l,p))}}if(a||!o)if(p[n.name]=p[n.name]||new Set,p[n.name].add(P),Array.isArray(P)){const t=n.items;if(void 0!==t)for(let n=0;n!i.includes(e)))):n.extensionsPrefix&&i.push(...Object.keys(P).filter((e=>e.startsWith(n.extensionsPrefix)))),(0,r.isRef)(t)&&i.push(...Object.keys(t).filter((e=>"$ref"!==e&&!i.includes(e))));for(const o of i){let i=P[o],a=T;void 0===i&&(i=t[o],a=f);let l=n.properties[o];void 0===l&&(l=n.additionalProperties),"function"==typeof l&&(l=l(i,o)),void 0===l&&n.extensionsPrefix&&o.startsWith(n.extensionsPrefix)&&(l=s.SpecExtension),!(0,s.isNamedType)(l)&&(null==l?void 0:l.directResolveAs)&&(l=l.directResolveAs,i={$ref:i}),l&&void 0===l.name&&!1!==l.resolvable&&(l={name:"scalar",properties:{}}),(0,s.isNamedType)(l)&&("scalar"!==l.name||(0,r.isRef)(i))&&e(i,l,a.child([o]),P,o)}}const h=l.any.leave,I=((null===(_=l[n.name])||void 0===_?void 0:_.leave)||[]).concat(h);for(const e of u.reverse())if(e.isSkippedLevel)e.seen.delete(P);else if(e.activatedOn=(0,i.popStack)(e.activatedOn),e.parent){let t=e.parent;for(;t;)t.activatedOn.value.nextLevelTypeActivated=(0,i.popStack)(t.activatedOn.value.nextLevelTypeActivated),t=t.parent}for(const{context:e,visit:n,ruleId:r,severity:i}of I)!e.isSkippedLevel&&R.has(e)&&N(n,P,t,e,r,i)}if(j=f,(0,r.isRef)(t)){const e=l.ref.leave;for(const{visit:r,ruleId:i,severity:o,context:s}of e)R.has(s)&&r(t,{report:$.bind(void 0,i,o),resolve:A,rawNode:t,rawLocation:C,location:f,type:n,parent:h,key:m,parentLocations:{},oasVersion:u.oasVersion,getVisitorData:L.bind(void 0,i)},{node:P,location:T,error:I})}function N(e,t,r,i,o,s){e(t,{report:$.bind(void 0,o,s),resolve:A,rawNode:r,location:j,rawLocation:C,type:n,parent:h,key:m,parentLocations:a(i),oasVersion:u.oasVersion,ignoreNextVisitorsOnNode:()=>{d.add(j.pointer)},getVisitorData:L.bind(void 0,o)},function(e){var t;const n={};for(;e.parent;)n[e.parent.type.name]=null===(t=e.parent.activatedOn)||void 0===t?void 0:t.value.node,e=e.parent;return n}(i),i)}function $(e,t,n){const r=(n.location?Array.isArray(n.location)?n.location:[n.location]:[Object.assign(Object.assign({},j),{reportOnKey:!1})]).map((e=>Object.assign(Object.assign(Object.assign({},j),{reportOnKey:!1}),e))),i=n.forceSeverity||t;"off"!==i&&u.problems.push(Object.assign(Object.assign({ruleId:n.ruleId||e,severity:i},n),{suggest:n.suggest||[],location:r}))}function L(e){return u.visitorsData[e]=u.visitorsData[e]||{},u.visitorsData[e]}}(t.parsed,n,new r.Location(t.source,"#/"),void 0,"")}},1431:function(e,t,n){var r=n(8505);e.exports=function(e){return e?("{}"===e.substr(0,2)&&(e="\\{\\}"+e.substr(2)),g(function(e){return e.split("\\\\").join(i).split("\\{").join(o).split("\\}").join(s).split("\\,").join(a).split("\\.").join(l)}(e),!0).map(u)):[]};var i="\0SLASH"+Math.random()+"\0",o="\0OPEN"+Math.random()+"\0",s="\0CLOSE"+Math.random()+"\0",a="\0COMMA"+Math.random()+"\0",l="\0PERIOD"+Math.random()+"\0";function c(e){return parseInt(e,10)==e?parseInt(e,10):e.charCodeAt(0)}function u(e){return e.split(i).join("\\").split(o).join("{").split(s).join("}").split(a).join(",").split(l).join(".")}function p(e){if(!e)return[""];var t=[],n=r("{","}",e);if(!n)return e.split(",");var i=n.pre,o=n.body,s=n.post,a=i.split(",");a[a.length-1]+="{"+o+"}";var l=p(s);return s.length&&(a[a.length-1]+=l.shift(),a.push.apply(a,l)),t.push.apply(t,a),t}function d(e){return"{"+e+"}"}function f(e){return/^-?0\d/.test(e)}function h(e,t){return e<=t}function m(e,t){return e>=t}function g(e,t){var n=[],i=r("{","}",e);if(!i)return[e];var o=i.pre,a=i.post.length?g(i.post,!1):[""];if(/\$$/.test(i.pre))for(var l=0;l=0;if(!w&&!k)return i.post.match(/,(?!,).*\}/)?g(e=i.pre+"{"+i.body+s+i.post):[e];if(w)y=i.body.split(/\.\./);else if(1===(y=p(i.body)).length&&1===(y=g(y[0],!1).map(d)).length)return a.map((function(e){return i.pre+y[0]+e}));if(w){var S=c(y[0]),E=c(y[1]),O=Math.max(y[0].length,y[1].length),_=3==y.length?Math.abs(c(y[2])):1,A=h;E0){var I=new Array(T+1).join("0");P=j<0?"-"+I+P.slice(1):I+P}}b.push(P)}}else{b=[];for(var R=0;R(g(t),!(!n.nocomment&&"#"===t.charAt(0))&&new v(t,n).match(e));e.exports=r;const i=n(4077);r.sep=i.sep;const o=Symbol("globstar **");r.GLOBSTAR=o;const s=n(1431),a={"!":{open:"(?:(?!(?:",close:"))[^/]*?)"},"?":{open:"(?:",close:")?"},"+":{open:"(?:",close:")+"},"*":{open:"(?:",close:")*"},"@":{open:"(?:",close:")"}},l="[^/]",c=l+"*?",u=e=>e.split("").reduce(((e,t)=>(e[t]=!0,e)),{}),p=u("().*{}+?[]^$\\!"),d=u("[.("),f=/\/+/;r.filter=(e,t={})=>(n,i,o)=>r(n,e,t);const h=(e,t={})=>{const n={};return Object.keys(e).forEach((t=>n[t]=e[t])),Object.keys(t).forEach((e=>n[e]=t[e])),n};r.defaults=e=>{if(!e||"object"!=typeof e||!Object.keys(e).length)return r;const t=r,n=(n,r,i)=>t(n,r,h(e,i));return(n.Minimatch=class extends t.Minimatch{constructor(t,n){super(t,h(e,n))}}).defaults=n=>t.defaults(h(e,n)).Minimatch,n.filter=(n,r)=>t.filter(n,h(e,r)),n.defaults=n=>t.defaults(h(e,n)),n.makeRe=(n,r)=>t.makeRe(n,h(e,r)),n.braceExpand=(n,r)=>t.braceExpand(n,h(e,r)),n.match=(n,r,i)=>t.match(n,r,h(e,i)),n},r.braceExpand=(e,t)=>m(e,t);const m=(e,t={})=>(g(e),t.nobrace||!/\{(?:(?!\{).)*\}/.test(e)?[e]:s(e)),g=e=>{if("string"!=typeof e)throw new TypeError("invalid pattern");if(e.length>65536)throw new TypeError("pattern is too long")},y=Symbol("subparse");r.makeRe=(e,t)=>new v(e,t||{}).makeRe(),r.match=(e,t,n={})=>{const r=new v(t,n);return e=e.filter((e=>r.match(e))),r.options.nonull&&!e.length&&e.push(t),e};const b=e=>e.replace(/[[\]\\]/g,"\\$&");class v{constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.pattern=e,this.windowsPathsNoEscape=!!t.windowsPathsNoEscape||!1===t.allowWindowsEscape,this.windowsPathsNoEscape&&(this.pattern=this.pattern.replace(/\\/g,"/")),this.regexp=null,this.negate=!1,this.comment=!1,this.empty=!1,this.partial=!!t.partial,this.make()}debug(){}make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.charAt(0))return void(this.comment=!0);if(!e)return void(this.empty=!0);this.parseNegate();let n=this.globSet=this.braceExpand();t.debug&&(this.debug=(...e)=>console.error(...e)),this.debug(this.pattern,n),n=this.globParts=n.map((e=>e.split(f))),this.debug(this.pattern,n),n=n.map(((e,t,n)=>e.map(this.parse,this))),this.debug(this.pattern,n),n=n.filter((e=>-1===e.indexOf(!1))),this.debug(this.pattern,n),this.set=n}parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let t=!1,n=0;for(let r=0;r>> no match, partial?",e,d,t,f),d!==a))}if("string"==typeof u?(c=p===u,this.debug("string match",u,p,c)):(c=p.match(u),this.debug("pattern match",u,p,c)),!c)return!1}if(i===a&&s===l)return!0;if(i===a)return n;if(s===l)return i===a-1&&""===e[i];throw new Error("wtf?")}braceExpand(){return m(this.pattern,this.options)}parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)return o;e="*"}if(""===e)return"";let r="",i=!1,s=!1;const u=[],f=[];let h,m,v,x,w=!1,k=-1,S=-1,E="."===e.charAt(0),O=n.dot||E;const _=e=>"."===e.charAt(0)?"":n.dot?"(?!(?:^|\\/)\\.{1,2}(?:$|\\/))":"(?!\\.)",A=()=>{if(h){switch(h){case"*":r+=c,i=!0;break;case"?":r+=l,i=!0;break;default:r+="\\"+h}this.debug("clearStateChar %j %j",h,r),h=!1}};for(let t,o=0;o(n||(n="\\"),t+t+n+"|"))),this.debug("tail=%j\n %s",e,e,v,r);const t="*"===v.type?c:"?"===v.type?l:"\\"+v.type;i=!0,r=r.slice(0,v.reStart)+t+"\\("+e}A(),s&&(r+="\\\\");const C=d[r.charAt(0)];for(let e=f.length-1;e>-1;e--){const n=f[e],i=r.slice(0,n.reStart),o=r.slice(n.reStart,n.reEnd-8);let s=r.slice(n.reEnd);const a=r.slice(n.reEnd-8,n.reEnd)+s,l=i.split(")").length,c=i.split("(").length-l;let u=s;for(let e=0;ee.replace(/\\(.)/g,"$1"))(e);const j=n.nocase?"i":"";try{return Object.assign(new RegExp("^"+r+"$",j),{_glob:e,_src:r})}catch(e){return new RegExp("$.")}}makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=this.set;if(!e.length)return this.regexp=!1,this.regexp;const t=this.options,n=t.noglobstar?c:t.dot?"(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?":"(?:(?!(?:\\/|^)\\.).)*?",r=t.nocase?"i":"";let i=e.map((e=>(e=e.map((e=>"string"==typeof e?e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"):e===o?o:e._src)).reduce(((e,t)=>(e[e.length-1]===o&&t===o||e.push(t),e)),[]),e.forEach(((t,r)=>{t===o&&e[r-1]!==o&&(0===r?e.length>1?e[r+1]="(?:\\/|"+n+"\\/)?"+e[r+1]:e[r]=n:r===e.length-1?e[r-1]+="(?:\\/|"+n+")?":(e[r-1]+="(?:\\/|\\/"+n+"\\/)"+e[r+1],e[r+1]=o))})),e.filter((e=>e!==o)).join("/")))).join("|");i="^(?:"+i+")$",this.negate&&(i="^(?!"+i+").*$");try{this.regexp=new RegExp(i,r)}catch(e){this.regexp=!1}return this.regexp}match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.comment)return!1;if(this.empty)return""===e;if("/"===e&&t)return!0;const n=this.options;"/"!==i.sep&&(e=e.split(i.sep).join("/")),e=e.split(f),this.debug(this.pattern,"split",e);const r=this.set;let o;this.debug(this.pattern,"set",r);for(let t=e.length-1;t>=0&&(o=e[t],!o);t--);for(let i=0;i=0&&c>0){if(e===t)return[l,c];for(r=[],o=n.length;u>=0&&!a;)u==l?(r.push(u),l=n.indexOf(e,u+1)):1==r.length?a=[r.pop(),c]:((i=r.pop())=0?l:c;r.length&&(a=[o,s])}return a}e.exports=t,t.range=r},3998:function(e,t,n){"use strict";var r=n(1137);e.exports=function(e,t){return e?void t.then((function(t){r((function(){e(null,t)}))}),(function(t){r((function(){e(t)}))})):t}},1137:function(e){"use strict";e.exports="object"==typeof process&&"function"==typeof process.nextTick?process.nextTick:"function"==typeof setImmediate?setImmediate:function(e){setTimeout(e,0)}},2485:function(e,t){var n;!function(){"use strict";var r={}.hasOwnProperty;function i(){for(var e=[],t=0;tu;)if((a=l[u++])!=a)return!0}else for(;c>u;u++)if((e||u in l)&&l[u]===n)return e||u||0;return!e&&-1}};e.exports={includes:s(!0),indexOf:s(!1)}},1344:function(e,t,n){var r=n(6885),i=n(8664),o=n(2612),s=n(3747),a=n(2998),l=[].push,c=function(e){var t=1==e,n=2==e,c=3==e,u=4==e,p=6==e,d=7==e,f=5==e||p;return function(h,m,g,y){for(var b,v,x=o(h),w=i(x),k=r(m,g,3),S=s(w.length),E=0,O=y||a,_=t?O(h,S):n||d?O(h,0):void 0;S>E;E++)if((f||E in w)&&(v=k(b=w[E],E,x),e))if(t)_[E]=v;else if(v)switch(e){case 3:return!0;case 5:return b;case 6:return E;case 2:l.call(_,b)}else switch(e){case 4:return!1;case 7:l.call(_,b)}return p?-1:c||u?u:_}};e.exports={forEach:c(0),map:c(1),filter:c(2),some:c(3),every:c(4),find:c(5),findIndex:c(6),filterOut:c(7)}},5634:function(e,t,n){var r=n(2074),i=n(1602),o=n(6845),s=i("species");e.exports=function(e){return o>=51||!r((function(){var t=[];return(t.constructor={})[s]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},2998:function(e,t,n){var r=n(5335),i=n(8679),o=n(1602)("species");e.exports=function(e,t){var n;return i(e)&&("function"!=typeof(n=e.constructor)||n!==Array&&!i(n.prototype)?r(n)&&null===(n=n[o])&&(n=void 0):n=void 0),new(void 0===n?Array:n)(0===t?0:t)}},8569:function(e){var t={}.toString;e.exports=function(e){return t.call(e).slice(8,-1)}},3062:function(e,t,n){var r=n(3129),i=n(8569),o=n(1602)("toStringTag"),s="Arguments"==i(function(){return arguments}());e.exports=r?i:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:s?i(t):"Object"==(r=i(t))&&"function"==typeof t.callee?"Arguments":r}},4361:function(e,t,n){var r=n(1883),i=n(5816),o=n(7632),s=n(3610);e.exports=function(e,t){for(var n=i(t),a=s.f,l=o.f,c=0;c=74)&&(r=s.match(/Chrome\/(\d+)/))&&(i=r[1]),e.exports=i&&+i},290:function(e){e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},1605:function(e,t,n){var r=n(200),i=n(7632).f,o=n(7712),s=n(7485),a=n(5975),l=n(4361),c=n(4977);e.exports=function(e,t){var n,u,p,d,f,h=e.target,m=e.global,g=e.stat;if(n=m?r:g?r[h]||a(h,{}):(r[h]||{}).prototype)for(u in t){if(d=t[u],p=e.noTargetGet?(f=i(n,u))&&f.value:n[u],!c(m?u:h+(g?".":"#")+u,e.forced)&&void 0!==p){if(typeof d==typeof p)continue;l(d,p)}(e.sham||p&&p.sham)&&o(d,"sham",!0),s(n,u,d,e)}}},2074:function(e){e.exports=function(e){try{return!!e()}catch(e){return!0}}},6885:function(e,t,n){var r=n(9085);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)}}return function(){return e.apply(t,arguments)}}},6492:function(e,t,n){var r=n(9720),i=n(200),o=function(e){return"function"==typeof e?e:void 0};e.exports=function(e,t){return arguments.length<2?o(r[e])||o(i[e]):r[e]&&r[e][t]||i[e]&&i[e][t]}},200:function(e,t,n){var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},1883:function(e,t,n){var r=n(2612),i={}.hasOwnProperty;e.exports=Object.hasOwn||function(e,t){return i.call(r(e),t)}},7708:function(e){e.exports={}},8890:function(e,t,n){var r=n(6492);e.exports=r("document","documentElement")},7694:function(e,t,n){var r=n(5077),i=n(2074),o=n(3262);e.exports=!r&&!i((function(){return 7!=Object.defineProperty(o("div"),"a",{get:function(){return 7}}).a}))},8664:function(e,t,n){var r=n(2074),i=n(8569),o="".split;e.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(e){return"String"==i(e)?o.call(e,""):Object(e)}:Object},9965:function(e,t,n){var r=n(9310),i=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(e){return i.call(e)}),e.exports=r.inspectSource},9206:function(e,t,n){var r,i,o,s=n(2886),a=n(200),l=n(5335),c=n(7712),u=n(1883),p=n(9310),d=n(5904),f=n(7708),h="Object already initialized",m=a.WeakMap;if(s||p.state){var g=p.state||(p.state=new m),y=g.get,b=g.has,v=g.set;r=function(e,t){if(b.call(g,e))throw new TypeError(h);return t.facade=e,v.call(g,e,t),t},i=function(e){return y.call(g,e)||{}},o=function(e){return b.call(g,e)}}else{var x=d("state");f[x]=!0,r=function(e,t){if(u(e,x))throw new TypeError(h);return t.facade=e,c(e,x,t),t},i=function(e){return u(e,x)?e[x]:{}},o=function(e){return u(e,x)}}e.exports={set:r,get:i,has:o,enforce:function(e){return o(e)?i(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!l(t)||(n=i(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}}}},8679:function(e,t,n){var r=n(8569);e.exports=Array.isArray||function(e){return"Array"==r(e)}},4977:function(e,t,n){var r=n(2074),i=/#|\.prototype\./,o=function(e,t){var n=a[s(e)];return n==c||n!=l&&("function"==typeof t?r(t):!!t)},s=o.normalize=function(e){return String(e).replace(i,".").toLowerCase()},a=o.data={},l=o.NATIVE="N",c=o.POLYFILL="P";e.exports=o},5335:function(e){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},6926:function(e){e.exports=!1},1849:function(e,t,n){var r=n(6845),i=n(2074);e.exports=!!Object.getOwnPropertySymbols&&!i((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},2886:function(e,t,n){var r=n(200),i=n(9965),o=r.WeakMap;e.exports="function"==typeof o&&/native code/.test(i(o))},3105:function(e,t,n){var r,i=n(3938),o=n(5318),s=n(290),a=n(7708),l=n(8890),c=n(3262),u=n(5904),p="prototype",d="script",f=u("IE_PROTO"),h=function(){},m=function(e){return"<"+d+">"+e+""},g=function(){try{r=document.domain&&new ActiveXObject("htmlfile")}catch(e){}var e,t,n;g=r?function(e){e.write(m("")),e.close();var t=e.parentWindow.Object;return e=null,t}(r):(t=c("iframe"),n="java"+d+":",t.style.display="none",l.appendChild(t),t.src=String(n),(e=t.contentWindow.document).open(),e.write(m("document.F=Object")),e.close(),e.F);for(var i=s.length;i--;)delete g[p][s[i]];return g()};a[f]=!0,e.exports=Object.create||function(e,t){var n;return null!==e?(h[p]=i(e),n=new h,h[p]=null,n[f]=e):n=g(),void 0===t?n:o(n,t)}},5318:function(e,t,n){var r=n(5077),i=n(3610),o=n(3938),s=n(1641);e.exports=r?Object.defineProperties:function(e,t){o(e);for(var n,r=s(t),a=r.length,l=0;a>l;)i.f(e,n=r[l++],t[n]);return e}},3610:function(e,t,n){var r=n(5077),i=n(7694),o=n(3938),s=n(874),a=Object.defineProperty;t.f=r?a:function(e,t,n){if(o(e),t=s(t,!0),o(n),i)try{return a(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(e[t]=n.value),e}},7632:function(e,t,n){var r=n(5077),i=n(9304),o=n(6843),s=n(5476),a=n(874),l=n(1883),c=n(7694),u=Object.getOwnPropertyDescriptor;t.f=r?u:function(e,t){if(e=s(e),t=a(t,!0),c)try{return u(e,t)}catch(e){}if(l(e,t))return o(!i.f.call(e,t),e[t])}},6509:function(e,t,n){var r=n(5476),i=n(4789).f,o={}.toString,s="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];e.exports.f=function(e){return s&&"[object Window]"==o.call(e)?function(e){try{return i(e)}catch(e){return s.slice()}}(e):i(r(e))}},4789:function(e,t,n){var r=n(6347),i=n(290).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return r(e,i)}},8916:function(e,t){t.f=Object.getOwnPropertySymbols},6347:function(e,t,n){var r=n(1883),i=n(5476),o=n(8186).indexOf,s=n(7708);e.exports=function(e,t){var n,a=i(e),l=0,c=[];for(n in a)!r(s,n)&&r(a,n)&&c.push(n);for(;t.length>l;)r(a,n=t[l++])&&(~o(c,n)||c.push(n));return c}},1641:function(e,t,n){var r=n(6347),i=n(290);e.exports=Object.keys||function(e){return r(e,i)}},9304:function(e,t){"use strict";var n={}.propertyIsEnumerable,r=Object.getOwnPropertyDescriptor,i=r&&!n.call({1:2},1);t.f=i?function(e){var t=r(this,e);return!!t&&t.enumerable}:n},4972:function(e,t,n){"use strict";var r=n(3129),i=n(3062);e.exports=r?{}.toString:function(){return"[object "+i(this)+"]"}},5816:function(e,t,n){var r=n(6492),i=n(4789),o=n(8916),s=n(3938);e.exports=r("Reflect","ownKeys")||function(e){var t=i.f(s(e)),n=o.f;return n?t.concat(n(e)):t}},9720:function(e,t,n){var r=n(200);e.exports=r},7485:function(e,t,n){var r=n(200),i=n(7712),o=n(1883),s=n(5975),a=n(9965),l=n(9206),c=l.get,u=l.enforce,p=String(String).split("String");(e.exports=function(e,t,n,a){var l,c=!!a&&!!a.unsafe,d=!!a&&!!a.enumerable,f=!!a&&!!a.noTargetGet;"function"==typeof n&&("string"!=typeof t||o(n,"name")||i(n,"name",t),(l=u(n)).source||(l.source=p.join("string"==typeof t?t:""))),e!==r?(c?!f&&e[t]&&(d=!0):delete e[t],d?e[t]=n:i(e,t,n)):d?e[t]=n:s(t,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&c(this).source||a(this)}))},1229:function(e){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},5975:function(e,t,n){var r=n(200),i=n(7712);e.exports=function(e,t){try{i(r,e,t)}catch(n){r[e]=t}return t}},5282:function(e,t,n){var r=n(3610).f,i=n(1883),o=n(1602)("toStringTag");e.exports=function(e,t,n){e&&!i(e=n?e:e.prototype,o)&&r(e,o,{configurable:!0,value:t})}},5904:function(e,t,n){var r=n(2),i=n(665),o=r("keys");e.exports=function(e){return o[e]||(o[e]=i(e))}},9310:function(e,t,n){var r=n(200),i=n(5975),o="__core-js_shared__",s=r[o]||i(o,{});e.exports=s},2:function(e,t,n){var r=n(6926),i=n(9310);(e.exports=function(e,t){return i[e]||(i[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.14.0",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},6539:function(e,t,n){var r=n(7317),i=Math.max,o=Math.min;e.exports=function(e,t){var n=r(e);return n<0?i(n+t,0):o(n,t)}},5476:function(e,t,n){var r=n(8664),i=n(1229);e.exports=function(e){return r(i(e))}},7317:function(e){var t=Math.ceil,n=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?n:t)(e)}},3747:function(e,t,n){var r=n(7317),i=Math.min;e.exports=function(e){return e>0?i(r(e),9007199254740991):0}},2612:function(e,t,n){var r=n(1229);e.exports=function(e){return Object(r(e))}},874:function(e,t,n){var r=n(5335);e.exports=function(e,t){if(!r(e))return e;var n,i;if(t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;if("function"==typeof(n=e.valueOf)&&!r(i=n.call(e)))return i;if(!t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;throw TypeError("Can't convert object to primitive value")}},3129:function(e,t,n){var r={};r[n(1602)("toStringTag")]="z",e.exports="[object z]"===String(r)},665:function(e){var t=0,n=Math.random();e.exports=function(e){return"Symbol("+String(void 0===e?"":e)+")_"+(++t+n).toString(36)}},5225:function(e,t,n){var r=n(1849);e.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},802:function(e,t,n){var r=n(1602);t.f=r},1602:function(e,t,n){var r=n(200),i=n(2),o=n(1883),s=n(665),a=n(1849),l=n(5225),c=i("wks"),u=r.Symbol,p=l?u:u&&u.withoutSetter||s;e.exports=function(e){return o(c,e)&&(a||"string"==typeof c[e])||(a&&o(u,e)?c[e]=u[e]:c[e]=p("Symbol."+e)),c[e]}},115:function(e,t,n){"use strict";var r=n(1605),i=n(2074),o=n(8679),s=n(5335),a=n(2612),l=n(3747),c=n(2057),u=n(2998),p=n(5634),d=n(1602),f=n(6845),h=d("isConcatSpreadable"),m=9007199254740991,g="Maximum allowed index exceeded",y=f>=51||!i((function(){var e=[];return e[h]=!1,e.concat()[0]!==e})),b=p("concat"),v=function(e){if(!s(e))return!1;var t=e[h];return void 0!==t?!!t:o(e)};r({target:"Array",proto:!0,forced:!y||!b},{concat:function(e){var t,n,r,i,o,s=a(this),p=u(s,0),d=0;for(t=-1,r=arguments.length;tm)throw TypeError(g);for(n=0;n=m)throw TypeError(g);c(p,d++,o)}return p.length=d,p}})},1586:function(e,t,n){var r=n(200);n(5282)(r.JSON,"JSON",!0)},6982:function(e,t,n){n(5282)(Math,"Math",!0)},5086:function(e,t,n){var r=n(3129),i=n(7485),o=n(4972);r||i(Object.prototype,"toString",o,{unsafe:!0})},3719:function(e,t,n){var r=n(1605),i=n(200),o=n(5282);r({global:!0},{Reflect:{}}),o(i.Reflect,"Reflect",!0)},7727:function(e,t,n){n(1272)("asyncIterator")},590:function(e,t,n){"use strict";var r=n(1605),i=n(5077),o=n(200),s=n(1883),a=n(5335),l=n(3610).f,c=n(4361),u=o.Symbol;if(i&&"function"==typeof u&&(!("description"in u.prototype)||void 0!==u().description)){var p={},d=function(){var e=arguments.length<1||void 0===arguments[0]?void 0:String(arguments[0]),t=this instanceof d?new u(e):void 0===e?u():u(e);return""===e&&(p[t]=!0),t};c(d,u);var f=d.prototype=u.prototype;f.constructor=d;var h=f.toString,m="Symbol(test)"==String(u("test")),g=/^Symbol\((.*)\)[^)]+$/;l(f,"description",{configurable:!0,get:function(){var e=a(this)?this.valueOf():this,t=h.call(e);if(s(p,e))return"";var n=m?t.slice(7,-1):t.replace(g,"$1");return""===n?void 0:n}}),r({global:!0,forced:!0},{Symbol:d})}},8290:function(e,t,n){n(1272)("hasInstance")},2619:function(e,t,n){n(1272)("isConcatSpreadable")},4216:function(e,t,n){n(1272)("iterator")},3534:function(e,t,n){"use strict";var r=n(1605),i=n(200),o=n(6492),s=n(6926),a=n(5077),l=n(1849),c=n(5225),u=n(2074),p=n(1883),d=n(8679),f=n(5335),h=n(3938),m=n(2612),g=n(5476),y=n(874),b=n(6843),v=n(3105),x=n(1641),w=n(4789),k=n(6509),S=n(8916),E=n(7632),O=n(3610),_=n(9304),A=n(7712),C=n(7485),j=n(2),P=n(5904),T=n(7708),I=n(665),R=n(1602),N=n(802),$=n(1272),L=n(5282),D=n(9206),M=n(1344).forEach,F=P("hidden"),z="Symbol",B="prototype",U=R("toPrimitive"),q=D.set,V=D.getterFor(z),W=Object[B],H=i.Symbol,Y=o("JSON","stringify"),G=E.f,Q=O.f,X=k.f,K=_.f,Z=j("symbols"),J=j("op-symbols"),ee=j("string-to-symbol-registry"),te=j("symbol-to-string-registry"),ne=j("wks"),re=i.QObject,ie=!re||!re[B]||!re[B].findChild,oe=a&&u((function(){return 7!=v(Q({},"a",{get:function(){return Q(this,"a",{value:7}).a}})).a}))?function(e,t,n){var r=G(W,t);r&&delete W[t],Q(e,t,n),r&&e!==W&&Q(W,t,r)}:Q,se=function(e,t){var n=Z[e]=v(H[B]);return q(n,{type:z,tag:e,description:t}),a||(n.description=t),n},ae=c?function(e){return"symbol"==typeof e}:function(e){return Object(e)instanceof H},le=function(e,t,n){e===W&&le(J,t,n),h(e);var r=y(t,!0);return h(n),p(Z,r)?(n.enumerable?(p(e,F)&&e[F][r]&&(e[F][r]=!1),n=v(n,{enumerable:b(0,!1)})):(p(e,F)||Q(e,F,b(1,{})),e[F][r]=!0),oe(e,r,n)):Q(e,r,n)},ce=function(e,t){h(e);var n=g(t),r=x(n).concat(fe(n));return M(r,(function(t){a&&!ue.call(n,t)||le(e,t,n[t])})),e},ue=function(e){var t=y(e,!0),n=K.call(this,t);return!(this===W&&p(Z,t)&&!p(J,t))&&(!(n||!p(this,t)||!p(Z,t)||p(this,F)&&this[F][t])||n)},pe=function(e,t){var n=g(e),r=y(t,!0);if(n!==W||!p(Z,r)||p(J,r)){var i=G(n,r);return!i||!p(Z,r)||p(n,F)&&n[F][r]||(i.enumerable=!0),i}},de=function(e){var t=X(g(e)),n=[];return M(t,(function(e){p(Z,e)||p(T,e)||n.push(e)})),n},fe=function(e){var t=e===W,n=X(t?J:g(e)),r=[];return M(n,(function(e){!p(Z,e)||t&&!p(W,e)||r.push(Z[e])})),r};l||(H=function(){if(this instanceof H)throw TypeError("Symbol is not a constructor");var e=arguments.length&&void 0!==arguments[0]?String(arguments[0]):void 0,t=I(e),n=function(e){this===W&&n.call(J,e),p(this,F)&&p(this[F],t)&&(this[F][t]=!1),oe(this,t,b(1,e))};return a&&ie&&oe(W,t,{configurable:!0,set:n}),se(t,e)},C(H[B],"toString",(function(){return V(this).tag})),C(H,"withoutSetter",(function(e){return se(I(e),e)})),_.f=ue,O.f=le,E.f=pe,w.f=k.f=de,S.f=fe,N.f=function(e){return se(R(e),e)},a&&(Q(H[B],"description",{configurable:!0,get:function(){return V(this).description}}),s||C(W,"propertyIsEnumerable",ue,{unsafe:!0}))),r({global:!0,wrap:!0,forced:!l,sham:!l},{Symbol:H}),M(x(ne),(function(e){$(e)})),r({target:z,stat:!0,forced:!l},{for:function(e){var t=String(e);if(p(ee,t))return ee[t];var n=H(t);return ee[t]=n,te[n]=t,n},keyFor:function(e){if(!ae(e))throw TypeError(e+" is not a symbol");if(p(te,e))return te[e]},useSetter:function(){ie=!0},useSimple:function(){ie=!1}}),r({target:"Object",stat:!0,forced:!l,sham:!a},{create:function(e,t){return void 0===t?v(e):ce(v(e),t)},defineProperty:le,defineProperties:ce,getOwnPropertyDescriptor:pe}),r({target:"Object",stat:!0,forced:!l},{getOwnPropertyNames:de,getOwnPropertySymbols:fe}),r({target:"Object",stat:!0,forced:u((function(){S.f(1)}))},{getOwnPropertySymbols:function(e){return S.f(m(e))}}),Y&&r({target:"JSON",stat:!0,forced:!l||u((function(){var e=H();return"[null]"!=Y([e])||"{}"!=Y({a:e})||"{}"!=Y(Object(e))}))},{stringify:function(e,t,n){for(var r,i=[e],o=1;arguments.length>o;)i.push(arguments[o++]);if(r=t,(f(t)||void 0!==e)&&!ae(e))return d(t)||(t=function(e,t){if("function"==typeof r&&(t=r.call(this,e,t)),!ae(t))return t}),i[1]=t,Y.apply(null,i)}}),H[B][U]||A(H[B],U,H[B].valueOf),L(H,z),T[F]=!0},6195:function(e,t,n){n(1272)("matchAll")},2957:function(e,t,n){n(1272)("match")},4100:function(e,t,n){n(1272)("replace")},3006:function(e,t,n){n(1272)("search")},4910:function(e,t,n){n(1272)("species")},2820:function(e,t,n){n(1272)("split")},6611:function(e,t,n){n(1272)("toPrimitive")},9576:function(e,t,n){n(1272)("toStringTag")},9747:function(e,t,n){n(1272)("unscopables")},8997:function(e,t,n){"use strict";var r=n(4991),i=n.n(r),o=n(6314),s=n.n(o)()(i());s.push([e.id,".ps{overflow:hidden!important;overflow-anchor:none;-ms-overflow-style:none;touch-action:auto;-ms-touch-action:auto}.ps__rail-x{display:none;opacity:0;transition:background-color .2s linear,opacity .2s linear;-webkit-transition:background-color .2s linear,opacity .2s linear;height:15px;bottom:0;position:absolute}.ps__rail-y{display:none;opacity:0;transition:background-color .2s linear,opacity .2s linear;-webkit-transition:background-color .2s linear,opacity .2s linear;width:15px;right:0;position:absolute}.ps--active-x>.ps__rail-x,.ps--active-y>.ps__rail-y{display:block;background-color:transparent}.ps:hover>.ps__rail-x,.ps:hover>.ps__rail-y,.ps--focus>.ps__rail-x,.ps--focus>.ps__rail-y,.ps--scrolling-x>.ps__rail-x,.ps--scrolling-y>.ps__rail-y{opacity:.6}.ps .ps__rail-x:hover,.ps .ps__rail-y:hover,.ps .ps__rail-x:focus,.ps .ps__rail-y:focus,.ps .ps__rail-x.ps--clicking,.ps .ps__rail-y.ps--clicking{background-color:#eee;opacity:.9}.ps__thumb-x{background-color:#aaa;border-radius:6px;transition:background-color .2s linear,height .2s ease-in-out;-webkit-transition:background-color .2s linear,height .2s ease-in-out;height:6px;bottom:2px;position:absolute}.ps__thumb-y{background-color:#aaa;border-radius:6px;transition:background-color .2s linear,width .2s ease-in-out;-webkit-transition:background-color .2s linear,width .2s ease-in-out;width:6px;right:2px;position:absolute}.ps__rail-x:hover>.ps__thumb-x,.ps__rail-x:focus>.ps__thumb-x,.ps__rail-x.ps--clicking .ps__thumb-x{background-color:#999;height:11px}.ps__rail-y:hover>.ps__thumb-y,.ps__rail-y:focus>.ps__thumb-y,.ps__rail-y.ps--clicking .ps__thumb-y{background-color:#999;width:11px}@supports (-ms-overflow-style: none){.ps{overflow:auto!important}}@media screen and (-ms-high-contrast: active),(-ms-high-contrast: none){.ps{overflow:auto!important}}\n","",{version:3,sources:["webpack://./node_modules/perfect-scrollbar/css/perfect-scrollbar.css"],names:[],mappings:"AAGA,IACE,yBAAU,CACV,oBAAiB,CACjB,uBAAoB,CACpB,iBAAc,CACd,qBACF,CAKA,YACE,YAAS,CACT,SAAS,CACT,yDAAqD,CACrD,iEAA6D,CAC7D,WAAQ,CAER,QAAQ,CAER,iBACF,CAEA,YACE,YAAS,CACT,SAAS,CACT,yDAAqD,CACrD,iEAA6D,CAC7D,UAAO,CAEP,OAAO,CAEP,iBACF,CAEA,oDAEE,aAAS,CACT,4BACF,CAEA,oJAME,UACF,CAEA,kJAME,qBAAkB,CAClB,UACF,CAKA,aACE,qBAAkB,CAnEpB,iBAoEiB,CACf,6DAAoD,CACpD,qEAA4D,CAC5D,UAAQ,CAER,UAAQ,CAER,iBACF,CAEA,aACE,qBAAkB,CA/EpB,iBAgFiB,CACf,4DAAmD,CACnD,oEAA2D,CAC3D,SAAO,CAEP,SAAO,CAEP,iBACF,CAEA,oGAGE,qBAAkB,CAClB,WACF,CAEA,oGAGE,qBAAkB,CAClB,UACF,CAGA,qCACE,IACE,uBACF,CACF,CAEA,wEACE,IACE,uBACF,CACF",sourcesContent:["/*\n * Container style\n */\n.ps {\n overflow: hidden !important;\n overflow-anchor: none;\n -ms-overflow-style: none;\n touch-action: auto;\n -ms-touch-action: auto;\n}\n\n/*\n * Scrollbar rail styles\n */\n.ps__rail-x {\n display: none;\n opacity: 0;\n transition: background-color .2s linear, opacity .2s linear;\n -webkit-transition: background-color .2s linear, opacity .2s linear;\n height: 15px;\n /* there must be 'bottom' or 'top' for ps__rail-x */\n bottom: 0px;\n /* please don't change 'position' */\n position: absolute;\n}\n\n.ps__rail-y {\n display: none;\n opacity: 0;\n transition: background-color .2s linear, opacity .2s linear;\n -webkit-transition: background-color .2s linear, opacity .2s linear;\n width: 15px;\n /* there must be 'right' or 'left' for ps__rail-y */\n right: 0;\n /* please don't change 'position' */\n position: absolute;\n}\n\n.ps--active-x > .ps__rail-x,\n.ps--active-y > .ps__rail-y {\n display: block;\n background-color: transparent;\n}\n\n.ps:hover > .ps__rail-x,\n.ps:hover > .ps__rail-y,\n.ps--focus > .ps__rail-x,\n.ps--focus > .ps__rail-y,\n.ps--scrolling-x > .ps__rail-x,\n.ps--scrolling-y > .ps__rail-y {\n opacity: 0.6;\n}\n\n.ps .ps__rail-x:hover,\n.ps .ps__rail-y:hover,\n.ps .ps__rail-x:focus,\n.ps .ps__rail-y:focus,\n.ps .ps__rail-x.ps--clicking,\n.ps .ps__rail-y.ps--clicking {\n background-color: #eee;\n opacity: 0.9;\n}\n\n/*\n * Scrollbar thumb styles\n */\n.ps__thumb-x {\n background-color: #aaa;\n border-radius: 6px;\n transition: background-color .2s linear, height .2s ease-in-out;\n -webkit-transition: background-color .2s linear, height .2s ease-in-out;\n height: 6px;\n /* there must be 'bottom' for ps__thumb-x */\n bottom: 2px;\n /* please don't change 'position' */\n position: absolute;\n}\n\n.ps__thumb-y {\n background-color: #aaa;\n border-radius: 6px;\n transition: background-color .2s linear, width .2s ease-in-out;\n -webkit-transition: background-color .2s linear, width .2s ease-in-out;\n width: 6px;\n /* there must be 'right' for ps__thumb-y */\n right: 2px;\n /* please don't change 'position' */\n position: absolute;\n}\n\n.ps__rail-x:hover > .ps__thumb-x,\n.ps__rail-x:focus > .ps__thumb-x,\n.ps__rail-x.ps--clicking .ps__thumb-x {\n background-color: #999;\n height: 11px;\n}\n\n.ps__rail-y:hover > .ps__thumb-y,\n.ps__rail-y:focus > .ps__thumb-y,\n.ps__rail-y.ps--clicking .ps__thumb-y {\n background-color: #999;\n width: 11px;\n}\n\n/* MS supports */\n@supports (-ms-overflow-style: none) {\n .ps {\n overflow: auto !important;\n }\n}\n\n@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n .ps {\n overflow: auto !important;\n }\n}\n"],sourceRoot:""}]),t.A=s},6314:function(e){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var i={};if(r)for(var o=0;oe.length)&&(t=e.length);for(var n=0,r=new Array(t);n2?r:e).apply(void 0,i)}}e.memoize=s,e.debounce=a,e.bind=l,e.default={memoize:s,debounce:a,bind:l}},void 0===(r=n.apply(t,[t]))||(e.exports=r)},6364:function(e){e.exports={}},228:function(e){"use strict";var t=Object.prototype.hasOwnProperty,n="~";function r(){}function i(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function o(e,t,r,o,s){if("function"!=typeof r)throw new TypeError("The listener must be a function");var a=new i(r,o||e,s),l=n?n+t:t;return e._events[l]?e._events[l].fn?e._events[l]=[e._events[l],a]:e._events[l].push(a):(e._events[l]=a,e._eventsCount++),e}function s(e,t){0==--e._eventsCount?e._events=new r:delete e._events[t]}function a(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),a.prototype.eventNames=function(){var e,r,i=[];if(0===this._eventsCount)return i;for(r in e=this._events)t.call(e,r)&&i.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?i.concat(Object.getOwnPropertySymbols(e)):i},a.prototype.listeners=function(e){var t=n?n+e:e,r=this._events[t];if(!r)return[];if(r.fn)return[r.fn];for(var i=0,o=r.length,s=new Array(o);iu.depthLimit)return void a(t,e,r,s);if(void 0!==u.edgesLimit&&i+1>u.edgesLimit)return void a(t,e,r,s);if(o.push(e),Array.isArray(e))for(p=0;pt?1:0}function u(e,t,n,s){void 0===s&&(s=o());var a,l=p(e,"",0,[],void 0,0,s)||e;try{a=0===i.length?JSON.stringify(l,t,n):JSON.stringify(l,d(t),n)}catch(e){return JSON.stringify("[unable to serialize, circular reference is too complex to analyze]")}finally{for(;0!==r.length;){var c=r.pop();4===c.length?Object.defineProperty(c[0],c[1],c[3]):c[0][c[1]]=c[2]}}return a}function p(e,i,o,s,l,u,d){var f;if(u+=1,"object"==typeof e&&null!==e){for(f=0;fd.depthLimit)return void a(t,e,i,l);if(void 0!==d.edgesLimit&&o+1>d.edgesLimit)return void a(t,e,i,l);if(s.push(e),Array.isArray(e))for(f=0;f0)for(var r=0;r{for(const n of e){if("string"==typeof n&&t===n)return!0;if(n instanceof RegExp&&n.test(t))return!0}}:()=>!1}},5334:function(e,t){"use strict";const n=":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",r="["+n+"]["+n+"\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*",i=new RegExp("^"+r+"$");t.isExist=function(e){return void 0!==e},t.isEmptyObject=function(e){return 0===Object.keys(e).length},t.merge=function(e,t,n){if(t){const r=Object.keys(t),i=r.length;for(let o=0;o5&&"xml"===r)return h("InvalidXml","XML declaration allowed only at the start of the document.",g(e,t));if("?"==e[t]&&">"==e[t+1]){t++;break}}return t}function a(e,t){if(e.length>t+5&&"-"===e[t+1]&&"-"===e[t+2]){for(t+=3;t"===e[t+2]){t+=2;break}}else if(e.length>t+8&&"D"===e[t+1]&&"O"===e[t+2]&&"C"===e[t+3]&&"T"===e[t+4]&&"Y"===e[t+5]&&"P"===e[t+6]&&"E"===e[t+7]){let n=1;for(t+=8;t"===e[t]&&(n--,0===n))break}else if(e.length>t+9&&"["===e[t+1]&&"C"===e[t+2]&&"D"===e[t+3]&&"A"===e[t+4]&&"T"===e[t+5]&&"A"===e[t+6]&&"["===e[t+7])for(t+=8;t"===e[t+2]){t+=2;break}return t}t.validate=function(e,t){t=Object.assign({},i,t);const n=[];let l=!1,c=!1;"\ufeff"===e[0]&&(e=e.substr(1));for(let i=0;i"!==e[i]&&" "!==e[i]&&"\t"!==e[i]&&"\n"!==e[i]&&"\r"!==e[i];i++)b+=e[i];if(b=b.trim(),"/"===b[b.length-1]&&(b=b.substring(0,b.length-1),i--),p=b,!r.isName(p)){let t;return t=0===b.trim().length?"Invalid space after '<'.":"Tag '"+b+"' is an invalid name.",h("InvalidTag",t,g(e,i))}const v=u(e,i);if(!1===v)return h("InvalidAttr","Attributes for '"+b+"' have open quote.",g(e,i));let x=v.value;if(i=v.index,"/"===x[x.length-1]){const n=i-x.length;x=x.substring(0,x.length-1);const r=d(x,t);if(!0!==r)return h(r.err.code,r.err.msg,g(e,n+r.err.line));l=!0}else if(y){if(!v.tagClosed)return h("InvalidTag","Closing tag '"+b+"' doesn't have proper closing.",g(e,i));if(x.trim().length>0)return h("InvalidTag","Closing tag '"+b+"' can't have attributes or invalid starting.",g(e,m));if(0===n.length)return h("InvalidTag","Closing tag '"+b+"' has not been opened.",g(e,m));{const t=n.pop();if(b!==t.tagName){let n=g(e,t.tagStartPos);return h("InvalidTag","Expected closing tag '"+t.tagName+"' (opened in line "+n.line+", col "+n.col+") instead of closing tag '"+b+"'.",g(e,m))}0==n.length&&(c=!0)}}else{const r=d(x,t);if(!0!==r)return h(r.err.code,r.err.msg,g(e,i-x.length+r.err.line));if(!0===c)return h("InvalidXml","Multiple possible root nodes found.",g(e,i));-1!==t.unpairedTags.indexOf(b)||n.push({tagName:b,tagStartPos:m}),l=!0}for(i++;i0)||h("InvalidXml","Invalid '"+JSON.stringify(n.map((e=>e.tagName)),null,4).replace(/\r?\n/g,"")+"' found.",{line:1,col:1}):h("InvalidXml","Start tag expected.",1)};const l='"',c="'";function u(e,t){let n="",r="",i=!1;for(;t"===e[t]&&""===r){i=!0;break}n+=e[t]}return""===r&&{value:n,index:t,tagClosed:i}}const p=new RegExp("(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['\"])(([\\s\\S])*?)\\5)?","g");function d(e,t){const n=r.getAllMatches(e,p),i={};for(let e=0;e","g"),val:">"},{regex:new RegExp("<","g"),val:"<"},{regex:new RegExp("'","g"),val:"'"},{regex:new RegExp('"',"g"),val:"""}],processEntities:!0,stopNodes:[],oneListGroup:!1};function s(e){this.options=Object.assign({},o,e),!0===this.options.ignoreAttributes||this.options.attributesGroupName?this.isAttribute=function(){return!1}:(this.ignoreAttributesFn=i(this.options.ignoreAttributes),this.attrPrefixLen=this.options.attributeNamePrefix.length,this.isAttribute=c),this.processTextOrObjNode=a,this.options.format?(this.indentate=l,this.tagEndChar=">\n",this.newLine="\n"):(this.indentate=function(){return""},this.tagEndChar=">",this.newLine="")}function a(e,t,n,r){const i=this.j2x(e,n+1,r.concat(t));return void 0!==e[this.options.textNodeName]&&1===Object.keys(e).length?this.buildTextValNode(e[this.options.textNodeName],t,i.attrStr,n):this.buildObjectNode(i.val,t,i.attrStr,n)}function l(e){return this.options.indentBy.repeat(e)}function c(e){return!(!e.startsWith(this.options.attributeNamePrefix)||e===this.options.textNodeName)&&e.substr(this.attrPrefixLen)}s.prototype.build=function(e){return this.options.preserveOrder?r(e,this.options):(Array.isArray(e)&&this.options.arrayNodeName&&this.options.arrayNodeName.length>1&&(e={[this.options.arrayNodeName]:e}),this.j2x(e,0,[]).val)},s.prototype.j2x=function(e,t,n){let r="",i="";const o=n.join(".");for(let s in e)if(Object.prototype.hasOwnProperty.call(e,s))if(void 0===e[s])this.isAttribute(s)&&(i+="");else if(null===e[s])this.isAttribute(s)||s===this.options.cdataPropName?i+="":"?"===s[0]?i+=this.indentate(t)+"<"+s+"?"+this.tagEndChar:i+=this.indentate(t)+"<"+s+"/"+this.tagEndChar;else if(e[s]instanceof Date)i+=this.buildTextValNode(e[s],s,"",t);else if("object"!=typeof e[s]){const n=this.isAttribute(s);if(n&&!this.ignoreAttributesFn(n,o))r+=this.buildAttrPairStr(n,""+e[s]);else if(!n)if(s===this.options.textNodeName){let t=this.options.tagValueProcessor(s,""+e[s]);i+=this.replaceEntitiesValue(t)}else i+=this.buildTextValNode(e[s],s,"",t)}else if(Array.isArray(e[s])){const r=e[s].length;let o="",a="";for(let l=0;l"+e+i}},s.prototype.closeTag=function(e){let t="";return-1!==this.options.unpairedTags.indexOf(e)?this.options.suppressUnpairedNode||(t="/"):t=this.options.suppressEmptyNode?"/":`>`+this.newLine;if(!1!==this.options.commentPropName&&t===this.options.commentPropName)return this.indentate(r)+`\x3c!--${e}--\x3e`+this.newLine;if("?"===t[0])return this.indentate(r)+"<"+t+n+"?"+this.tagEndChar;{let i=this.options.tagValueProcessor(t,e);return i=this.replaceEntitiesValue(i),""===i?this.indentate(r)+"<"+t+n+this.closeTag(t)+this.tagEndChar:this.indentate(r)+"<"+t+n+">"+i+"0&&this.options.processEntities)for(let t=0;t`,u=!1;continue}if(f===s.commentPropName){c+=l+`\x3c!--${d[f][0][s.textNodeName]}--\x3e`,u=!0;continue}if("?"===f[0]){const e=r(d[":@"],s),t="?xml"===f?"":l;let n=d[f][0][s.textNodeName];n=0!==n.length?" "+n:"",c+=t+`<${f}${n}${e}?>`,u=!0;continue}let m=l;""!==m&&(m+=s.indentBy);const g=l+`<${f}${r(d[":@"],s)}`,y=t(d[f],s,h,m);-1!==s.unpairedTags.indexOf(f)?s.suppressUnpairedNode?c+=g+">":c+=g+"/>":y&&0!==y.length||!s.suppressEmptyNode?y&&y.endsWith(">")?c+=g+`>${y}${l}`:(c+=g+">",y&&""!==l&&(y.includes("/>")||y.includes("`):c+=g+"/>",u=!0}return c}function n(e){const t=Object.keys(e);for(let n=0;n0&&t.processEntities)for(let n=0;n0&&(r="\n"),t(e,n,"",r)}},9400:function(e,t,n){const r=n(5334);function i(e,t){let n="";for(;t"===e[t]){if(d?"-"===e[t-1]&&"-"===e[t-2]&&(d=!1,r--):r--,0===r)break}else"["===e[t]?p=!0:f+=e[t];else{if(p&&s(e,t)){let r,o;t+=7,[r,o,t]=i(e,t+1),-1===o.indexOf("&")&&(n[u(r)]={regx:RegExp(`&${r};`,"g"),val:o})}else if(p&&a(e,t))t+=8;else if(p&&l(e,t))t+=8;else if(p&&c(e,t))t+=9;else{if(!o)throw new Error("Invalid DOCTYPE");d=!0}r++,f=""}if(0!==r)throw new Error("Unclosed DOCTYPE")}return{entities:n,i:t}}},460:function(e,t){const n={preserveOrder:!1,attributeNamePrefix:"@_",attributesGroupName:!1,textNodeName:"#text",ignoreAttributes:!0,removeNSPrefix:!1,allowBooleanAttributes:!1,parseTagValue:!0,parseAttributeValue:!1,trimValues:!0,cdataPropName:!1,numberParseOptions:{hex:!0,leadingZeros:!0,eNotation:!0},tagValueProcessor:function(e,t){return t},attributeValueProcessor:function(e,t){return t},stopNodes:[],alwaysCreateTextNode:!1,isArray:()=>!1,commentPropName:!1,unpairedTags:[],processEntities:!0,htmlEntities:!1,ignoreDeclaration:!1,ignorePiTags:!1,transformTagName:!1,transformAttributeName:!1,updateTag:function(e,t,n){return e}};t.buildOptions=function(e){return Object.assign({},n,e)},t.defaultOptions=n},7680:function(e,t,n){"use strict";const r=n(5334),i=n(3832),o=n(9400),s=n(7983),a=n(3085);function l(e){const t=Object.keys(e);for(let n=0;n0)){s||(e=this.replaceEntitiesValue(e));const r=this.options.tagValueProcessor(t,e,n,i,o);return null==r?e:typeof r!=typeof e||r!==e?r:this.options.trimValues||e.trim()===e?w(e,this.options.parseTagValue,this.options.numberParseOptions):e}}function u(e){if(this.options.removeNSPrefix){const t=e.split(":"),n="/"===e.charAt(0)?"/":"";if("xmlns"===t[0])return"";2===t.length&&(e=n+t[1])}return e}const p=new RegExp("([^\\s=]+)\\s*(=\\s*(['\"])([\\s\\S]*?)\\3)?","gm");function d(e,t,n){if(!0!==this.options.ignoreAttributes&&"string"==typeof e){const n=r.getAllMatches(e,p),i=n.length,o={};for(let e=0;e",a,"Closing Tag is not closed.");let i=e.substring(a+2,t).trim();if(this.options.removeNSPrefix){const e=i.indexOf(":");-1!==e&&(i=i.substr(e+1))}this.options.transformTagName&&(i=this.options.transformTagName(i)),n&&(r=this.saveTextToParentTag(r,n,s));const o=s.substring(s.lastIndexOf(".")+1);if(i&&-1!==this.options.unpairedTags.indexOf(i))throw new Error(`Unpaired tag can not be used as closing tag: `);let l=0;o&&-1!==this.options.unpairedTags.indexOf(o)?(l=s.lastIndexOf(".",s.lastIndexOf(".")-1),this.tagsNodeStack.pop()):l=s.lastIndexOf("."),s=s.substring(0,l),n=this.tagsNodeStack.pop(),r="",a=t}else if("?"===e[a+1]){let t=v(e,a,!1,"?>");if(!t)throw new Error("Pi Tag is not closed.");if(r=this.saveTextToParentTag(r,n,s),this.options.ignoreDeclaration&&"?xml"===t.tagName||this.options.ignorePiTags);else{const e=new i(t.tagName);e.add(this.options.textNodeName,""),t.tagName!==t.tagExp&&t.attrExpPresent&&(e[":@"]=this.buildAttributesMap(t.tagExp,s,t.tagName)),this.addChild(n,e,s)}a=t.closeIndex+1}else if("!--"===e.substr(a+1,3)){const t=b(e,"--\x3e",a+4,"Comment is not closed.");if(this.options.commentPropName){const i=e.substring(a+4,t-2);r=this.saveTextToParentTag(r,n,s),n.add(this.options.commentPropName,[{[this.options.textNodeName]:i}])}a=t}else if("!D"===e.substr(a+1,2)){const t=o(e,a);this.docTypeEntities=t.entities,a=t.i}else if("!["===e.substr(a+1,2)){const t=b(e,"]]>",a,"CDATA is not closed.")-2,i=e.substring(a+9,t);r=this.saveTextToParentTag(r,n,s);let o=this.parseTextData(i,n.tagname,s,!0,!1,!0,!0);null==o&&(o=""),this.options.cdataPropName?n.add(this.options.cdataPropName,[{[this.options.textNodeName]:i}]):n.add(this.options.textNodeName,o),a=t+2}else{let o=v(e,a,this.options.removeNSPrefix),l=o.tagName;const c=o.rawTagName;let u=o.tagExp,p=o.attrExpPresent,d=o.closeIndex;this.options.transformTagName&&(l=this.options.transformTagName(l)),n&&r&&"!xml"!==n.tagname&&(r=this.saveTextToParentTag(r,n,s,!1));const f=n;if(f&&-1!==this.options.unpairedTags.indexOf(f.tagname)&&(n=this.tagsNodeStack.pop(),s=s.substring(0,s.lastIndexOf("."))),l!==t.tagname&&(s+=s?"."+l:l),this.isItStopNode(this.options.stopNodes,s,l)){let t="";if(u.length>0&&u.lastIndexOf("/")===u.length-1)"/"===l[l.length-1]?(l=l.substr(0,l.length-1),s=s.substr(0,s.length-1),u=l):u=u.substr(0,u.length-1),a=o.closeIndex;else if(-1!==this.options.unpairedTags.indexOf(l))a=o.closeIndex;else{const n=this.readStopNodeData(e,c,d+1);if(!n)throw new Error(`Unexpected end of ${c}`);a=n.i,t=n.tagContent}const r=new i(l);l!==u&&p&&(r[":@"]=this.buildAttributesMap(u,s,l)),t&&(t=this.parseTextData(t,l,s,!0,p,!0,!0)),s=s.substr(0,s.lastIndexOf(".")),r.add(this.options.textNodeName,t),this.addChild(n,r,s)}else{if(u.length>0&&u.lastIndexOf("/")===u.length-1){"/"===l[l.length-1]?(l=l.substr(0,l.length-1),s=s.substr(0,s.length-1),u=l):u=u.substr(0,u.length-1),this.options.transformTagName&&(l=this.options.transformTagName(l));const e=new i(l);l!==u&&p&&(e[":@"]=this.buildAttributesMap(u,s,l)),this.addChild(n,e,s),s=s.substr(0,s.lastIndexOf("."))}else{const e=new i(l);this.tagsNodeStack.push(n),l!==u&&p&&(e[":@"]=this.buildAttributesMap(u,s,l)),this.addChild(n,e,s),n=e}r="",a=d}}else r+=e[a];return t.child};function h(e,t,n){const r=this.options.updateTag(t.tagname,n,t[":@"]);!1===r||("string"==typeof r?(t.tagname=r,e.addChild(t)):e.addChild(t))}const m=function(e){if(this.options.processEntities){for(let t in this.docTypeEntities){const n=this.docTypeEntities[t];e=e.replace(n.regx,n.val)}for(let t in this.lastEntities){const n=this.lastEntities[t];e=e.replace(n.regex,n.val)}if(this.options.htmlEntities)for(let t in this.htmlEntities){const n=this.htmlEntities[t];e=e.replace(n.regex,n.val)}e=e.replace(this.ampEntity.regex,this.ampEntity.val)}return e};function g(e,t,n,r){return e&&(void 0===r&&(r=0===t.child.length),void 0!==(e=this.parseTextData(e,t.tagname,n,!1,!!t[":@"]&&0!==Object.keys(t[":@"]).length,r))&&""!==e&&t.add(this.options.textNodeName,e),e=""),e}function y(e,t,n){const r="*."+n;for(const n in e){const i=e[n];if(r===i||t===i)return!0}return!1}function b(e,t,n,r){const i=e.indexOf(t,n);if(-1===i)throw new Error(r);return i+t.length-1}function v(e,t,n,r=">"){const i=function(e,t,n=">"){let r,i="";for(let o=t;o",n,`${t} is not closed`);if(e.substring(n+2,o).trim()===t&&(i--,0===i))return{tagContent:e.substring(r,n),i:o};n=o}else if("?"===e[n+1])n=b(e,"?>",n+1,"StopNode is not closed.");else if("!--"===e.substr(n+1,3))n=b(e,"--\x3e",n+3,"StopNode is not closed.");else if("!["===e.substr(n+1,2))n=b(e,"]]>",n,"StopNode is not closed.")-2;else{const r=v(e,n,">");r&&((r&&r.tagName)===t&&"/"!==r.tagExp[r.tagExp.length-1]&&i++,n=r.closeIndex)}}function w(e,t,n){if(t&&"string"==typeof e){const t=e.trim();return"true"===t||"false"!==t&&s(e,n)}return r.isExist(e)?e:""}e.exports=class{constructor(e){this.options=e,this.currentNode=null,this.tagsNodeStack=[],this.docTypeEntities={},this.lastEntities={apos:{regex:/&(apos|#39|#x27);/g,val:"'"},gt:{regex:/&(gt|#62|#x3E);/g,val:">"},lt:{regex:/&(lt|#60|#x3C);/g,val:"<"},quot:{regex:/&(quot|#34|#x22);/g,val:'"'}},this.ampEntity={regex:/&(amp|#38|#x26);/g,val:"&"},this.htmlEntities={space:{regex:/&(nbsp|#160);/g,val:" "},cent:{regex:/&(cent|#162);/g,val:"¢"},pound:{regex:/&(pound|#163);/g,val:"£"},yen:{regex:/&(yen|#165);/g,val:"¥"},euro:{regex:/&(euro|#8364);/g,val:"€"},copyright:{regex:/&(copy|#169);/g,val:"©"},reg:{regex:/&(reg|#174);/g,val:"®"},inr:{regex:/&(inr|#8377);/g,val:"₹"},num_dec:{regex:/&#([0-9]{1,7});/g,val:(e,t)=>String.fromCharCode(Number.parseInt(t,10))},num_hex:{regex:/&#x([0-9a-fA-F]{1,6});/g,val:(e,t)=>String.fromCharCode(Number.parseInt(t,16))}},this.addExternalEntities=l,this.parseXml=f,this.parseTextData=c,this.resolveNameSpace=u,this.buildAttributesMap=d,this.isItStopNode=y,this.replaceEntitiesValue=m,this.readStopNodeData=x,this.saveTextToParentTag=g,this.addChild=h,this.ignoreAttributesFn=a(this.options.ignoreAttributes)}}},2923:function(e,t,n){const{buildOptions:r}=n(460),i=n(7680),{prettify:o}=n(5629),s=n(3918);e.exports=class{constructor(e){this.externalEntities={},this.options=r(e)}parse(e,t){if("string"==typeof e);else{if(!e.toString)throw new Error("XML data is accepted in String or Bytes[] form.");e=e.toString()}if(t){!0===t&&(t={});const n=s.validate(e,t);if(!0!==n)throw Error(`${n.err.msg}:${n.err.line}:${n.err.col}`)}const n=new i(this.options);n.addExternalEntities(this.externalEntities);const r=n.parseXml(e);return this.options.preserveOrder||void 0===r?r:o(r,this.options)}addEntity(e,t){if(-1!==t.indexOf("&"))throw new Error("Entity value can't have '&'");if(-1!==e.indexOf("&")||-1!==e.indexOf(";"))throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for ' '");if("&"===t)throw new Error("An entity with value '&' is not permitted");this.externalEntities[e]=t}}},5629:function(e,t){"use strict";function n(e,t,s){let a;const l={};for(let c=0;c0&&(l[t.textNodeName]=a):void 0!==a&&(l[t.textNodeName]=a),l}function r(e){const t=Object.keys(e);for(let e=0;e0?this.child.push({[e.tagname]:e.child,":@":e[":@"]}):this.child.push({[e.tagname]:e.child})}}},7593:function(e){var t=Object.prototype.hasOwnProperty,n=Object.prototype.toString;e.exports=function(e,r,i){if("[object Function]"!==n.call(r))throw new TypeError("iterator must be a function");var o=e.length;if(o===+o)for(var s=0;s=55296&&r<=56319&&t+1=56320&&n<=57343?1024*(r-55296)+n-56320+65536:r}function H(e){return/^\n* /.test(e)}var Y=1,G=2,Q=3,X=4,K=5;function Z(e,t,n,r,o){e.dump=function(){if(0===t.length)return e.quotingType===D?'""':"''";if(!e.noCompatMode&&(-1!==N.indexOf(t)||$.test(t)))return e.quotingType===D?'"'+t+'"':"'"+t+"'";var s=e.indent*Math.max(1,n),a=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-s),c=r||e.flowLevel>-1&&n>=e.flowLevel;switch(function(e,t,n,r,i,o,s,a){var c,p,d=0,R=null,N=!1,$=!1,L=-1!==r,M=-1,F=U(p=W(e,0))&&p!==l&&!B(p)&&p!==w&&p!==O&&p!==k&&p!==x&&p!==A&&p!==C&&p!==P&&p!==I&&p!==m&&p!==y&&p!==v&&p!==f&&p!==T&&p!==S&&p!==E&&p!==b&&p!==h&&p!==g&&p!==_&&p!==j&&function(e){return!B(e)&&e!==k}(W(e,e.length-1));if(t||s)for(c=0;c=65536?c+=2:c++){if(!U(d=W(e,c)))return K;F=F&&V(d,R,a),R=d}else{for(c=0;c=65536?c+=2:c++){if((d=W(e,c))===u)N=!0,L&&($=$||c-M-1>r&&" "!==e[M+1],M=c);else if(!U(d))return K;F=F&&V(d,R,a),R=d}$=$||L&&c-M-1>r&&" "!==e[M+1]}return N||$?n>9&&H(e)?K:s?o===D?K:G:$?X:Q:!F||s||i(e)?o===D?K:G:Y}(t,c,e.indent,a,(function(t){return function(e,t){var n,r;for(n=0,r=e.implicitTypes.length;n"+J(t,e.indent)+ee(F(function(e,t){for(var n,r,i,o=/(\n+)([^\n]*)/g,s=(i=-1!==(i=e.indexOf("\n"))?i:e.length,o.lastIndex=i,te(e.slice(0,i),t)),a="\n"===e[0]||" "===e[0];r=o.exec(e);){var l=r[1],c=r[2];n=" "===c[0],s+=l+(a||n||""===c?"":"\n")+te(c,t),a=n}return s}(t,a),s));case K:return'"'+function(e){for(var t,n="",r=0,i=0;i=65536?i+=2:i++)r=W(e,i),!(t=R[r])&&U(r)?(n+=e[i],r>=65536&&(n+=e[i+1])):n+=t||L(r);return n}(t)+'"';default:throw new i("impossible error: invalid scalar style")}}()}function J(e,t){var n=H(e)?String(t):"",r="\n"===e[e.length-1];return n+(!r||"\n"!==e[e.length-2]&&"\n"!==e?r?"":"-":"+")+"\n"}function ee(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function te(e,t){if(""===e||" "===e[0])return e;for(var n,r,i=/ [^ ]/g,o=0,s=0,a=0,l="";n=i.exec(e);)(a=n.index)-o>t&&(r=s>o?s:a,l+="\n"+e.slice(o,r),o=r+1),s=a;return l+="\n",e.length-o>t&&s>o?l+=e.slice(o,s)+"\n"+e.slice(s+1):l+=e.slice(o),l.slice(1)}function ne(e,t,n,r){var i,o,s,a="",l=e.tag;for(i=0,o=n.length;i tag resolver accepts not "'+p+'" style');r=u.represent[p](t,p)}e.dump=r}return!0}return!1}function ie(e,t,n,r,o,a,l){e.tag=null,e.dump=n,re(e,n,!1)||re(e,n,!0);var c,p=s.call(e.dump),d=r;r&&(r=e.flowLevel<0||e.flowLevel>t);var f,h,m="[object Object]"===p||"[object Array]"===p;if(m&&(h=-1!==(f=e.duplicates.indexOf(n))),(null!==e.tag&&"?"!==e.tag||h||2!==e.indent&&t>0)&&(o=!1),h&&e.usedDuplicates[f])e.dump="*ref_"+f;else{if(m&&h&&!e.usedDuplicates[f]&&(e.usedDuplicates[f]=!0),"[object Object]"===p)r&&0!==Object.keys(e.dump).length?(function(e,t,n,r){var o,s,a,l,c,p,d="",f=e.tag,h=Object.keys(n);if(!0===e.sortKeys)h.sort();else if("function"==typeof e.sortKeys)h.sort(e.sortKeys);else if(e.sortKeys)throw new i("sortKeys must be a boolean or a function");for(o=0,s=h.length;o1024)&&(e.dump&&u===e.dump.charCodeAt(0)?p+="?":p+="? "),p+=e.dump,c&&(p+=z(e,t)),ie(e,t+1,l,!0,c)&&(e.dump&&u===e.dump.charCodeAt(0)?p+=":":p+=": ",d+=p+=e.dump));e.tag=f,e.dump=d||"{}"}(e,t,e.dump,o),h&&(e.dump="&ref_"+f+e.dump)):(function(e,t,n){var r,i,o,s,a,l="",c=e.tag,u=Object.keys(n);for(r=0,i=u.length;r1024&&(a+="? "),a+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),ie(e,t,s,!1,!1)&&(l+=a+=e.dump));e.tag=c,e.dump="{"+l+"}"}(e,t,e.dump),h&&(e.dump="&ref_"+f+" "+e.dump));else if("[object Array]"===p)r&&0!==e.dump.length?(e.noArrayIndent&&!l&&t>0?ne(e,t-1,e.dump,o):ne(e,t,e.dump,o),h&&(e.dump="&ref_"+f+e.dump)):(function(e,t,n){var r,i,o,s="",a=e.tag;for(r=0,i=n.length;r",e.dump=c+" "+e.dump)}return!0}function oe(e,t){var n,r,i=[],o=[];for(se(e,i,o),n=0,r=o.length;n>10),56320+(e-65536&1023))}for(var C=new Array(256),j=new Array(256),P=0;P<256;P++)C[P]=_(P)?1:0,j[P]=_(P);function T(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||s,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function I(e,t){var n={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart};return n.snippet=o(n),new i(t,n)}function R(e,t){throw I(e,t)}function N(e,t){e.onWarning&&e.onWarning.call(null,I(e,t))}var $={YAML:function(e,t,n){var r,i,o;null!==e.version&&R(e,"duplication of %YAML directive"),1!==n.length&&R(e,"YAML directive accepts exactly one argument"),null===(r=/^([0-9]+)\.([0-9]+)$/.exec(n[0]))&&R(e,"ill-formed argument of the YAML directive"),i=parseInt(r[1],10),o=parseInt(r[2],10),1!==i&&R(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=o<2,1!==o&&2!==o&&N(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var r,i;2!==n.length&&R(e,"TAG directive accepts exactly two arguments"),r=n[0],i=n[1],b.test(r)||R(e,"ill-formed tag handle (first argument) of the TAG directive"),a.call(e.tagMap,r)&&R(e,'there is a previously declared suffix for "'+r+'" tag handle'),v.test(i)||R(e,"ill-formed tag prefix (second argument) of the TAG directive");try{i=decodeURIComponent(i)}catch(t){R(e,"tag prefix is malformed: "+i)}e.tagMap[r]=i}};function L(e,t,n,r){var i,o,s,a;if(t1&&(e.result+=r.repeat("\n",t-1))}function q(e,t){var n,r,i=e.tag,o=e.anchor,s=[],a=!1;if(-1!==e.firstTabInLine)return!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=s),r=e.input.charCodeAt(e.position);0!==r&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,R(e,"tab characters must not be used in indentation")),45===r)&&S(e.input.charCodeAt(e.position+1));)if(a=!0,e.position++,z(e,!0,-1)&&e.lineIndent<=t)s.push(null),r=e.input.charCodeAt(e.position);else if(n=e.line,H(e,t,u,!1,!0),s.push(e.result),z(e,!0,-1),r=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==r)R(e,"bad indentation of a sequence entry");else if(e.lineIndentt?T=1:e.lineIndent===t?T=0:e.lineIndentt?T=1:e.lineIndent===t?T=0:e.lineIndentt)&&(v&&(s=e.line,a=e.lineStart,l=e.position),H(e,t,p,!0,i)&&(v?y=e.result:b=e.result),v||(M(e,h,m,g,y,b,s,a,l),g=y=b=null),z(e,!0,-1),u=e.input.charCodeAt(e.position)),(e.line===o||e.lineIndent>t)&&0!==u)R(e,"bad indentation of a mapping entry");else if(e.lineIndent=0))break;0===o?R(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):u?R(e,"repeat of an indentation width identifier"):(p=t+o-1,u=!0)}if(k(s)){do{s=e.input.charCodeAt(++e.position)}while(k(s));if(35===s)do{s=e.input.charCodeAt(++e.position)}while(!w(s)&&0!==s)}for(;0!==s;){for(F(e),e.lineIndent=0,s=e.input.charCodeAt(e.position);(!u||e.lineIndentp&&(p=e.lineIndent),w(s))m++;else{if(e.lineIndent0){for(i=s,o=0;i>0;i--)(s=O(a=e.input.charCodeAt(++e.position)))>=0?o=(o<<4)+s:R(e,"expected hexadecimal character");e.result+=A(o),e.position++}else R(e,"unknown escape sequence");n=r=e.position}else w(a)?(L(e,n,r,!0),U(e,z(e,!1,t)),n=r=e.position):e.position===e.lineStart&&B(e)?R(e,"unexpected end of the document within a double quoted scalar"):(e.position++,r=e.position)}R(e,"unexpected end of the stream within a double quoted scalar")}(e,_)?N=!0:function(e){var t,n,r;if(42!==(r=e.input.charCodeAt(e.position)))return!1;for(r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!S(r)&&!E(r);)r=e.input.charCodeAt(++e.position);return e.position===t&&R(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),a.call(e.anchorMap,n)||R(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],z(e,!0,-1),!0}(e)?(N=!0,null===e.tag&&null===e.anchor||R(e,"alias node should not have any properties")):function(e,t,n){var r,i,o,s,a,l,c,u,p=e.kind,d=e.result;if(S(u=e.input.charCodeAt(e.position))||E(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1;if((63===u||45===u)&&(S(r=e.input.charCodeAt(e.position+1))||n&&E(r)))return!1;for(e.kind="scalar",e.result="",i=o=e.position,s=!1;0!==u;){if(58===u){if(S(r=e.input.charCodeAt(e.position+1))||n&&E(r))break}else if(35===u){if(S(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&B(e)||n&&E(u))break;if(w(u)){if(a=e.line,l=e.lineStart,c=e.lineIndent,z(e,!1,-1),e.lineIndent>=t){s=!0,u=e.input.charCodeAt(e.position);continue}e.position=o,e.line=a,e.lineStart=l,e.lineIndent=c;break}}s&&(L(e,i,o,!1),U(e,e.line-a),i=o=e.position,s=!1),k(u)||(o=e.position+1),u=e.input.charCodeAt(++e.position)}return L(e,i,o,!1),!!e.result||(e.kind=p,e.result=d,!1)}(e,_,l===n)&&(N=!0,null===e.tag&&(e.tag="?")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===T&&(N=g&&q(e,P))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&R(e,'unacceptable node kind for ! tag; it should be "scalar", not "'+e.kind+'"'),y=0,b=e.implicitTypes.length;y"),null!==e.result&&x.kind!==e.kind&&R(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+x.kind+'", not "'+e.kind+'"'),x.resolve(e.result,e.tag)?(e.result=x.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):R(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||N}function Y(e){var t,n,r,i,o=e.position,s=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);0!==(i=e.input.charCodeAt(e.position))&&(z(e,!0,-1),i=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==i));){for(s=!0,i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!S(i);)i=e.input.charCodeAt(++e.position);for(r=[],(n=e.input.slice(t,e.position)).length<1&&R(e,"directive name must not be less than one character in length");0!==i;){for(;k(i);)i=e.input.charCodeAt(++e.position);if(35===i){do{i=e.input.charCodeAt(++e.position)}while(0!==i&&!w(i));break}if(w(i))break;for(t=e.position;0!==i&&!S(i);)i=e.input.charCodeAt(++e.position);r.push(e.input.slice(t,e.position))}0!==i&&F(e),a.call($,n)?$[n](e,n,r):N(e,'unknown document directive "'+n+'"')}z(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,z(e,!0,-1)):s&&R(e,"directives end mark is expected"),H(e,e.lineIndent-1,p,!1,!0),z(e,!0,-1),e.checkLineBreaks&&g.test(e.input.slice(o,e.position))&&N(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&B(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,z(e,!0,-1)):e.positiona&&(t=r-a+(o=" ... ").length),n-r>a&&(n=r+a-(s=" ...").length),{str:o+e.slice(t,n).replace(/\t/g,"→")+s,pos:r-t+o.length}}function o(e,t){return r.repeat(" ",t-e.length)+e}e.exports=function(e,t){if(t=Object.create(t||null),!e.buffer)return null;t.maxLength||(t.maxLength=79),"number"!=typeof t.indent&&(t.indent=1),"number"!=typeof t.linesBefore&&(t.linesBefore=3),"number"!=typeof t.linesAfter&&(t.linesAfter=2);for(var n,s=/\r?\n|\r|\0/g,a=[0],l=[],c=-1;n=s.exec(e.buffer);)l.push(n.index),a.push(n.index+n[0].length),e.position<=n.index&&c<0&&(c=a.length-2);c<0&&(c=a.length-1);var u,p,d="",f=Math.min(e.line+t.linesAfter,l.length).toString().length,h=t.maxLength-(t.indent+f+3);for(u=1;u<=t.linesBefore&&!(c-u<0);u++)p=i(e.buffer,a[c-u],l[c-u],e.position-(a[c]-a[c-u]),h),d=r.repeat(" ",t.indent)+o((e.line-u+1).toString(),f)+" | "+p.str+"\n"+d;for(p=i(e.buffer,a[c],l[c],e.position,h),d+=r.repeat(" ",t.indent)+o((e.line+1).toString(),f)+" | "+p.str+"\n",d+=r.repeat("-",t.indent+f+3+p.pos)+"^\n",u=1;u<=t.linesAfter&&!(c+u>=l.length);u++)p=i(e.buffer,a[c+u],l[c+u],e.position-(a[c]-a[c+u]),h),d+=r.repeat(" ",t.indent)+o((e.line+u+1).toString(),f)+" | "+p.str+"\n";return d.replace(/\n$/,"")}},5388:function(e,t,n){"use strict";var r=n(1231),i=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],o=["scalar","sequence","mapping"];e.exports=function(e,t){var n,s;if(t=t||{},Object.keys(t).forEach((function(t){if(-1===i.indexOf(t))throw new r('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')})),this.options=t,this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.representName=t.representName||null,this.defaultStyle=t.defaultStyle||null,this.multi=t.multi||!1,this.styleAliases=(n=t.styleAliases||null,s={},null!==n&&Object.keys(n).forEach((function(e){n[e].forEach((function(t){s[String(t)]=e}))})),s),-1===o.indexOf(this.kind))throw new r('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')}},9342:function(e,t,n){"use strict";var r=n(5388),i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";e.exports=new r("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,r=0,o=e.length,s=i;for(n=0;n64)){if(t<0)return!1;r+=6}return r%8==0},construct:function(e){var t,n,r=e.replace(/[\r\n=]/g,""),o=r.length,s=i,a=0,l=[];for(t=0;t>16&255),l.push(a>>8&255),l.push(255&a)),a=a<<6|s.indexOf(r.charAt(t));return 0==(n=o%4*6)?(l.push(a>>16&255),l.push(a>>8&255),l.push(255&a)):18===n?(l.push(a>>10&255),l.push(a>>2&255)):12===n&&l.push(a>>4&255),new Uint8Array(l)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){var t,n,r="",o=0,s=e.length,a=i;for(t=0;t>18&63],r+=a[o>>12&63],r+=a[o>>6&63],r+=a[63&o]),o=(o<<8)+e[t];return 0==(n=s%3)?(r+=a[o>>18&63],r+=a[o>>12&63],r+=a[o>>6&63],r+=a[63&o]):2===n?(r+=a[o>>10&63],r+=a[o>>4&63],r+=a[o<<2&63],r+=a[64]):1===n&&(r+=a[o>>2&63],r+=a[o<<4&63],r+=a[64],r+=a[64]),r}})},6199:function(e,t,n){"use strict";var r=n(5388);e.exports=new r("tag:yaml.org,2002:bool",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t=e.length;return 4===t&&("true"===e||"True"===e||"TRUE"===e)||5===t&&("false"===e||"False"===e||"FALSE"===e)},construct:function(e){return"true"===e||"True"===e||"TRUE"===e},predicate:function(e){return"[object Boolean]"===Object.prototype.toString.call(e)},represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"})},1461:function(e,t,n){"use strict";var r=n(8433),i=n(5388),o=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"),s=/^[-+]?[0-9]+e/;e.exports=new i("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&!(!o.test(e)||"_"===e[e.length-1])},construct:function(e){var t,n;return n="-"===(t=e.replace(/_/g,"").toLowerCase())[0]?-1:1,"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:n*parseFloat(t,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!=0||r.isNegativeZero(e))},represent:function(e,t){var n;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(r.isNegativeZero(e))return"-0.0";return n=e.toString(10),s.test(n)?n.replace("e",".e"):n},defaultStyle:"lowercase"})},4466:function(e,t,n){"use strict";var r=n(8433),i=n(5388);function o(e){return 48<=e&&e<=55}function s(e){return 48<=e&&e<=57}e.exports=new i("tag:yaml.org,2002:int",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,r=e.length,i=0,a=!1;if(!r)return!1;if("-"!==(t=e[i])&&"+"!==t||(t=e[++i]),"0"===t){if(i+1===r)return!0;if("b"===(t=e[++i])){for(i++;i=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})},2369:function(e,t,n){"use strict";var r=n(5388);e.exports=new r("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return null!==e?e:{}}})},1851:function(e,t,n){"use strict";var r=n(5388);e.exports=new r("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(e){return"<<"===e||null===e}})},9198:function(e,t,n){"use strict";var r=n(5388);e.exports=new r("tag:yaml.org,2002:null",{kind:"scalar",resolve:function(e){if(null===e)return!0;var t=e.length;return 1===t&&"~"===e||4===t&&("null"===e||"Null"===e||"NULL"===e)},construct:function(){return null},predicate:function(e){return null===e},represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"},empty:function(){return""}},defaultStyle:"lowercase"})},6946:function(e,t,n){"use strict";var r=n(5388),i=Object.prototype.hasOwnProperty,o=Object.prototype.toString;e.exports=new r("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null===e)return!0;var t,n,r,s,a,l=[],c=e;for(t=0,n=c.length;tc))return!1;var p=a.get(e);if(p&&a.get(t))return p==t;var d=-1,f=!0,h=n&o?new Ae:void 0;for(a.set(e,t),a.set(t,e);++d-1},Oe.prototype.set=function(e,t){var n=this.__data__,r=je(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},_e.prototype.clear=function(){this.size=0,this.__data__={hash:new Ee,map:new(de||Oe),string:new Ee}},_e.prototype.delete=function(e){var t=$e(this,e).delete(e);return this.size-=t?1:0,t},_e.prototype.get=function(e){return $e(this,e).get(e)},_e.prototype.has=function(e){return $e(this,e).has(e)},_e.prototype.set=function(e,t){var n=$e(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},Ae.prototype.add=Ae.prototype.push=function(e){return this.__data__.set(e,r),this},Ae.prototype.has=function(e){return this.__data__.has(e)},Ce.prototype.clear=function(){this.__data__=new Oe,this.size=0},Ce.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},Ce.prototype.get=function(e){return this.__data__.get(e)},Ce.prototype.has=function(e){return this.__data__.has(e)},Ce.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Oe){var r=n.__data__;if(!de||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new _e(r)}return n.set(e,t),this.size=n.size,this};var De=le?function(e){return null==e?[]:(e=Object(e),function(t){for(var n=-1,r=null==t?0:t.length,i=0,o=[];++n-1&&e%1==0&&e-1&&e%1==0&&e<=s}function Ye(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function Ge(e){return null!=e&&"object"==typeof e}var Qe=F?function(e){return function(t){return e(t)}}(F):function(e){return Ge(e)&&He(e.length)&&!!P[Pe(e)]};function Xe(e){return null!=(t=e)&&He(t.length)&&!We(t)?function(e,t){var n=qe(e),r=!n&&Ue(e),i=!n&&!r&&Ve(e),o=!n&&!r&&!i&&Qe(e),s=n||r||i||o,a=s?function(e,t){for(var n=-1,r=Array(e);++n1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;t(this,e),this.ctx=n,this.iframes=r,this.exclude=i,this.iframesTimeout=o}return n(e,[{key:"getContexts",value:function(){var e=[];return(void 0!==this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(document.querySelectorAll(this.ctx)):[this.ctx]:[]).forEach((function(t){var n=e.filter((function(e){return e.contains(t)})).length>0;-1!==e.indexOf(t)||n||e.push(t)})),e}},{key:"getIframeContents",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var i=e.contentWindow;if(r=i.document,!i||!r)throw new Error("iframe inaccessible")}catch(e){n()}r&&t(r)}},{key:"isIframeBlank",value:function(e){var t="about:blank",n=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&n!==t&&n}},{key:"observeIframeLoad",value:function(e,t,n){var r=this,i=!1,o=null,s=function s(){if(!i){i=!0,clearTimeout(o);try{r.isIframeBlank(e)||(e.removeEventListener("load",s),r.getIframeContents(e,t,n))}catch(e){n()}}};e.addEventListener("load",s),o=setTimeout(s,this.iframesTimeout)}},{key:"onIframeReady",value:function(e,t,n){try{"complete"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(e){n()}}},{key:"waitForIframes",value:function(e,t){var n=this,r=0;this.forEachIframe(e,(function(){return!0}),(function(e){r++,n.waitForIframes(e.querySelector("html"),(function(){--r||t()}))}),(function(e){e||t()}))}},{key:"forEachIframe",value:function(t,n,r){var i=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},s=t.querySelectorAll("iframe"),a=s.length,l=0;s=Array.prototype.slice.call(s);var c=function(){--a<=0&&o(l)};a||c(),s.forEach((function(t){e.matches(t,i.exclude)?c():i.onIframeReady(t,(function(e){n(t)&&(l++,r(e)),c()}),c)}))}},{key:"createIterator",value:function(e,t,n){return document.createNodeIterator(e,t,n,!1)}},{key:"createInstanceOnIframe",value:function(t){return new e(t.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(e,t,n){if(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_PRECEDING){if(null===t)return!0;if(t.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)return!0}return!1}},{key:"getIteratorNode",value:function(e){var t=e.previousNode();return{prevNode:t,node:(null===t||e.nextNode())&&e.nextNode()}}},{key:"checkIframeFilter",value:function(e,t,n,r){var i=!1,o=!1;return r.forEach((function(e,t){e.val===n&&(i=t,o=e.handled)})),this.compareNodeIframe(e,t,n)?(!1!==i||o?!1===i||o||(r[i].handled=!0):r.push({val:n,handled:!0}),!0):(!1===i&&r.push({val:n,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(e,t,n,r){var i=this;e.forEach((function(e){e.handled||i.getIframeContents(e.val,(function(e){i.createInstanceOnIframe(e).forEachNode(t,n,r)}))}))}},{key:"iterateThroughNodes",value:function(e,t,n,r,i){for(var o=this,s=this.createIterator(t,e,r),a=[],l=[],c=void 0,u=void 0;p=void 0,p=o.getIteratorNode(s),u=p.prevNode,c=p.node;)this.iframes&&this.forEachIframe(t,(function(e){return o.checkIframeFilter(c,u,e,a)}),(function(t){o.createInstanceOnIframe(t).forEachNode(e,(function(e){return l.push(e)}),r)})),l.push(c);var p;l.forEach((function(e){n(e)})),this.iframes&&this.handleOpenIframes(a,e,n,r),i()}},{key:"forEachNode",value:function(e,t,n){var r=this,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},o=this.getContexts(),s=o.length;s||i(),o.forEach((function(o){var a=function(){r.iterateThroughNodes(e,o,t,n,(function(){--s<=0&&i()}))};r.iframes?r.waitForIframes(o,a):a()}))}}],[{key:"matches",value:function(e,t){var n="string"==typeof t?[t]:t,r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(r){var i=!1;return n.every((function(t){return!r.call(e,t)||(i=!0,!1)})),i}return!1}}]),e}(),o=function(){function o(e){t(this,o),this.ctx=e,this.ie=!1;var n=window.navigator.userAgent;(n.indexOf("MSIE")>-1||n.indexOf("Trident")>-1)&&(this.ie=!0)}return n(o,[{key:"log",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",r=this.opt.log;this.opt.debug&&"object"===(void 0===r?"undefined":e(r))&&"function"==typeof r[n]&&r[n]("mark.js: "+t)}},{key:"escapeStr",value:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createRegExp",value:function(e){return"disabled"!==this.opt.wildcards&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),"disabled"!==this.opt.wildcards&&(e=this.createWildcardsRegExp(e)),this.createAccuracyRegExp(e)}},{key:"createSynonymsRegExp",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i",r=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(var i in t)if(t.hasOwnProperty(i)){var o=t[i],s="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(i):this.escapeStr(i),a="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(o):this.escapeStr(o);""!==s&&""!==a&&(e=e.replace(new RegExp("("+this.escapeStr(s)+"|"+this.escapeStr(a)+")","gm"+n),r+"("+this.processSynomyms(s)+"|"+this.processSynomyms(a)+")"+r))}return e}},{key:"processSynomyms",value:function(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}},{key:"setupWildcardsRegExp",value:function(e){return(e=e.replace(/(?:\\)*\?/g,(function(e){return"\\"===e.charAt(0)?"?":""}))).replace(/(?:\\)*\*/g,(function(e){return"\\"===e.charAt(0)?"*":""}))}},{key:"createWildcardsRegExp",value:function(e){var t="withSpaces"===this.opt.wildcards;return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}},{key:"setupIgnoreJoinersRegExp",value:function(e){return e.replace(/[^(|)\\]/g,(function(e,t,n){var r=n.charAt(t+1);return/[(|)\\]/.test(r)||""===r?e:e+"\0"}))}},{key:"createJoinersRegExp",value:function(e){var t=[],n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join("["+t.join("")+"]*"):e}},{key:"createDiacriticsRegExp",value:function(e){var t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"],r=[];return e.split("").forEach((function(i){n.every((function(n){if(-1!==n.indexOf(i)){if(r.indexOf(n)>-1)return!1;e=e.replace(new RegExp("["+n+"]","gm"+t),"["+n+"]"),r.push(n)}return!0}))})),e}},{key:"createMergedBlanksRegExp",value:function(e){return e.replace(/[\s]+/gim,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(e){var t=this,n=this.opt.accuracy,r="string"==typeof n?n:n.value,i="string"==typeof n?[]:n.limiters,o="";switch(i.forEach((function(e){o+="|"+t.escapeStr(e)})),r){case"partially":default:return"()("+e+")";case"complementary":return"()([^"+(o="\\s"+(o||this.escapeStr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿")))+"]*"+e+"[^"+o+"]*)";case"exactly":return"(^|\\s"+o+")("+e+")(?=$|\\s"+o+")"}}},{key:"getSeparatedKeywords",value:function(e){var t=this,n=[];return e.forEach((function(e){t.opt.separateWordSearch?e.split(" ").forEach((function(e){e.trim()&&-1===n.indexOf(e)&&n.push(e)})):e.trim()&&-1===n.indexOf(e)&&n.push(e)})),{keywords:n.sort((function(e,t){return t.length-e.length})),length:n.length}}},{key:"isNumeric",value:function(e){return Number(parseFloat(e))==e}},{key:"checkRanges",value:function(e){var t=this;if(!Array.isArray(e)||"[object Object]"!==Object.prototype.toString.call(e[0]))return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];var n=[],r=0;return e.sort((function(e,t){return e.start-t.start})).forEach((function(e){var i=t.callNoMatchOnInvalidRanges(e,r),o=i.start,s=i.end;i.valid&&(e.start=o,e.length=s-o,n.push(e),r=s)})),n}},{key:"callNoMatchOnInvalidRanges",value:function(e,t){var n=void 0,r=void 0,i=!1;return e&&void 0!==e.start?(r=(n=parseInt(e.start,10))+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&r-t>0&&r-n>0?i=!0:(this.log("Ignoring invalid or overlapping range: "+JSON.stringify(e)),this.opt.noMatch(e))):(this.log("Ignoring invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:n,end:r,valid:i}}},{key:"checkWhitespaceRanges",value:function(e,t,n){var r=void 0,i=!0,o=n.length,s=t-o,a=parseInt(e.start,10)-s;return(r=(a=a>o?o:a)+parseInt(e.length,10))>o&&(r=o,this.log("End range automatically set to the max value of "+o)),a<0||r-a<0||a>o||r>o?(i=!1,this.log("Invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)):""===n.substring(a,r).replace(/\s+/g,"")&&(i=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:a,end:r,valid:i}}},{key:"getTextNodes",value:function(e){var t=this,n="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,(function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})}),(function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}),(function(){e({value:n,nodes:r})}))}},{key:"matchesExclude",value:function(e){return i.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(e,t,n){var r=this.opt.element?this.opt.element:"mark",i=e.splitText(t),o=i.splitText(n-t),s=document.createElement(r);return s.setAttribute("data-markjs","true"),this.opt.className&&s.setAttribute("class",this.opt.className),s.textContent=i.textContent,i.parentNode.replaceChild(s,i),o}},{key:"wrapRangeInMappedTextNode",value:function(e,t,n,r,i){var o=this;e.nodes.every((function(s,a){var l=e.nodes[a+1];if(void 0===l||l.start>t){if(!r(s.node))return!1;var c=t-s.start,u=(n>s.end?s.end:n)-s.start,p=e.value.substr(0,s.start),d=e.value.substr(u+s.start);if(s.node=o.wrapRangeInTextNode(s.node,c,u),e.value=p+d,e.nodes.forEach((function(t,n){n>=a&&(e.nodes[n].start>0&&n!==a&&(e.nodes[n].start-=u),e.nodes[n].end-=u)})),n-=u,i(s.node.previousSibling,s.start),!(n>s.end))return!1;t=s.end}return!0}))}},{key:"wrapMatches",value:function(e,t,n,r,i){var o=this,s=0===t?0:t+1;this.getTextNodes((function(t){t.nodes.forEach((function(t){t=t.node;for(var i=void 0;null!==(i=e.exec(t.textContent))&&""!==i[s];)if(n(i[s],t)){var a=i.index;if(0!==s)for(var l=1;l1&&console.warn("Replacing with",t),m++}}else{let i=u(l(t,e[n]));if(s.verbose>1&&console.warn((!1===i?f.colour.red:f.colour.green)+"Fragment resolution",e[n],f.colour.normal),!1===i){if(r.parent[r.pkey]={},s.fatal){let t=new Error("Fragment $ref resolution failed "+e[n]);if(!s.promise)throw t;s.promise.reject(t)}}else m++,r.parent[r.pkey]=i,h[e[n]]=r.path.replace("/%24ref","")}else if(p.protocol){let t=o.resolve(i,e[n]).toString();s.verbose>1&&console.warn(f.colour.yellow+"Rewriting external url ref",e[n],"as",t,f.colour.normal),e["x-miro"]=e[n],s.externalRefs[e[n]]&&(s.externalRefs[t]||(s.externalRefs[t]=s.externalRefs[e[n]]),s.externalRefs[t].failed=s.externalRefs[e[n]].failed),e[n]=t}else if(!e["x-miro"]){let t=o.resolve(i,e[n]).toString(),r=!1;s.externalRefs[e[n]]&&(r=s.externalRefs[e[n]].failed),r||(s.verbose>1&&console.warn(f.colour.yellow+"Rewriting external ref",e[n],"as",t,f.colour.normal),e["x-miro"]=e[n],e[n]=t)}}));return c(e,{},(function(e,t,n){d(e,t)&&void 0!==e.$fixed&&delete e.$fixed})),s.verbose>1&&console.warn("Finished fragment resolution"),e}function m(e,t){if(!t.filters||!t.filters.length)return e;for(let n of t.filters)e=n(e,t);return e}function g(e,t,n,s){var c=o.parse(n.source),p=n.source.split("\\").join("/").split("/");p.pop()||p.pop();let d="",f=t.split("#");f.length>1&&(d="#"+f[1],t=f[0]),p=p.join("/");let g=(y=o.parse(t).protocol,b=c.protocol,y&&y.length>2?y:b&&b.length>2?b:"file:");var y,b;let v;if(v="file:"===g?i.resolve(p?p+"/":"",t):o.resolve(p?p+"/":"",t),n.cache[v]){n.verbose&&console.warn("CACHED",v,d);let e=u(n.cache[v]),r=n.externalRef=e;if(d&&(r=l(r,d),!1===r&&(r={},n.fatal))){let e=new Error("Cached $ref resolution failed "+v+d);if(!n.promise)throw e;n.promise.reject(e)}return r=h(r,e,t,d,v,n),r=m(r,n),s(u(r),v,n),Promise.resolve(r)}if(n.verbose&&console.warn("GET",v,d),n.handlers&&n.handlers[g])return n.handlers[g](p,t,d,n).then((function(e){return n.externalRef=e,e=m(e,n),n.cache[v]=e,s(e,v,n),e})).catch((function(e){throw n.verbose&&console.warn(e),e}));if(g&&g.startsWith("http")){const e=Object.assign({},n.fetchOptions,{agent:n.agent});return n.fetch(v,e).then((function(e){if(200!==e.status){if(n.ignoreIOErrors)return n.verbose&&console.warn("FAILED",t),n.externalRefs[t].failed=!0,'{"$ref":"'+t+'"}';throw new Error(`Received status code ${e.status}: ${v}`)}return e.text()})).then((function(e){try{let r=a.parse(e,{schema:"core",prettyErrors:!0});if(e=n.externalRef=r,n.cache[v]=u(e),d&&!1===(e=l(e,d))&&(e={},n.fatal)){let e=new Error("Remote $ref resolution failed "+v+d);if(!n.promise)throw e;n.promise.reject(e)}e=m(e=h(e,r,t,d,v,n),n)}catch(e){if(n.verbose&&console.warn(e),!n.promise||!n.fatal)throw e;n.promise.reject(e)}return s(e,v,n),e})).catch((function(e){if(n.verbose&&console.warn(e),n.cache[v]={},!n.promise||!n.fatal)throw e;n.promise.reject(e)}))}{const e='{"$ref":"'+t+'"}';return function(e,t,n,i,o){return new Promise((function(s,a){r.readFile(e,t,(function(e,t){e?n.ignoreIOErrors&&o?(n.verbose&&console.warn("FAILED",i),n.externalRefs[i].failed=!0,s(o)):a(e):s(t)}))}))}(v,n.encoding||"utf8",n,t,e).then((function(e){try{let r=a.parse(e,{schema:"core",prettyErrors:!0});if(e=n.externalRef=r,n.cache[v]=u(e),d&&!1===(e=l(e,d))&&(e={},n.fatal)){let e=new Error("File $ref resolution failed "+v+d);if(!n.promise)throw e;n.promise.reject(e)}e=m(e=h(e,r,t,d,v,n),n)}catch(e){if(n.verbose&&console.warn(e),!n.promise||!n.fatal)throw e;n.promise.reject(e)}return s(e,v,n),e})).catch((function(e){if(n.verbose&&console.warn(e),!n.promise||!n.fatal)throw e;n.promise.reject(e)}))}}function y(e){return new Promise((function(t,n){(function(e){return new Promise((function(t,n){function r(t,n,r){if(t[n]&&d(t[n],"$ref")){let o=t[n].$ref;if(!o.startsWith("#")){let s="";if(!i[o]){let t=Object.keys(i).find((function(e,t,n){return o.startsWith(e+"/")}));t&&(e.verbose&&console.warn("Found potential subschema at",t),s="/"+(o.split("#")[1]||"").replace(t.split("#")[1]||""),s=s.split("/undefined").join(""),o=t)}if(i[o]||(i[o]={resolved:!1,paths:[],extras:{},description:t[n].description}),i[o].resolved)if(i[o].failed);else if(e.rewriteRefs){let r=i[o].resolvedAt;e.verbose>1&&console.warn("Rewriting ref",o,r),t[n]["x-miro"]=o,t[n].$ref=r+s}else t[n]=u(i[o].data);else i[o].paths.push(r.path),i[o].extras[r.path]=s}}}let i=e.externalRefs;if(e.resolver.depth>0&&e.source===e.resolver.base)return t(i);c(e.openapi.definitions,{identityDetection:!0,path:"#/definitions"},r),c(e.openapi.components,{identityDetection:!0,path:"#/components"},r),c(e.openapi,{identityDetection:!0},r),t(i)}))})(e).then((function(t){for(let n in t)if(!t[n].resolved){let r=e.resolver.depth;r>0&&r++,e.resolver.actions[r].push((function(){return g(e.openapi,n,e,(function(e,r,i){if(!t[n].resolved){let o={};o.context=t[n],o.$ref=n,o.original=u(e),o.updated=e,o.source=r,i.externals.push(o),t[n].resolved=!0}let o=Object.assign({},i,{source:"",resolver:{actions:i.resolver.actions,depth:i.resolver.actions.length-1,base:i.resolver.base}});i.patch&&t[n].description&&!e.description&&"object"==typeof e&&(e.description=t[n].description),t[n].data=e;let s=(a=t[n].paths,[...new Set(a)]);var a;s=s.sort((function(e,t){const n=e.startsWith("#/components/")||e.startsWith("#/definitions/"),r=t.startsWith("#/components/")||t.startsWith("#/definitions/");return n&&!r?-1:r&&!n?1:0}));for(let r of s)if(t[n].resolvedAt&&r!==t[n].resolvedAt&&r.indexOf("x-ms-examples/")<0)i.verbose>1&&console.warn("Creating pointer to data at",r),l(i.openapi,r,{$ref:t[n].resolvedAt+t[n].extras[r],"x-miro":n+t[n].extras[r]});else{t[n].resolvedAt?i.verbose>1&&console.warn("Avoiding circular reference"):(t[n].resolvedAt=r,i.verbose>1&&console.warn("Creating initial clone of data at",r));let o=u(e);l(i.openapi,r,o)}0===i.resolver.actions[o.resolver.depth].length&&i.resolver.actions[o.resolver.depth].push((function(){return y(o)}))}))}))}})).catch((function(t){e.verbose&&console.warn(t),n(t)}));let r={options:e};r.actions=e.resolver.actions[e.resolver.depth],t(r)}))}function b(e,t,n){e.resolver.actions.push([]),y(e).then((function(r){var i;(i=r.actions,i.reduce(((e,t)=>e.then((e=>t().then(Array.prototype.concat.bind(e))))),Promise.resolve([]))).then((function(){if(e.resolver.depth>=e.resolver.actions.length)return console.warn("Ran off the end of resolver actions"),t(!0);e.resolver.depth++,e.resolver.actions[e.resolver.depth].length?setTimeout((function(){b(r.options,t,n)}),0):(e.verbose>1&&console.warn(f.colour.yellow+"Finished external resolution!",f.colour.normal),e.resolveInternal&&(e.verbose>1&&console.warn(f.colour.yellow+"Starting internal resolution!",f.colour.normal),e.openapi=p(e.openapi,e.original,{verbose:e.verbose-1}),e.verbose>1&&console.warn(f.colour.yellow+"Finished internal resolution!",f.colour.normal)),c(e.openapi,{},(function(t,n,r){d(t,n)&&(e.preserveMiro||delete t["x-miro"])})),t(e))})).catch((function(t){e.verbose&&console.warn(t),n(t)}))})).catch((function(t){e.verbose&&console.warn(t),n(t)}))}function v(e){if(e.cache||(e.cache={}),e.fetch||(e.fetch=s),e.source){let t=o.parse(e.source);(!t.protocol||t.protocol.length<=2)&&(e.source=i.resolve(e.source))}e.externals=[],e.externalRefs={},e.rewriteRefs=!0,e.resolver={},e.resolver.depth=0,e.resolver.base=e.source,e.resolver.actions=[[]]}e.exports={optionalResolve:function(e){return v(e),new Promise((function(t,n){e.resolve?b(e,t,n):t(e)}))},resolve:function(e,t,n){return n||(n={}),n.openapi=e,n.source=t,n.resolve=!0,v(n),new Promise((function(e,t){b(n,e,t)}))}}},1319:function(e){"use strict";function t(){return{depth:0,seen:new WeakMap,top:!0,combine:!1,allowRefSiblings:!1}}e.exports={getDefaultState:t,walkSchema:function e(n,r,i,o){if(void 0===i.depth&&(i=t()),null==n)return n;if(void 0!==n.$ref){let e={$ref:n.$ref};return i.allowRefSiblings&&n.description&&(e.description=n.description),o(e,r,i),e}if(i.combine&&(n.allOf&&Array.isArray(n.allOf)&&1===n.allOf.length&&delete(n=Object.assign({},n.allOf[0],n)).allOf,n.anyOf&&Array.isArray(n.anyOf)&&1===n.anyOf.length&&delete(n=Object.assign({},n.anyOf[0],n)).anyOf,n.oneOf&&Array.isArray(n.oneOf)&&1===n.oneOf.length&&delete(n=Object.assign({},n.oneOf[0],n)).oneOf),o(n,r,i),i.seen.has(n))return n;if("object"==typeof n&&null!==n&&i.seen.set(n,!0),i.top=!1,i.depth++,void 0!==n.items&&(i.property="items",e(n.items,n,i,o)),n.additionalItems&&"object"==typeof n.additionalItems&&(i.property="additionalItems",e(n.additionalItems,n,i,o)),n.additionalProperties&&"object"==typeof n.additionalProperties&&(i.property="additionalProperties",e(n.additionalProperties,n,i,o)),n.properties)for(let t in n.properties){let r=n.properties[t];i.property="properties/"+t,e(r,n,i,o)}if(n.patternProperties)for(let t in n.patternProperties){let r=n.patternProperties[t];i.property="patternProperties/"+t,e(r,n,i,o)}if(n.allOf)for(let t in n.allOf){let r=n.allOf[t];i.property="allOf/"+t,e(r,n,i,o)}if(n.anyOf)for(let t in n.anyOf){let r=n.anyOf[t];i.property="anyOf/"+t,e(r,n,i,o)}if(n.oneOf)for(let t in n.oneOf){let r=n.oneOf[t];i.property="oneOf/"+t,e(r,n,i,o)}return n.not&&(i.property="not",e(n.not,n,i,o)),i.depth--,n}}},7975:function(e){"use strict";function t(e){if("string"!=typeof e)throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}function n(e,t){for(var n,r="",i=0,o=-1,s=0,a=0;a<=e.length;++a){if(a2){var l=r.lastIndexOf("/");if(l!==r.length-1){-1===l?(r="",i=0):i=(r=r.slice(0,l)).length-1-r.lastIndexOf("/"),o=a,s=0;continue}}else if(2===r.length||1===r.length){r="",i=0,o=a,s=0;continue}t&&(r.length>0?r+="/..":r="..",i=2)}else r.length>0?r+="/"+e.slice(o+1,a):r=e.slice(o+1,a),i=a-o-1;o=a,s=0}else 46===n&&-1!==s?++s:s=-1}return r}var r={resolve:function(){for(var e,r="",i=!1,o=arguments.length-1;o>=-1&&!i;o--){var s;o>=0?s=arguments[o]:(void 0===e&&(e=process.cwd()),s=e),t(s),0!==s.length&&(r=s+"/"+r,i=47===s.charCodeAt(0))}return r=n(r,!i),i?r.length>0?"/"+r:"/":r.length>0?r:"."},normalize:function(e){if(t(e),0===e.length)return".";var r=47===e.charCodeAt(0),i=47===e.charCodeAt(e.length-1);return 0!==(e=n(e,!r)).length||r||(e="."),e.length>0&&i&&(e+="/"),r?"/"+e:e},isAbsolute:function(e){return t(e),e.length>0&&47===e.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var e,n=0;n0&&(void 0===e?e=i:e+="/"+i)}return void 0===e?".":r.normalize(e)},relative:function(e,n){if(t(e),t(n),e===n)return"";if((e=r.resolve(e))===(n=r.resolve(n)))return"";for(var i=1;ic){if(47===n.charCodeAt(a+p))return n.slice(a+p+1);if(0===p)return n.slice(a+p)}else s>c&&(47===e.charCodeAt(i+p)?u=p:0===p&&(u=0));break}var d=e.charCodeAt(i+p);if(d!==n.charCodeAt(a+p))break;47===d&&(u=p)}var f="";for(p=i+u+1;p<=o;++p)p!==o&&47!==e.charCodeAt(p)||(0===f.length?f+="..":f+="/..");return f.length>0?f+n.slice(a+u):(a+=u,47===n.charCodeAt(a)&&++a,n.slice(a))},_makeLong:function(e){return e},dirname:function(e){if(t(e),0===e.length)return".";for(var n=e.charCodeAt(0),r=47===n,i=-1,o=!0,s=e.length-1;s>=1;--s)if(47===(n=e.charCodeAt(s))){if(!o){i=s;break}}else o=!1;return-1===i?r?"/":".":r&&1===i?"//":e.slice(0,i)},basename:function(e,n){if(void 0!==n&&"string"!=typeof n)throw new TypeError('"ext" argument must be a string');t(e);var r,i=0,o=-1,s=!0;if(void 0!==n&&n.length>0&&n.length<=e.length){if(n.length===e.length&&n===e)return"";var a=n.length-1,l=-1;for(r=e.length-1;r>=0;--r){var c=e.charCodeAt(r);if(47===c){if(!s){i=r+1;break}}else-1===l&&(s=!1,l=r+1),a>=0&&(c===n.charCodeAt(a)?-1==--a&&(o=r):(a=-1,o=l))}return i===o?o=l:-1===o&&(o=e.length),e.slice(i,o)}for(r=e.length-1;r>=0;--r)if(47===e.charCodeAt(r)){if(!s){i=r+1;break}}else-1===o&&(s=!1,o=r+1);return-1===o?"":e.slice(i,o)},extname:function(e){t(e);for(var n=-1,r=0,i=-1,o=!0,s=0,a=e.length-1;a>=0;--a){var l=e.charCodeAt(a);if(47!==l)-1===i&&(o=!1,i=a+1),46===l?-1===n?n=a:1!==s&&(s=1):-1!==n&&(s=-1);else if(!o){r=a+1;break}}return-1===n||-1===i||0===s||1===s&&n===i-1&&n===r+1?"":e.slice(n,i)},format:function(e){if(null===e||"object"!=typeof e)throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof e);return function(e,t){var n=t.dir||t.root,r=t.base||(t.name||"")+(t.ext||"");return n?n===t.root?n+r:n+"/"+r:r}(0,e)},parse:function(e){t(e);var n={root:"",dir:"",base:"",ext:"",name:""};if(0===e.length)return n;var r,i=e.charCodeAt(0),o=47===i;o?(n.root="/",r=1):r=0;for(var s=-1,a=0,l=-1,c=!0,u=e.length-1,p=0;u>=r;--u)if(47!==(i=e.charCodeAt(u)))-1===l&&(c=!1,l=u+1),46===i?-1===s?s=u:1!==p&&(p=1):-1!==s&&(p=-1);else if(!c){a=u+1;break}return-1===s||-1===l||0===p||1===p&&s===l-1&&s===a+1?-1!==l&&(n.base=n.name=0===a&&o?e.slice(1,l):e.slice(a,l)):(0===a&&o?(n.name=e.slice(1,s),n.base=e.slice(1,l)):(n.name=e.slice(a,s),n.base=e.slice(a,l)),n.ext=e.slice(s,l)),a>0?n.dir=e.slice(0,a-1):o&&(n.dir="/"),n},sep:"/",delimiter:":",win32:null,posix:null};r.posix=r,e.exports=r},5127:function(e){e.exports=function(){var e=[],t=[],n={},r={},i={};function o(e){return"string"==typeof e?new RegExp("^"+e+"$","i"):e}function s(e,t){return e===t?t:e===e.toLowerCase()?t.toLowerCase():e===e.toUpperCase()?t.toUpperCase():e[0]===e[0].toUpperCase()?t.charAt(0).toUpperCase()+t.substr(1).toLowerCase():t.toLowerCase()}function a(e,t){return e.replace(t[0],(function(n,r){var i,o,a=(i=t[1],o=arguments,i.replace(/\$(\d{1,2})/g,(function(e,t){return o[t]||""})));return s(""===n?e[r-1]:n,a)}))}function l(e,t,r){if(!e.length||n.hasOwnProperty(e))return t;for(var i=r.length;i--;){var o=r[i];if(o[0].test(t))return a(t,o)}return t}function c(e,t,n){return function(r){var i=r.toLowerCase();return t.hasOwnProperty(i)?s(r,i):e.hasOwnProperty(i)?s(r,e[i]):l(i,r,n)}}function u(e,t,n,r){return function(r){var i=r.toLowerCase();return!!t.hasOwnProperty(i)||!e.hasOwnProperty(i)&&l(i,i,n)===i}}function p(e,t,n){return(n?t+" ":"")+(1===t?p.singular(e):p.plural(e))}return p.plural=c(i,r,e),p.isPlural=u(i,r,e),p.singular=c(r,i,t),p.isSingular=u(r,i,t),p.addPluralRule=function(t,n){e.push([o(t),n])},p.addSingularRule=function(e,n){t.push([o(e),n])},p.addUncountableRule=function(e){"string"!=typeof e?(p.addPluralRule(e,"$0"),p.addSingularRule(e,"$0")):n[e.toLowerCase()]=!0},p.addIrregularRule=function(e,t){t=t.toLowerCase(),e=e.toLowerCase(),i[e]=t,r[t]=e},[["I","we"],["me","us"],["he","they"],["she","they"],["them","them"],["myself","ourselves"],["yourself","yourselves"],["itself","themselves"],["herself","themselves"],["himself","themselves"],["themself","themselves"],["is","are"],["was","were"],["has","have"],["this","these"],["that","those"],["echo","echoes"],["dingo","dingoes"],["volcano","volcanoes"],["tornado","tornadoes"],["torpedo","torpedoes"],["genus","genera"],["viscus","viscera"],["stigma","stigmata"],["stoma","stomata"],["dogma","dogmata"],["lemma","lemmata"],["schema","schemata"],["anathema","anathemata"],["ox","oxen"],["axe","axes"],["die","dice"],["yes","yeses"],["foot","feet"],["eave","eaves"],["goose","geese"],["tooth","teeth"],["quiz","quizzes"],["human","humans"],["proof","proofs"],["carve","carves"],["valve","valves"],["looey","looies"],["thief","thieves"],["groove","grooves"],["pickaxe","pickaxes"],["passerby","passersby"]].forEach((function(e){return p.addIrregularRule(e[0],e[1])})),[[/s?$/i,"s"],[/[^\u0000-\u007F]$/i,"$0"],[/([^aeiou]ese)$/i,"$1"],[/(ax|test)is$/i,"$1es"],[/(alias|[^aou]us|t[lm]as|gas|ris)$/i,"$1es"],[/(e[mn]u)s?$/i,"$1s"],[/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i,"$1"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1i"],[/(alumn|alg|vertebr)(?:a|ae)$/i,"$1ae"],[/(seraph|cherub)(?:im)?$/i,"$1im"],[/(her|at|gr)o$/i,"$1oes"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i,"$1a"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i,"$1a"],[/sis$/i,"ses"],[/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i,"$1$2ves"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/([^ch][ieo][ln])ey$/i,"$1ies"],[/(x|ch|ss|sh|zz)$/i,"$1es"],[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i,"$1ices"],[/\b((?:tit)?m|l)(?:ice|ouse)$/i,"$1ice"],[/(pe)(?:rson|ople)$/i,"$1ople"],[/(child)(?:ren)?$/i,"$1ren"],[/eaux$/i,"$0"],[/m[ae]n$/i,"men"],["thou","you"]].forEach((function(e){return p.addPluralRule(e[0],e[1])})),[[/s$/i,""],[/(ss)$/i,"$1"],[/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,"$1fe"],[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i,"$1f"],[/ies$/i,"y"],[/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,"$1ie"],[/\b(mon|smil)ies$/i,"$1ey"],[/\b((?:tit)?m|l)ice$/i,"$1ouse"],[/(seraph|cherub)im$/i,"$1"],[/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,"$1"],[/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,"$1sis"],[/(movie|twelve|abuse|e[mn]u)s$/i,"$1"],[/(test)(?:is|es)$/i,"$1is"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1us"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,"$1um"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,"$1on"],[/(alumn|alg|vertebr)ae$/i,"$1a"],[/(cod|mur|sil|vert|ind)ices$/i,"$1ex"],[/(matr|append)ices$/i,"$1ix"],[/(pe)(rson|ople)$/i,"$1rson"],[/(child)ren$/i,"$1"],[/(eau)x?$/i,"$1"],[/men$/i,"man"]].forEach((function(e){return p.addSingularRule(e[0],e[1])})),["adulthood","advice","agenda","aid","aircraft","alcohol","ammo","analytics","anime","athletics","audio","bison","blood","bream","buffalo","butter","carp","cash","chassis","chess","clothing","cod","commerce","cooperation","corps","debris","diabetes","digestion","elk","energy","equipment","excretion","expertise","firmware","flounder","fun","gallows","garbage","graffiti","hardware","headquarters","health","herpes","highjinks","homework","housework","information","jeans","justice","kudos","labour","literature","machinery","mackerel","mail","media","mews","moose","music","mud","manga","news","only","personnel","pike","plankton","pliers","police","pollution","premises","rain","research","rice","salmon","scissors","series","sewage","shambles","shrimp","software","species","staff","swine","tennis","traffic","transportation","trout","tuna","wealth","welfare","whiting","wildebeest","wildlife","you",/pok[eé]mon$/i,/[^aeiou]ese$/i,/deer$/i,/fish$/i,/measles$/i,/o[iu]s$/i,/pox$/i,/sheep$/i].forEach(p.addUncountableRule),p}()},7022:function(){!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var i=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,s=0;s>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Prism.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],char:Prism.languages.c.char,comment:Prism.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}}}),Prism.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete Prism.languages.c.boolean},5624:function(){Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}},4511:function(){!function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(Prism)},2415:function(){!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism)},5651:function(){!function(e){function t(e,t){return e.replace(/<<(\d+)>>/g,(function(e,n){return"(?:"+t[+n]+")"}))}function n(e,n,r){return RegExp(t(e,n),r||"")}function r(e,t){for(var n=0;n>/g,(function(){return"(?:"+e+")"}));return e.replace(/<>/g,"[^\\s\\S]")}var i="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",o="class enum interface record struct",s="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",a="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var c=l(o),u=RegExp(l(i+" "+o+" "+s+" "+a)),p=l(o+" "+s+" "+a),d=l(i+" "+o+" "+a),f=r(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),h=r(/\((?:[^()]|<>)*\)/.source,2),m=/@?\b[A-Za-z_]\w*\b/.source,g=t(/<<0>>(?:\s*<<1>>)?/.source,[m,f]),y=t(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[p,g]),b=/\[\s*(?:,\s*)*\]/.source,v=t(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[y,b]),x=t(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[f,h,b]),w=t(/\(<<0>>+(?:,<<0>>+)+\)/.source,[x]),k=t(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[w,y,b]),S={keyword:u,punctuation:/[<>()?,.:[\]]/},E=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,O=/"(?:\\.|[^\\"\r\n])*"/.source,_=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;e.languages.csharp=e.languages.extend("clike",{string:[{pattern:n(/(^|[^$\\])<<0>>/.source,[_]),lookbehind:!0,greedy:!0},{pattern:n(/(^|[^@$\\])<<0>>/.source,[O]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:n(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[y]),lookbehind:!0,inside:S},{pattern:n(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[m,k]),lookbehind:!0,inside:S},{pattern:n(/(\busing\s+)<<0>>(?=\s*=)/.source,[m]),lookbehind:!0},{pattern:n(/(\b<<0>>\s+)<<1>>/.source,[c,g]),lookbehind:!0,inside:S},{pattern:n(/(\bcatch\s*\(\s*)<<0>>/.source,[y]),lookbehind:!0,inside:S},{pattern:n(/(\bwhere\s+)<<0>>/.source,[m]),lookbehind:!0},{pattern:n(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[v]),lookbehind:!0,inside:S},{pattern:n(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[k,d,m]),inside:S}],keyword:u,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),e.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),e.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:n(/([(,]\s*)<<0>>(?=\s*:)/.source,[m]),lookbehind:!0,alias:"punctuation"}}),e.languages.insertBefore("csharp","class-name",{namespace:{pattern:n(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[m]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:n(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[h]),lookbehind:!0,alias:"class-name",inside:S},"return-type":{pattern:n(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[k,y]),inside:S,alias:"class-name"},"constructor-invocation":{pattern:n(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[k]),lookbehind:!0,inside:S,alias:"class-name"},"generic-method":{pattern:n(/<<0>>\s*<<1>>(?=\s*\()/.source,[m,f]),inside:{function:n(/^<<0>>/.source,[m]),generic:{pattern:RegExp(f),alias:"class-name",inside:S}}},"type-list":{pattern:n(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[c,g,m,k,u.source,h,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:n(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[g,h]),lookbehind:!0,greedy:!0,inside:e.languages.csharp},keyword:u,"class-name":{pattern:RegExp(k),greedy:!0,inside:S},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var A=O+"|"+E,C=t(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[A]),j=r(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[C]),2),P=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,T=t(/<<0>>(?:\s*\(<<1>>*\))?/.source,[y,j]);e.languages.insertBefore("csharp","class-name",{attribute:{pattern:n(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[P,T]),lookbehind:!0,greedy:!0,inside:{target:{pattern:n(/^<<0>>(?=\s*:)/.source,[P]),alias:"keyword"},"attribute-arguments":{pattern:n(/\(<<0>>*\)/.source,[j]),inside:e.languages.csharp},"class-name":{pattern:RegExp(y),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var I=/:[^}\r\n]+/.source,R=r(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[C]),2),N=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[R,I]),$=r(t(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[A]),2),L=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[$,I]);function D(t,r){return{interpolation:{pattern:n(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[t]),lookbehind:!0,inside:{"format-string":{pattern:n(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[r,I]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:e.languages.csharp}}},string:/[\s\S]+/}}e.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:n(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[N]),lookbehind:!0,greedy:!0,inside:D(N,R)},{pattern:n(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[L]),lookbehind:!0,greedy:!0,inside:D(L,$)}],char:{pattern:RegExp(E),greedy:!0}}),e.languages.dotnet=e.languages.cs=e.languages.csharp}(Prism)},2630:function(){Prism.languages.csv={value:/[^\r\n,"]+|"(?:[^"]|"")*"(?!")/,punctuation:/,/}},6378:function(){Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Prism.languages.go["class-name"]},4784:function(){!function(e){function t(e){return RegExp("(^(?:"+e+"):[ \t]*(?![ \t]))[^]+","i")}e.languages.http={"request-line":{pattern:/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:e.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[\d.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[\d.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[\d.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},header:{pattern:/^[\w-]+:.+(?:(?:\r\n?|\n)[ \t].+)*/m,inside:{"header-value":[{pattern:t(/Content-Security-Policy/.source),lookbehind:!0,alias:["csp","languages-csp"],inside:e.languages.csp},{pattern:t(/Public-Key-Pins(?:-Report-Only)?/.source),lookbehind:!0,alias:["hpkp","languages-hpkp"],inside:e.languages.hpkp},{pattern:t(/Strict-Transport-Security/.source),lookbehind:!0,alias:["hsts","languages-hsts"],inside:e.languages.hsts},{pattern:t(/[^:]+/.source),lookbehind:!0}],"header-name":{pattern:/^[^:]+/,alias:"keyword"},punctuation:/^:/}}};var n,r=e.languages,i={"application/javascript":r.javascript,"application/json":r.json||r.javascript,"application/xml":r.xml,"text/xml":r.xml,"text/html":r.html,"text/css":r.css,"text/plain":r.plain},o={"application/json":!0,"application/xml":!0};function s(e){var t=e.replace(/^[a-z]+\//,"");return"(?:"+e+"|\\w+/(?:[\\w.-]+\\+)+"+t+"(?![+\\w.-]))"}for(var a in i)if(i[a]){n=n||{};var l=o[a]?s(a):a;n[a.replace(/\//g,"-")]={pattern:RegExp("("+/content-type:\s*/.source+l+/(?:(?:\r\n?|\n)[\w-].*)*(?:\r(?:\n|(?!\n))|\n)/.source+")"+/[^ \t\w-][\s\S]*/.source,"i"),lookbehind:!0,inside:i[a]}}n&&e.languages.insertBefore("http","header",n)}(Prism)},6976:function(){!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,r={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[r,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:r.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:r.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":r,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:r.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:r.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)},64:function(){Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[^z]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+(?:\.[a-f\d]*)?(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|(?:\.\d*)?(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}},9700:function(){!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,i,o){if(n.language===r){var s=n.tokenStack=[];n.code=n.code.replace(i,(function(e){if("function"==typeof o&&!o(e))return e;for(var i,a=s.length;-1!==n.code.indexOf(i=t(r,a));)++a;return s[a]=e,i})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var i=0,o=Object.keys(n.tokenStack);!function s(a){for(var l=0;l=o.length);l++){var c=a[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[i],p=n.tokenStack[u],d="string"==typeof c?c:c.content,f=t(r,u),h=d.indexOf(f);if(h>-1){++i;var m=d.substring(0,h),g=new e.Token(r,e.tokenize(p,n.grammar),"language-"+r,p),y=d.substring(h+f.length),b=[];m&&b.push.apply(b,s([m])),b.push(g),y&&b.push.apply(b,s([y])),"string"==typeof c?a.splice.apply(a,[l,1].concat(b)):c.content=b}}else c.content&&s(c.content)}return a}(n.tokens)}}}})}(Prism)},4312:function(){Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:Prism.languages[t]};var i={};i[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},Prism.languages.insertBefore("markup","cdata",i)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(e,t){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:Prism.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml},596:function(){Prism.languages.objectivec=Prism.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete Prism.languages.objectivec["class-name"],Prism.languages.objc=Prism.languages.objectivec},2821:function(){!function(e){var t=/(?:\((?:[^()\\]|\\[\s\S])*\)|\{(?:[^{}\\]|\\[\s\S])*\}|\[(?:[^[\]\\]|\\[\s\S])*\]|<(?:[^<>\\]|\\[\s\S])*>)/.source;e.languages.perl={comment:[{pattern:/(^\s*)=\w[\s\S]*?=cut.*/m,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0,greedy:!0}],string:[{pattern:RegExp(/\b(?:q|qq|qw|qx)(?![a-zA-Z0-9])\s*/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2/.source,t].join("|")+")"),greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:RegExp(/\b(?:m|qr)(?![a-zA-Z0-9])\s*/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2/.source,t].join("|")+")"+/[msixpodualngc]*/.source),greedy:!0},{pattern:RegExp(/(^|[^-])\b(?:s|tr|y)(?![a-zA-Z0-9])\s*/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2/.source,/([a-zA-Z0-9])(?:(?!\3)[^\\]|\\[\s\S])*\3(?:(?!\3)[^\\]|\\[\s\S])*\3/.source,t+/\s*/.source+t].join("|")+")"+/[msixpodualngcer]*/.source),lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|x|xor)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+(?![\w$]))+(?:::)*/,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*?>|\b_\b/,alias:"symbol"},"v-string":{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},function:{pattern:/(\bsub[ \t]+)\w+/,lookbehind:!0},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|return|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)\b/,punctuation:/[{}[\];(),:]/}}(Prism)},3554:function(){!function(e){var t=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,n=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],r=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,i=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,o=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:t,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:r,operator:i,punctuation:o};var s={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},a=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:s}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:s}}];e.languages.insertBefore("php","variable",{string:a,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:t,string:a,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,number:r,operator:i,punctuation:o}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(t){/<\?/.test(t.code)&&e.languages["markup-templating"].buildPlaceholders(t,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"php")}))}(Prism)},2342:function(){Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python},4113:function(){Prism.languages.q={string:/"(?:\\.|[^"\\\r\n])*"/,comment:[{pattern:/([\t )\]}])\/.*/,lookbehind:!0,greedy:!0},{pattern:/(^|\r?\n|\r)\/[\t ]*(?:(?:\r?\n|\r)(?:.*(?:\r?\n|\r(?!\n)))*?(?:\\(?=[\t ]*(?:\r?\n|\r))|$)|\S.*)/,lookbehind:!0,greedy:!0},{pattern:/^\\[\t ]*(?:\r?\n|\r)[\s\S]+/m,greedy:!0},{pattern:/^#!.+/m,greedy:!0}],symbol:/`(?::\S+|[\w.]*)/,datetime:{pattern:/0N[mdzuvt]|0W[dtz]|\d{4}\.\d\d(?:m|\.\d\d(?:T(?:\d\d(?::\d\d(?::\d\d(?:[.:]\d\d\d)?)?)?)?)?[dz]?)|\d\d:\d\d(?::\d\d(?:[.:]\d\d\d)?)?[uvt]?/,alias:"number"},number:/\b(?![01]:)(?:0N[hje]?|0W[hj]?|0[wn]|0x[\da-fA-F]+|\d+(?:\.\d*)?(?:e[+-]?\d+)?[hjfeb]?)/,keyword:/\\\w+\b|\b(?:abs|acos|aj0?|all|and|any|asc|asin|asof|atan|attr|avgs?|binr?|by|ceiling|cols|cor|cos|count|cov|cross|csv|cut|delete|deltas|desc|dev|differ|distinct|div|do|dsave|ej|enlist|eval|except|exec|exit|exp|fby|fills|first|fkeys|flip|floor|from|get|getenv|group|gtime|hclose|hcount|hdel|hopen|hsym|iasc|identity|idesc|if|ij|in|insert|inter|inv|keys?|last|like|list|ljf?|load|log|lower|lsq|ltime|ltrim|mavg|maxs?|mcount|md5|mdev|med|meta|mins?|mmax|mmin|mmu|mod|msum|neg|next|not|null|or|over|parse|peach|pj|plist|prds?|prev|prior|rand|rank|ratios|raze|read0|read1|reciprocal|reval|reverse|rload|rotate|rsave|rtrim|save|scan|scov|sdev|select|set|setenv|show|signum|sin|sqrt|ssr?|string|sublist|sums?|sv|svar|system|tables|tan|til|trim|txf|type|uj|ungroup|union|update|upper|upsert|value|var|views?|vs|wavg|where|while|within|wj1?|wsum|ww|xasc|xbar|xcols?|xdesc|xexp|xgroup|xkey|xlog|xprev|xrank)\b/,adverb:{pattern:/['\/\\]:?|\beach\b/,alias:"function"},verb:{pattern:/(?:\B\.\B|\b[01]:|<[=>]?|>=?|[:+\-*%,!?~=|$&#@^]):?|\b_\b:?/,alias:"operator"},punctuation:/[(){}\[\];.]/}},1648:function(){!function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===||[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var t={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var n="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",r=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+n+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+r),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+r+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+n),greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+n),greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(Prism)},4252:function(){Prism.languages.scala=Prism.languages.extend("java",{"triple-quoted-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/<-|=>|\b(?:abstract|case|catch|class|def|derives|do|else|enum|extends|extension|final|finally|for|forSome|given|if|implicit|import|infix|inline|lazy|match|new|null|object|opaque|open|override|package|private|protected|return|sealed|self|super|this|throw|trait|transparent|try|type|using|val|var|while|with|yield)\b/,number:/\b0x(?:[\da-f]*\.)?[\da-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e\d+)?[dfl]?/i,builtin:/\b(?:Any|AnyRef|AnyVal|Boolean|Byte|Char|Double|Float|Int|Long|Nothing|Short|String|Unit)\b/,symbol:/'[^\d\s\\]\w*/}),Prism.languages.insertBefore("scala","triple-quoted-string",{"string-interpolation":{pattern:/\b[a-z]\w*(?:"""(?:[^$]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*?"""|"(?:[^$"\r\n]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*")/i,greedy:!0,inside:{id:{pattern:/^\w+/,greedy:!0,alias:"function"},escape:{pattern:/\\\$"|\$[$"]/,greedy:!0,alias:"symbol"},interpolation:{pattern:/\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,greedy:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:Prism.languages.scala}}},string:/[\s\S]+/}}}),delete Prism.languages.scala["class-name"],delete Prism.languages.scala.function,delete Prism.languages.scala.constant},6966:function(){Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}},4793:function(){Prism.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+/(?:elseif|if)\b/.source+"(?:[ \t]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},Prism.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=Prism.languages.swift}))},83:function(){!function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",i=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function s(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return"(?:"+i+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:s(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:s(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:s(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:s(o),lookbehind:!0,greedy:!0},number:{pattern:s(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism)},8848:function(e,t,n){var r=function(e){var t=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,r={},i={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(t){return t instanceof o?new o(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=p.reach);S+=k.value.length,k=k.next){var E=k.value;if(t.length>e.length)return;if(!(E instanceof o)){var O,_=1;if(b){if(!(O=s(w,S,e,y))||O.index>=e.length)break;var A=O.index,C=O.index+O[0].length,j=S;for(j+=k.value.length;A>=j;)j+=(k=k.next).value.length;if(S=j-=k.value.length,k.value instanceof o)continue;for(var P=k;P!==t.tail&&(jp.reach&&(p.reach=N);var $=k.prev;if(I&&($=c(t,$,I),S+=I.length),u(t,$,_),k=c(t,$,new o(d,g?i.tokenize(T,g):T,v,T)),R&&c(t,k,R),_>1){var L={cause:d+","+h,reach:N};a(e,t,n,k.prev,S,L),p&&L.reach>p.reach&&(p.reach=L.reach)}}}}}}function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function c(e,t,n){var r=t.next,i={value:n,prev:t,next:r};return t.next=i,r.prev=i,e.length++,i}function u(e,t,n){for(var r=t.next,i=0;i"+o.content+""},!e.document)return e.addEventListener?(i.disableWorkerMessageHandler||e.addEventListener("message",(function(t){var n=JSON.parse(t.data),r=n.language,o=n.code,s=n.immediateClose;e.postMessage(i.highlight(o,i.languages[r],r)),s&&e.close()}),!1),i):i;var p=i.util.currentScript();function d(){i.manual||i.highlightAll()}if(p&&(i.filename=p.src,p.hasAttribute("data-manual")&&(i.manual=!0)),!i.manual){var f=document.readyState;"loading"===f||"interactive"===f&&p&&p.defer?document.addEventListener("DOMContentLoaded",d):window.requestAnimationFrame?window.requestAnimationFrame(d):window.setTimeout(d,16)}return i}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});e.exports&&(e.exports=r),void 0!==n.g&&(n.g.Prism=r),r.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},r.languages.markup.tag.inside["attr-value"].inside.entity=r.languages.markup.entity,r.languages.markup.doctype.inside["internal-subset"].inside=r.languages.markup,r.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(r.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:r.languages[t]},n.cdata=/^$/i;var i={"included-cdata":{pattern://i,inside:n}};i["language-"+t]={pattern:/[\s\S]+/,inside:r.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:i},r.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(r.languages.markup.tag,"addAttribute",{value:function(e,t){r.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:r.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),r.languages.html=r.languages.markup,r.languages.mathml=r.languages.markup,r.languages.svg=r.languages.markup,r.languages.xml=r.languages.extend("markup",{}),r.languages.ssml=r.languages.xml,r.languages.atom=r.languages.xml,r.languages.rss=r.languages.xml,function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+t.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(r),r.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},r.languages.javascript=r.languages.extend("clike",{"class-name":[r.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),r.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,r.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:r.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:r.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:r.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:r.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:r.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),r.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:r.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),r.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),r.languages.markup&&(r.languages.markup.tag.addInlined("script","javascript"),r.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),r.languages.js=r.languages.javascript,function(){if(void 0!==r&&"undefined"!=typeof document){Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector);var e={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"},t="data-src-status",n="loading",i="loaded",o="pre[data-src]:not(["+t+'="'+i+'"]):not(['+t+'="'+n+'"])';r.hooks.add("before-highlightall",(function(e){e.selector+=", "+o})),r.hooks.add("before-sanity-check",(function(s){var a=s.element;if(a.matches(o)){s.code="",a.setAttribute(t,n);var l=a.appendChild(document.createElement("CODE"));l.textContent="Loading…";var c=a.getAttribute("data-src"),u=s.language;if("none"===u){var p=(/\.(\w+)$/.exec(c)||[,"none"])[1];u=e[p]||p}r.util.setLanguage(l,u),r.util.setLanguage(a,u);var d=r.plugins.autoloader;d&&d.loadLanguages(u),function(e,n,o){var s=new XMLHttpRequest;s.open("GET",e,!0),s.onreadystatechange=function(){4==s.readyState&&(s.status<400&&s.responseText?function(e){a.setAttribute(t,i);var n=function(e){var t=/^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(e||"");if(t){var n=Number(t[1]),r=t[2],i=t[3];return r?i?[n,Number(i)]:[n,void 0]:[n,n]}}(a.getAttribute("data-range"));if(n){var o=e.split(/\r\n?|\n/g),s=n[0],c=null==n[1]?o.length:n[1];s<0&&(s+=o.length),s=Math.max(0,Math.min(s-1,o.length)),c<0&&(c+=o.length),c=Math.max(0,Math.min(c,o.length)),e=o.slice(s,c).join("\n"),a.hasAttribute("data-start")||a.setAttribute("data-start",String(s+1))}l.textContent=e,r.highlightElement(l)}(s.responseText):s.status>=400?o("✖ Error "+s.status+" while fetching file: "+s.statusText):o("✖ Error: File does not exist or is empty"))},s.send(null)}(c,0,(function(e){a.setAttribute(t,"failed"),l.textContent=e}))}})),r.plugins.fileHighlight={highlight:function(e){for(var t,n=(e||document).querySelectorAll(o),i=0;t=n[i++];)r.highlightElement(t)}};var s=!1;r.fileHighlight=function(){s||(console.warn("Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead."),s=!0),r.plugins.fileHighlight.highlight.apply(this,arguments)}}}()},2694:function(e,t,n){"use strict";var r=n(6925);function i(){}function o(){}o.resetWarningCache=i,e.exports=function(){function e(e,t,n,i,o,s){if(s!==r){var a=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw a.name="Invariant Violation",a}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:i};return n.PropTypes=n,n}},5556:function(e,t,n){e.exports=n(2694)()},6925:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},2551:function(e,t,n){"use strict";var r=n(6540),i=n(194);function o(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n