From 3408a4dc23e061741d5c77faecba3526dce395eb Mon Sep 17 00:00:00 2001 From: Helmut Hoffer von Ankershoffen Date: Mon, 14 Apr 2025 07:32:10 +0200 Subject: [PATCH 1/5] chore(deps): update from template --- .copier-answers.yml | 4 +- .env.example | 24 +- .github/workflows/test-and-report.yml | 34 +- .github/workflows/test-scheduled.yml | 14 +- .gitignore | 4 +- .readthedocs.yml | 2 +- API_REFERENCE_v1.md | 34 +- ATTRIBUTIONS.md | 5231 ++++++++++++++++- CLI_REFERENCE.md | 243 +- CONTRIBUTING.md | 29 +- Dockerfile | 19 +- Makefile | 8 +- README.md | 12 +- SERVICE_CONNECTIONS.md | 76 + codegen/out/.openapi-generator/FILES | 1 - .../out/aignx/codegen/api/externals_api.py | 3 + codegen/out/aignx/codegen/api_client.py | 1 + codegen/out/aignx/codegen/configuration.py | 1 + codegen/out/aignx/codegen/exceptions.py | 1 + .../models/application_read_response.py | 3 + .../codegen/models/application_run_status.py | 3 + .../codegen/models/application_version.py | 3 + .../application_version_read_response.py | 3 + .../codegen/models/http_validation_error.py | 3 + .../aignx/codegen/models/input_artifact.py | 3 + .../models/input_artifact_creation_request.py | 3 + .../models/input_artifact_read_response.py | 3 + .../input_artifact_schema_creation_request.py | 3 + .../codegen/models/item_creation_request.py | 3 + .../models/item_result_read_response.py | 3 + .../out/aignx/codegen/models/item_status.py | 3 + .../aignx/codegen/models/output_artifact.py | 3 + .../models/output_artifact_read_response.py | 3 + .../output_artifact_result_read_response.py | 3 + ...output_artifact_schema_creation_request.py | 3 + .../codegen/models/output_artifact_scope.py | 3 + .../models/output_artifact_visibility.py | 3 + .../codegen/models/payload_input_artifact.py | 3 + .../out/aignx/codegen/models/payload_item.py | 3 + .../codegen/models/payload_output_artifact.py | 3 + .../codegen/models/run_creation_request.py | 3 + .../codegen/models/run_creation_response.py | 3 + .../aignx/codegen/models/run_read_response.py | 3 + .../codegen/models/slug_version_request.py | 3 + .../out/aignx/codegen/models/transfer_urls.py | 3 + .../out/aignx/codegen/models/user_payload.py | 3 + .../aignx/codegen/models/validation_error.py | 3 + .../models/validation_error_loc_inner.py | 3 + .../models/version_creation_request.py | 3 + .../models/version_creation_response.py | 3 + .../codegen/models/version_read_response.py | 3 + codegen/out/aignx/codegen/rest.py | 1 + codegen/out/docs/ExternalsApi.md | 1 + compose.yaml | 24 +- docs/Makefile | 2 +- docs/make.bat | 70 +- docs/partials/README_header.md | 12 +- docs/source/_static/openapi_v1.json | 5 + docs/source/_static/openapi_v1.yaml | 28 +- docs/source/conf.py | 1 - docs/source/lib_reference.rst | 18 +- docs/source/release-notes.rst | 2 +- examples/notebook.ipynb | 13 +- examples/notebook.py | 2 +- examples/script.py | 2 +- examples/streamlit.py | 30 - noxfile.py | 40 +- pyproject.toml | 49 +- sitecustomize.py | 5 + sonar-project.properties | 5 +- src/aignostics/__init__.py | 70 +- src/aignostics/application/__init__.py | 7 + src/aignostics/application/_cli.py | 107 + src/aignostics/cli.py | 176 +- src/aignostics/client/__init__.py | 59 +- src/aignostics/client/_authentication.py | 54 +- src/aignostics/client/_client.py | 26 +- src/aignostics/client/_constants.py | 28 + src/aignostics/client/_settings.py | 106 +- src/aignostics/client/{utils.py => _utils.py} | 0 src/aignostics/client/resources/__init__.py | 1 + src/aignostics/client/resources/runs.py | 2 +- src/aignostics/constants.py | 37 +- src/aignostics/models.py | 19 - src/aignostics/platform.py | 151 - src/aignostics/settings.py | 35 - src/aignostics/system/__init__.py | 11 + src/aignostics/system/_cli.py | 125 + .../{exceptions.py => system/_exceptions.py} | 2 +- src/aignostics/system/_service.py | 188 + src/aignostics/system/_settings.py | 31 + src/aignostics/types.py | 57 - src/aignostics/utils/__init__.py | 57 +- src/aignostics/utils/{cli.py => _cli.py} | 11 +- .../utils/{console.py => _console.py} | 2 +- src/aignostics/utils/_constants.py | 59 + src/aignostics/utils/_di.py | 70 + src/aignostics/utils/_health.py | 107 + src/aignostics/utils/_log.py | 122 + src/aignostics/utils/_logfire.py | 69 + .../utils/{process.py => _process.py} | 1 - src/aignostics/utils/_sentry.py | 102 + src/aignostics/utils/_service.py | 39 + src/aignostics/utils/_settings.py | 89 + src/aignostics/utils/boot.py | 86 + tests/__init__.py | 2 +- tests/aignostics/__init__.py | 1 + tests/aignostics/application/__init__.py | 1 + .../core_test.py => application/cli_test.py} | 74 +- tests/aignostics/cli_test.py | 91 + tests/aignostics/client/__init__.py | 1 + .../aignostics/client/authentication_test.py | 2 +- tests/aignostics/client/scheduled_test.py | 2 +- tests/aignostics/client/settings_test.py | 49 +- tests/aignostics/client/utils_test.py | 2 +- tests/aignostics/{cli => }/docker_test.py | 8 +- tests/aignostics/system/__init__.py | 1 + tests/aignostics/system/cli_test.py | 88 + tests/aignostics/system/service_test.py | 36 + tests/conftest.py | 59 + tests/fixtures/.keep | 0 tests/fixtures/__init__.py | 1 + uv.lock | 742 ++- 123 files changed, 8317 insertions(+), 1096 deletions(-) delete mode 100644 examples/streamlit.py create mode 100644 sitecustomize.py create mode 100644 src/aignostics/application/__init__.py create mode 100644 src/aignostics/application/_cli.py create mode 100644 src/aignostics/client/_constants.py rename src/aignostics/client/{utils.py => _utils.py} (100%) create mode 100644 src/aignostics/client/resources/__init__.py delete mode 100644 src/aignostics/models.py delete mode 100644 src/aignostics/platform.py delete mode 100644 src/aignostics/settings.py create mode 100644 src/aignostics/system/__init__.py create mode 100644 src/aignostics/system/_cli.py rename src/aignostics/{exceptions.py => system/_exceptions.py} (86%) create mode 100644 src/aignostics/system/_service.py create mode 100644 src/aignostics/system/_settings.py delete mode 100644 src/aignostics/types.py rename src/aignostics/utils/{cli.py => _cli.py} (90%) rename src/aignostics/utils/{console.py => _console.py} (83%) create mode 100644 src/aignostics/utils/_constants.py create mode 100644 src/aignostics/utils/_di.py create mode 100644 src/aignostics/utils/_health.py create mode 100644 src/aignostics/utils/_log.py create mode 100644 src/aignostics/utils/_logfire.py rename src/aignostics/utils/{process.py => _process.py} (99%) create mode 100644 src/aignostics/utils/_sentry.py create mode 100644 src/aignostics/utils/_service.py create mode 100644 src/aignostics/utils/_settings.py create mode 100644 src/aignostics/utils/boot.py create mode 100644 tests/aignostics/__init__.py create mode 100644 tests/aignostics/application/__init__.py rename tests/aignostics/{cli/core_test.py => application/cli_test.py} (58%) create mode 100644 tests/aignostics/cli_test.py create mode 100644 tests/aignostics/client/__init__.py rename tests/aignostics/{cli => }/docker_test.py (72%) create mode 100644 tests/aignostics/system/__init__.py create mode 100644 tests/aignostics/system/cli_test.py create mode 100644 tests/aignostics/system/service_test.py delete mode 100644 tests/fixtures/.keep create mode 100644 tests/fixtures/__init__.py diff --git a/.copier-answers.yml b/.copier-answers.yml index ab93ded5..cf5319c1 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,4 +1,4 @@ -_commit: v0.9.4 +_commit: v0.11.0 _src_path: gh:helmut-hoffer-von-ankershoffen/oe-python-template attestations_enabled: false author_email: helmut@aignostics.com @@ -24,4 +24,6 @@ readthedocs_domain: readthedocs.org readthedocs_project_key: aignostics sonarqube_key: aignostics_python-sdk streamlit_project_key: aignostics +uptime_badge_snippet: "[![Better Stack Badge](https://uptime.betterstack.com/status-badges/v1/monitor/1vtu1.svg)](https://aignostics.betteruptime.com/)" +vercel_badge_snippet: "" vercel_function_enabled: false diff --git a/.env.example b/.env.example index 1549c242..fecd62ee 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,15 @@ - CLIENT_ID_DEVICE=YOUR_CLIENT_ID_DEVICE - CLIENT_ID_INTERACTIVE=YOUR_CLIENT_ID_INTERACTIVE - SCOPE=YOUR_SCOPE_ELEMENT,YOUR_SCOPE_ELEMENT - REDIRECT_URI=YOUR_REDIRECT_URI - AUDIENCE=YOUR_AUDIENCE - AUTHORIZATION_BASE_URL=YOUR_AUTHORIZATION_BASE_URL - TOKEN_URL=YOUR_TOKEN_URL - DEVICE_URL=YOUR_DEVICE_URL - JWS_JSON_URL=YOUR_JWS_JSON_URL +ENV=local +AIGNOSTICS_SYSTEM_TOKEN=YOUR_SECRET_TOKEN +AIGNOSTICS_LOG_LEVEL=INFO +AIGNOSTICS_LOG_FILE_ENABLED=false +AIGNOSTICS_LOG_FILE_NAME=aignostics.log +AIGNOSTICS_LOG_CONSOLE_ENABLED=false +AIGNOSTICS_LOGFIRE_TOKEN=pylf_v1_eu_CwtB1kc64d42qClGkVHLgZ65X4yFCSwPS6lv8ydw35Wm +AIGNOSTICS_LOGFIRE_INSTRUMENT_SYSTEM_METRICS=true +AIGNOSTICS_SENTRY_DSN=https://5e2b6e59746a3cb502589d8c2f0e3b64@o443095.ingest.us.sentry.io/4509130454466560 +AIGNOSTICS_SENTRY_DEBUG=false +AIGNOSTICS_SENTRY_SEND_DEFAULT_PII=false +AIGNOSTICS_SENTRY_MAX_BREADCRUMBS=5 +AIGNOSTICS_SENTRY_SAMPLE_RATE=1.0 +AIGNOSTICS_SENTRY_TRACES_SAMPLE_RATE=1.0 +AIGNOSTICS_SENTRY_PROFILES_SAMPLE_RATE=1.0 diff --git a/.github/workflows/test-and-report.yml b/.github/workflows/test-and-report.yml index a1a7d324..ae1388ed 100644 --- a/.github/workflows/test-and-report.yml +++ b/.github/workflows/test-and-report.yml @@ -49,8 +49,22 @@ jobs: if: ${{ !startsWith(github.ref, 'refs/tags/v') }} run: | TOML_VERSION=$(uv run python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") - echo "Development build - Current version in pyproject.toml: $TOML_VERSION" - + echo "Development build - Current version in pyproject.toml: $TOML_VERSION" + + - name: Create .env file + uses: SpicyPizza/create-envfile@ace6d4f5d7802b600276c23ca417e669f1a06f6f # v2.0.3 + with: + envkey_ENV: "TEST" + envkey_AIGNOSTICS_LOGFIRE_TOKEN: "${{ secrets.AIGNOSTICS_LOGFIRE_TOKEN }}" + envkey_AIGNOSTICS_SENTRY_DSN: "${{ secrets.AIGNOSTICS_SENTRY_DSN }}" + envkey_AIGNOSTICS_LOG_LEVEL: "DEBUG" + envkey_AIGNOSTICS_LOG_FILE_ENABLED: 1 + envkey_AIGNOSTICS_API_ROOT: https://platform.aignostics.com + envkey_AIGNOSTICS_CLIENT_ID_DEVICE: ${{ secrets.AIGNOSTICS_CLIENT_ID_DEVICE }} + envkey_AIGNOSTICS_CLIENT_ID_INTERACTIVE: ${{ secrets.AIGNOSTICS_CLIENT_ID_INTERACTIVE }} + envkey_AIGNOSTICS_REFRESH_TOKEN: ${{ secrets.AIGNOSTICS_REFRESH_TOKEN }} + fail_on_empty: false + - name: Validate installation run: | OUTPUT=$(uv run --no-dev aignostics --help) @@ -61,20 +75,16 @@ jobs: - name: Set up cloud credentials env: + AIGNOSTICS_API_ROOT: https://platform.aignostics.com CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} run: | echo "$CREDENTIALS" | base64 -d > credentials.json echo "GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/credentials.json" >> $GITHUB_ENV - name: Smoke tests - env: - AIGNOSTICS_API_ROOT: https://platform-dev.aignostics.com - AIGNOSTICS_CLIENT_ID_DEVICE: ${{ secrets.AIGNOSTICS_CLIENT_DEVICE_ID }} - AIGNOSTICS_CLIENT_ID_INTERACTIVE: ${{ secrets.AIGNOSTICS_CLIENT_ID_INTERACTIVE }} - AIGNOSTICS_REFRESH_TOKEN: ${{ secrets.AIGNOSTICS_REFRESH_TOKEN }} run: | - uv run --no-dev aignostics platform health - uv run --no-dev aignostics platform info + uv run --no-dev aignostics system health + uv run --no-dev aignostics system info - name: Lint run: make lint @@ -83,11 +93,6 @@ jobs: run: make audit - name: Test - env: - AIGNOSTICS_API_ROOT: https://platform-dev.aignostics.com - AIGNOSTICS_CLIENT_ID_DEVICE: ${{ secrets.AIGNOSTICS_CLIENT_DEVICE_ID }} - AIGNOSTICS_CLIENT_ID_INTERACTIVE: ${{ secrets.AIGNOSTICS_CLIENT_ID_INTERACTIVE }} - AIGNOSTICS_REFRESH_TOKEN: ${{ secrets.AIGNOSTICS_REFRESH_TOKEN }} run: make test - name: Upload test results @@ -106,6 +111,7 @@ jobs: reports/junit.xml reports/coverage.xml reports/coverage_html + aignostics.log retention-days: 30 - name: Upload coverage reports to Codecov diff --git a/.github/workflows/test-scheduled.yml b/.github/workflows/test-scheduled.yml index be292c44..3cf39d44 100644 --- a/.github/workflows/test-scheduled.yml +++ b/.github/workflows/test-scheduled.yml @@ -2,7 +2,7 @@ name: "CI Scheduled" on: schedule: - - cron: '0 6 * * *' + - cron: '0 * * * *' jobs: test-scheduled: @@ -29,8 +29,16 @@ jobs: - name: Create .env file uses: SpicyPizza/create-envfile@ace6d4f5d7802b600276c23ca417e669f1a06f6f # v2.0.3 with: - envkey_ENV_KEY: "ENV_VALUE" - fail_on_empty: true + envkey_ENV: "TEST" + envkey_AIGNOSTICS_LOGFIRE_TOKEN: "${{ secrets.AIGNOSTICS_LOGFIRE_TOKEN }}" + envkey_AIGNOSTICS_SENTRY_DSN: "${{ secrets.AIGNOSTICS_SENTRY_DSN }}" + envkey_AIGNOSTICS_LOG_LEVEL: "DEBUG" + envkey_AIGNOSTICS_LOG_FILE_ENABLED: 1 + envkey_AIGNOSTICS_API_ROOT: https://platform.aignostics.com + envkey_AIGNOSTICS_CLIENT_ID_DEVICE: ${{ secrets.AIGNOSTICS_CLIENT_ID_DEVICE }} + envkey_AIGNOSTICS_CLIENT_ID_INTERACTIVE: ${{ secrets.AIGNOSTICS_CLIENT_ID_INTERACTIVE }} + envkey_AIGNOSTICS_REFRESH_TOKEN: ${{ secrets.AIGNOSTICS_REFRESH_TOKEN }} + fail_on_empty: false - name: Run scheduled tests run: make test_scheduled diff --git a/.gitignore b/.gitignore index 0cd702bd..36d6a6d6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,11 @@ # Environment .env -.env.backup -.env.bak +.env.* ENV/ env/ .envrc +!.env.example ## secrets .secret diff --git a/.readthedocs.yml b/.readthedocs.yml index df9cfb08..6a35f743 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,4 +1,4 @@ -# Read the Docs configuration file for Aignostics Python SDK +# Read the Docs configuration file for {{ project_name }} # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required diff --git a/API_REFERENCE_v1.md b/API_REFERENCE_v1.md index 93520550..0c58aa74 100644 --- a/API_REFERENCE_v1.md +++ b/API_REFERENCE_v1.md @@ -1,6 +1,6 @@ # API v1 Reference --- -title: - url: '' +title: https://logfire-eu.pydantic.dev:443 "POST /v1/metrics HTTP/1.1" 200 2 language_tabs: toc_footers: [] includes: [] @@ -18,6 +18,8 @@ highlight_theme: darkula + + - Aignostics H&E TME application title: Description type: string @@ -736,8 +738,7 @@ paths: - Externals /v1/applications/{application_id}/versions: get: - operationId: -list_versions_by_application_id_v1_applications__application_id__versions_get + operationId: list_versions_by_application_id_v1_applications__application_id__versions_get parameters: - in: path name: application_id @@ -800,8 +801,7 @@ list_versions_by_application_id_v1_applications__application_id__versions_get schema: items: $ref: '#/components/schemas/ApplicationVersionReadResponse' - title: Response List Versions By Application Id V1 Applications -Application + title: Response List Versions By Application Id V1 Applications Application Id Versions Get type: array description: Successful Response @@ -816,8 +816,7 @@ Application - Externals /v1/applications/{application_slug}: get: - operationId: -read_application_by_slug_v1_applications__application_slug__get + operationId: read_application_by_slug_v1_applications__application_slug__get parameters: - in: path name: application_slug @@ -843,9 +842,7 @@ read_application_by_slug_v1_applications__application_slug__get - Externals /v1/applications/{application_slug}/versions: get: - operationId: -list_versions_by_application_slug_v1_applications__application_slug__versions_ge -t + operationId: list_versions_by_application_slug_v1_applications__application_slug__versions_get parameters: - in: path name: application_slug @@ -908,8 +905,7 @@ t schema: items: $ref: '#/components/schemas/ApplicationVersionReadResponse' - title: Response List Versions By Application Slug V1 -Applications Application + title: Response List Versions By Application Slug V1 Applications Application Slug Versions Get type: array description: Successful Response @@ -1101,8 +1097,7 @@ Applications Application - Externals /v1/runs/{application_run_id}/results: delete: - operationId: -delete_run_results_v1_runs__application_run_id__results_delete + operationId: delete_run_results_v1_runs__application_run_id__results_delete parameters: - in: path name: application_run_id @@ -1200,8 +1195,7 @@ delete_run_results_v1_runs__application_run_id__results_delete schema: items: $ref: '#/components/schemas/ItemResultReadResponse' - title: Response List Run Results V1 Runs Application Run Id -Results + title: Response List Run Results V1 Runs Application Run Id Results Get type: array description: Successful Response @@ -1282,6 +1276,14 @@ Results - Externals servers: - url: '' +Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 +Starting new HTTPS connection (2): logfire-eu.pydantic.dev:443 +https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 +https://logfire-eu.pydantic.dev:443 "POST /v1/metrics HTTP/1.1" 200 2 + +> Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 + +> https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 > components: diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index b6d783f5..9c820085 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -30,6 +30,39 @@ limitations under the License. ``` +## Deprecated (1.2.18) - MIT License + +Python @deprecated decorator to deprecate old python classes, functions or methods. + +* URL: https://github.com/laurent-laporte-pro/deprecated +* Author(s): Laurent LAPORTE + +### License Text + +``` +The MIT License (MIT) + +Copyright (c) 2017 Laurent LAPORTE + +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. +``` + ## Faker (37.1.0) - MIT License Faker is a Python package that generates fake data for you. @@ -1354,6 +1387,46 @@ Better dates & times for Python ``` +## asgiref (3.8.1) - BSD License + +ASGI specs, helper code, and adapters + +* URL: https://github.com/django/asgiref/ +* Author(s): Django Software Foundation + +### License Text + +``` +Copyright (c) Django Software Foundation and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Django nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +``` + ## asttokens (3.0.0) - Apache 2.0 Annotate AST trees with source code positions @@ -5062,6 +5135,54 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ``` +## dnspython (2.7.0) - ISC License (ISCL) + +DNS toolkit + +* URL: https://www.dnspython.org +* Author(s): Bob Halley + +### License Text + +``` +ISC License + +Copyright (C) Dnspython Contributors + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + + +Copyright (C) 2001-2017 Nominum, Inc. +Copyright (C) Google Inc. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose with or without fee is hereby granted, +provided that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +``` + ## docutils (0.21.2) - BSD License; GNU General Public License (GPL); Public Domain; Python Software Foundation License Docutils -- Python Documentation Utilities @@ -5267,6 +5388,46 @@ OR OTHER DEALINGS IN THE SOFTWARE. ``` +## email_validator (2.2.0) - The Unlicense (Unlicense) + +A robust email address syntax and deliverability validation library. + +* URL: https://github.com/JoshData/python-email-validator +* Author(s): Joshua Tauberer + +### License Text + +``` +This is free and unencumbered software released into the public +domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a +compiled binary, for any purpose, commercial or non-commercial, +and by any means. + +In jurisdictions that recognize copyright laws, the author or +authors of this software dedicate any and all copyright +interest in the software to the public domain. We make this +dedication for the benefit of the public at large and to the +detriment of our heirs and successors. We intend this +dedication to be an overt act of relinquishment in perpetuity +of all present and future rights to this software under +copyright law. + +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 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. + +For more information, please refer to + +``` + ## enum-tools (0.12.0) - GNU Lesser General Public License v3 or later (LGPLv3+) Tools to expand Python's enum module. @@ -5510,6 +5671,74 @@ SOFTWARE. ``` +## fastapi (0.115.12) - MIT License + +FastAPI framework, high performance, easy to learn, fast to code, ready for production + +* URL: https://github.com/fastapi/fastapi +* Author(s): =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= + +### License Text + +``` +The MIT License (MIT) + +Copyright (c) 2018 Sebastián Ramírez + +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. + +``` + +## fastapi-cli (0.0.7) - MIT License + +Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀 + +* URL: https://github.com/fastapi/fastapi-cli +* Author(s): =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= + +### License Text + +``` +The MIT License (MIT) + +Copyright (c) 2024 Sebastián Ramírez + +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. + +``` + ## fastjsonschema (2.21.1) - BSD License Fastest Python implementation of JSON schema @@ -7714,6 +7943,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` +## httptools (0.6.4) - MIT License + +A collection of framework independent HTTP protocol utils. + +* URL: https://github.com/MagicStack/httptools +* Author(s): Yury Selivanov + +### License Text + +``` +The MIT License + +Copyright (c) 2015 MagicStack Inc. http://magic.io + +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. + +``` + ## httpx (0.28.1) - BSD License The next generation HTTP client. @@ -7847,58 +8110,273 @@ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## iniconfig (2.1.0) - MIT License +## importlib_metadata (8.6.1) - Apache Software License -brain-dead simple config-ini parsing +Read metadata from Python packages -* URL: https://github.com/pytest-dev/iniconfig -* Author(s): Ronny Pfannschmidt , Holger Krekel +* URL: https://github.com/python/importlib_metadata +* Author(s): "Jason R. Coombs" ### License Text ``` -The MIT License (MIT) - -Copyright (c) 2010 - 2023 Holger Krekel and others - -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. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -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. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -``` + 1. Definitions. -## ipykernel (6.29.5) - BSD License + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -IPython Kernel for Jupyter + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -* URL: https://ipython.org -* Author(s): IPython Development Team + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -### License Text + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -``` -BSD 3-Clause License + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Copyright (c) 2015, IPython Development Team + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -All rights reserved. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## iniconfig (2.1.0) - MIT License + +brain-dead simple config-ini parsing + +* URL: https://github.com/pytest-dev/iniconfig +* Author(s): Ronny Pfannschmidt , Holger Krekel + +### License Text + +``` +The MIT License (MIT) + +Copyright (c) 2010 - 2023 Holger Krekel and others + +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. + +``` + +## ipykernel (6.29.5) - BSD License + +IPython Kernel for Jupyter + +* URL: https://ipython.org +* Author(s): IPython Development Team + +### License Text + +``` +BSD 3-Clause License + +Copyright (c) 2015, IPython Development Team + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. @@ -9541,6 +10019,40 @@ license-expression is a comprehensive utility library to parse, compare, simplif ``` +## logfire (3.13.1) - MIT License + +The best Python observability tool! 🪵🔥 + +* URL: https://logfire.pydantic.dev/ +* Author(s): Pydantic Team , Samuel Colvin , Hasan Ramezani , Adrian Garcia Badaracco , David Montague , Marcelo Trylesinski , David Hewitt , Alex Hall + +### License Text + +``` +The MIT License (MIT) + +Copyright (c) 2023 - present Pydantic Services inc. + +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. + +``` + ## lxml (5.3.2) - BSD License Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API. @@ -9584,7 +10096,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` -## marimo (0.12.4) - Apache Software License +## marimo (0.12.8) - Apache Software License A library for making reactive notebooks and apps @@ -12017,12 +12529,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` -## overrides (7.7.0) - Apache License, Version 2.0 +## opentelemetry-api (1.32.0) - Apache Software License -A decorator to automatically detect mismatch when overriding a method. +OpenTelemetry Python API -* URL: https://github.com/mkorpela/overrides -* Author(s): Mikko Korpela +* URL: https://github.com/open-telemetry/opentelemetry-python/tree/main/opentelemetry-api +* Author(s): OpenTelemetry Authors ### License Text @@ -12207,7 +12719,7 @@ A decorator to automatically detect mismatch when overriding a method. APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -12215,7 +12727,7 @@ A decorator to automatically detect mismatch when overriding a method. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -12229,10 +12741,4083 @@ A decorator to automatically detect mismatch when overriding a method. See the License for the specific language governing permissions and limitations under the License. - ``` -## packageurl-python (0.16.0) - MIT License +## opentelemetry-exporter-otlp-proto-common (1.32.0) - Apache Software License + +OpenTelemetry Protobuf encoding + +* URL: https://github.com/open-telemetry/opentelemetry-python/tree/main/exporter/opentelemetry-exporter-otlp-proto-common +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-exporter-otlp-proto-http (1.32.0) - Apache Software License + +OpenTelemetry Collector Protobuf over HTTP Exporter + +* URL: https://github.com/open-telemetry/opentelemetry-python/tree/main/exporter/opentelemetry-exporter-otlp-proto-http +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation (0.53b0) - Apache Software License + +Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/opentelemetry-instrumentation +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-asgi (0.53b0) - Apache Software License + +ASGI instrumentation for OpenTelemetry + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-asgi +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-dbapi (0.53b0) - Apache Software License + +OpenTelemetry Database API instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-dbapi +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-fastapi (0.53b0) - Apache Software License + +OpenTelemetry FastAPI Instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-fastapi +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-httpx (0.53b0) - Apache Software License + +OpenTelemetry HTTPX Instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-httpx +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-jinja2 (0.53b0) - Apache Software License + +OpenTelemetry jinja2 instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-jinja2 +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-requests (0.53b0) - Apache Software License + +OpenTelemetry requests instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-requests +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-sqlite3 (0.53b0) - Apache Software License + +OpenTelemetry SQLite3 instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-sqlite3 +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-system-metrics (0.53b0) - Apache Software License + +OpenTelemetry System Metrics Instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-system-metrics +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-tornado (0.53b0) - Apache Software License + +Tornado instrumentation for OpenTelemetry + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-tornado +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-urllib (0.53b0) - Apache Software License + +OpenTelemetry urllib instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-urllib +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-instrumentation-urllib3 (0.53b0) - Apache Software License + +OpenTelemetry urllib3 instrumentation + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-urllib3 +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-proto (1.32.0) - Apache Software License + +OpenTelemetry Python Proto + +* URL: https://github.com/open-telemetry/opentelemetry-python/tree/main/opentelemetry-proto +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-sdk (1.32.0) - Apache Software License + +OpenTelemetry Python SDK + +* URL: https://github.com/open-telemetry/opentelemetry-python/tree/main/opentelemetry-sdk +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-semantic-conventions (0.53b0) - Apache Software License + +OpenTelemetry Semantic Conventions + +* URL: https://github.com/open-telemetry/opentelemetry-python/tree/main/opentelemetry-semantic-conventions +* Author(s): OpenTelemetry Authors + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +## opentelemetry-util-http (0.53b0) - Apache Software License + +Web util for OpenTelemetry + +* URL: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/util/opentelemetry-util-http +* Author(s): OpenTelemetry Authors + +## orjson (3.10.16) - Apache Software License; MIT License + +Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy + +* URL: https://github.com/ijl/orjson +* Author(s): ijl + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +``` + +## overrides (7.7.0) - Apache License, Version 2.0 + +A decorator to automatically detect mismatch when overriding a method. + +* URL: https://github.com/mkorpela/overrides +* Author(s): Mikko Korpela + +### License Text + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +``` + +## packageurl-python (0.16.0) - MIT License A purl aka. Package URL parser and builder @@ -15307,7 +19892,7 @@ pip requirements parser - a mostly correct pip requirements parsing library beca * URL: https://github.com/nexB/pip-requirements-parser * Author(s): The pip authors, nexB. Inc. and others -## pip_audit (2.8.0) - Apache Software License +## pip_audit (2.9.0) - Apache Software License A tool for scanning Python environments for known vulnerabilities @@ -19001,7 +23586,7 @@ SOFTWARE. ``` -## pydantic (2.11.2) - MIT License +## pydantic (2.11.3) - MIT License Data validation using Python type hints @@ -19035,6 +23620,40 @@ SOFTWARE. ``` +## pydantic-extra-types (2.10.3) - MIT License + +Extra Pydantic types. + +* URL: https://github.com/pydantic/pydantic-extra-types +* Author(s): Samuel Colvin , Yasser Tahiri + +### License Text + +``` +The MIT License (MIT) + +Copyright (c) 2023 Samuel Colvin and other contributors + +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. + +``` + ## pydantic-settings (2.8.1) - MIT License Settings management using Pydantic @@ -19286,7 +23905,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## pyright (1.1.398) - MIT +## pyright (1.1.399) - MIT Command line wrapper for pyright @@ -19635,7 +24254,7 @@ DEALINGS IN THE SOFTWARE. ``` -## pytest-docker (3.2.0) - MIT License +## pytest-docker (3.2.1) - MIT License Simple pytest fixtures for Docker and Docker Compose based tests @@ -19981,6 +24600,33 @@ This software includes the following licenced software: Licenced under ISC Licence Source: https://github.com/mkdocstrings/python +``` + +## python-multipart (0.0.20) - Apache Software License + +A streaming multipart parser for Python + +* URL: https://github.com/Kludex/python-multipart +* Author(s): Andrew Dunham , Marcelo Trylesinski + +### License Text + +``` +Copyright 2012, Andrew Dunham + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + ``` ## pytz (2025.2) - MIT License @@ -20534,6 +25180,39 @@ SOFTWARE. ``` +## rich-toolkit (0.14.1) - MIT License + +Rich toolkit for building command-line applications + +* URL: UNKNOWN + +### License Text + +``` +MIT License + +Copyright (c) 2024 Patrick Arminio + +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. + +``` + ## roman-numerals-py (3.1.0) - CC0 1.0 Universal (CC0 1.0) Public Domain Dedication; Zero-Clause BSD (0BSD) Manipulate well-formed Roman numerals @@ -20826,7 +25505,7 @@ ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of com ``` -## ruff (0.11.4) - MIT License +## ruff (0.11.5) - MIT License An extremely fast Python linter and code formatter, written in Rust. @@ -22460,6 +27139,40 @@ Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. ``` +## sentry-sdk (2.25.1) - BSD License + +Python client for Sentry (https://sentry.io) + +* URL: https://github.com/getsentry/sentry-python +* Author(s): Sentry Team and Contributors + +### License Text + +``` +MIT License + +Copyright (c) 2018 Functional Software, Inc. dba Sentry + +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. + +``` + ## setuptools (78.1.0) - MIT License Easily download, build, install, upgrade, and uninstall Python packages @@ -25533,13 +30246,175 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at -http://www.apache.org/licenses/LICENSE-2.0 +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +``` + +## ujson (5.10.0) - BSD License + +Ultra fast JSON encoder and decoder for Python + +* URL: https://github.com/ultrajson/ultrajson +* Author(s): Jonas Tarnstrom + +### License Text + +``` +Developed by ESN, an Electronic Arts Inc. studio. +Copyright (c) 2014, Electronic Arts Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +* Neither the name of ESN, Electronic Arts Inc. nor the +names of its contributors may be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---- + +Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) +https://github.com/client9/stringencoders + + Copyright 2005, 2006, 2007 + Nick Galbreath -- nickg [at] modp [dot] com + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of the modp.com nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This is the standard "new" BSD license: + http://www.opensource.org/licenses/bsd-license.php + +https://github.com/client9/stringencoders/blob/cfd5c1507325ae497ea9bacdacba12c0ffd79d30/COPYING + +---- + +Numeric decoder derived from from TCL library +https://opensource.apple.com/source/tcl/tcl-14/tcl/license.terms + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + + This software is copyrighted by the Regents of the University of + California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState + Corporation and other parties. The following terms apply to all files + associated with the software unless explicitly disclaimed in + individual files. + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. + + GOVERNMENT USE: If you are acquiring this software on behalf of the + U.S. government, the Government shall have only "Restricted Rights" + in the software and related documentation as defined in the Federal + Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you + are acquiring the software on behalf of the Department of Defense, the + software shall be classified as "Commercial Computer Software" and the + Government shall have only "Restricted Rights" as defined in Clause + 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the + authors grant the U.S. Government and others acting in its behalf + permission to use and distribute the software in accordance with the + terms specified in this license. + +``` + +## uptime (3.0.1) - BSD License + +Cross-platform uptime library + +* URL: https://github.com/Cairnarvon/uptime +* Author(s): Koen Crolla + +### License Text + +``` +Copyright (c) 2012, Koen Crolla +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` @@ -25866,6 +30741,222 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` +## uvloop (0.21.0) - Apache Software License; MIT License + +Fast implementation of asyncio event loop on top of libuv + +* URL: UNKNOWN +* Author(s): Yury Selivanov + +### License Text + +``` +Copyright (C) 2016-present the uvloop authors and contributors. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2015-present MagicStack Inc. http://magic.io + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + ## virtualenv (20.30.0) - MIT License Virtual Python Environment builder @@ -26414,3 +31505,33 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` + +## zipp (3.21.0) - MIT License + +Backport of pathlib-compatible object wrapper for zip files + +* URL: https://github.com/jaraco/zipp +* Author(s): "Jason R. Coombs" + +### License Text + +``` +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. + +``` diff --git a/CLI_REFERENCE.md b/CLI_REFERENCE.md index 46f26567..ec74078c 100644 --- a/CLI_REFERENCE.md +++ b/CLI_REFERENCE.md @@ -1,6 +1,6 @@ # CLI Reference -Command Line Interface of the aignostics platform +Command Line Interface of **Usage**: @@ -14,21 +14,21 @@ $ aignostics [OPTIONS] COMMAND [ARGS]... * `--show-completion`: Show completion for the current shell, to copy it or customize the installation. * `--help`: Show this message and exit. -🔬 Aignostics Python SDK v0.0.10 - built with love in Berlin 🐻 +🧠 Aignostics Python SDK v0.0.10 - built with love in Berlin 🐻 **Commands**: -* `platform`: Platform diagnostics and utilities -* `application`: aignostics applications +* `application`: Application commands +* `system`: System commands -## `aignostics platform` +## `aignostics application` -Platform diagnostics and utilities +Application commands **Usage**: ```console -$ aignostics platform [OPTIONS] COMMAND [ARGS]... +$ aignostics application [OPTIONS] COMMAND [ARGS]... ``` **Options**: @@ -37,81 +37,49 @@ $ aignostics platform [OPTIONS] COMMAND [ARGS]... **Commands**: -* `install`: Complete and validate installation of the... -* `health`: Indicate if aignostics platform is healthy. -* `info`: Print info about service configuration. -* `openapi`: Dump the OpenAPI specification of to stdout. +* `list`: List available applications. +* `describe`: Describe application. * `bucket`: Transfer bucket provide by platform +* `dataset`: Datasets for use as input for applications +* `metadata`: Metadata required as input for applications +* `run`: Runs of applications -### `aignostics platform install` - -Complete and validate installation of the CLI. - -**Usage**: - -```console -$ aignostics platform install [OPTIONS] -``` - -**Options**: - -* `--help`: Show this message and exit. - -### `aignostics platform health` - -Indicate if aignostics platform is healthy. - -**Usage**: - -```console -$ aignostics platform health [OPTIONS] -``` - -**Options**: - -* `--help`: Show this message and exit. - -### `aignostics platform info` +### `aignostics application list` -Print info about service configuration. +List available applications. **Usage**: ```console -$ aignostics platform info [OPTIONS] +$ aignostics application list [OPTIONS] ``` **Options**: -* `--output-format [yaml|json]`: Output format [default: yaml] -* `--env / --no-env`: Include environment variables in output [default: no-env] -* `--filter-secrets / --no-filter-secrets`: Filter out secret values from environment variables [default: filter-secrets] * `--help`: Show this message and exit. -### `aignostics platform openapi` +### `aignostics application describe` -Dump the OpenAPI specification of to stdout. +Describe application. **Usage**: ```console -$ aignostics platform openapi [OPTIONS] +$ aignostics application describe [OPTIONS] ``` **Options**: -* `--api-version [v1]`: API Version [default: v1] -* `--output-format [yaml|json]`: Output format [default: yaml] * `--help`: Show this message and exit. -### `aignostics platform bucket` +### `aignostics application bucket` Transfer bucket provide by platform **Usage**: ```console -$ aignostics platform bucket [OPTIONS] COMMAND [ARGS]... +$ aignostics application bucket [OPTIONS] COMMAND [ARGS]... ``` **Options**: @@ -123,78 +91,28 @@ $ aignostics platform bucket [OPTIONS] COMMAND [ARGS]... * `ls`: List contents of tranfer bucket. * `purge`: Purge content of transfer bucket. -#### `aignostics platform bucket ls` +#### `aignostics application bucket ls` List contents of tranfer bucket. **Usage**: ```console -$ aignostics platform bucket ls [OPTIONS] +$ aignostics application bucket ls [OPTIONS] ``` **Options**: * `--help`: Show this message and exit. -#### `aignostics platform bucket purge` +#### `aignostics application bucket purge` Purge content of transfer bucket. **Usage**: ```console -$ aignostics platform bucket purge [OPTIONS] -``` - -**Options**: - -* `--help`: Show this message and exit. - -## `aignostics application` - -aignostics applications - -**Usage**: - -```console -$ aignostics application [OPTIONS] COMMAND [ARGS]... -``` - -**Options**: - -* `--help`: Show this message and exit. - -**Commands**: - -* `list`: List available applications. -* `describe`: Describe application. -* `dataset`: Datasets for use as input for applications -* `metadata`: Metadata required as input for applications -* `run`: Runs of applications - -### `aignostics application list` - -List available applications. - -**Usage**: - -```console -$ aignostics application list [OPTIONS] -``` - -**Options**: - -* `--help`: Show this message and exit. - -### `aignostics application describe` - -Describe application. - -**Usage**: - -```console -$ aignostics application describe [OPTIONS] +$ aignostics application bucket purge [OPTIONS] ``` **Options**: @@ -404,3 +322,116 @@ $ aignostics application run result delete [OPTIONS] **Options**: * `--help`: Show this message and exit. + +## `aignostics system` + +System commands + +**Usage**: + +```console +$ aignostics system [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--help`: Show this message and exit. + +**Commands**: + +* `health`: Determine and print system health. +* `info`: Determine and print system info. +* `openapi`: Dump the OpenAPI specification. +* `install`: Complete installation. +* `whoami`: Print user info. + +### `aignostics system health` + +Determine and print system health. + +Args: + output_format (OutputFormat): Output format (JSON or YAML). + +**Usage**: + +```console +$ aignostics system health [OPTIONS] +``` + +**Options**: + +* `--output-format [yaml|json]`: Output format [default: json] +* `--help`: Show this message and exit. + +### `aignostics system info` + +Determine and print system info. + +Args: + include_environ (bool): Include environment variables. + filter_secrets (bool): Filter secrets from the output. + output_format (OutputFormat): Output format (JSON or YAML). + +**Usage**: + +```console +$ aignostics system info [OPTIONS] +``` + +**Options**: + +* `--include-environ / --no-include-environ`: Include environment variables [default: no-include-environ] +* `--filter-secrets / --no-filter-secrets`: Filter secrets [default: filter-secrets] +* `--output-format [yaml|json]`: Output format [default: json] +* `--help`: Show this message and exit. + +### `aignostics system openapi` + +Dump the OpenAPI specification. + +Args: + api_version (str): API version to dump. + output_format (OutputFormat): Output format (JSON or YAML). + +Raises: + typer.Exit: If an invalid API version is provided. + +**Usage**: + +```console +$ aignostics system openapi [OPTIONS] +``` + +**Options**: + +* `--api-version TEXT`: API Version. Available: v1 [default: v1] +* `--output-format [yaml|json]`: Output format [default: json] +* `--help`: Show this message and exit. + +### `aignostics system install` + +Complete installation. + +**Usage**: + +```console +$ aignostics system install [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. + +### `aignostics system whoami` + +Print user info. + +**Usage**: + +```console +$ aignostics system whoami [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f84de8d6..b09fbc7c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ Install or update tools required for development: ```shell # Install Homebrew, uv package manager, copier and further dev tools -curl -LsSf https://raw.githubusercontent.com/helmut-hoffer-von-ankershoffen/oe-python-template/HEAD/install.sh | sh +curl -LsSf https://raw.githubusercontent.com/aignostics/python-sdk/HEAD/install.sh | sh ``` [Create a fork](https://github.com/aignostics/python-sdk/fork) and clone your fork using ```git clone URL_OF_YOUR_CLONE```. Then change into the directory of your local Aignostics Python SDK repository with ```cd python-sdk```. @@ -31,16 +31,16 @@ If you are one of the committers of https://github.com/aignostics/python-sdk you ├── .env # Environment variables, on .gitignore ├── .env.example # Example environment variables src/aignostics/ # Source code -├── __init__.py # Package initialization -├── constants.py # Constants used throughout the app -├── settings.py # Settings loaded from environment and .env -├── models.py # Models and data structures -├── service.py # Service exposed for use as shared library -├── cli.py # CLI enabling to interact with service from terminal -└── api.py # API exposing service as web service -tests/ # Unit and E2E tests -├── cli_tests.py # Verifies the CLI functionality -├── api_tests.py # Verifies the API functionality +├── __init__.py # Package initialization and +├── utils/*.py # Infrastructure for logging, sentry, logfire etc. +├── system/*.py # Module for system management, including service, CLI commands and API operations +├── hello/*.py # Module for "Hello" functionality, including service, CLI commands and API operations +├── cli.py # CLI entrypoint with auto-registration of CLI commands of modules +├── api.py # Webservice API entrypoint with auto-registration of API operations of modules +└── constants.py # Package specific constants such as major API versions and modules to instrument. +tests/aignostics/ # Tests +├── **/cli_tests.py # Verifies the core and module specific CLI commands +├── **/api_tests.py # Verifies the core and module specific API operations └── fixtures/ # Fixtures and mock data docs/ # Documentation ├── partials/*.md # Partials to compile README.md, _main partial included in HTML and PDF documentation @@ -68,7 +68,6 @@ reports/ # Compliance reports for auditing └── sbom.json # Software Bill of Materials in OWASP CycloneDX format ``` - ## Build, Run and Release ### Setup project specific development environment @@ -146,7 +145,7 @@ Build and run the Docker image with plain Docker ```shell # Build from Dockerimage -make docker build +make docker_build # Run the CLI docker run --env THE_VAR=THE_VALUE aignostics --help ``` @@ -164,7 +163,7 @@ echo "Checking health of v1 API ..." curl http://127.0.0.1:8000/api/v1/healthz echo "" echo "Saying hello world with v1 API ..." -curl http://127.0.0.1:8000/api/v1/hello-world +curl http://127.0.0.1:8000/api/v1/hello/world echo "" echo "Swagger docs of v1 API ..." curl http://127.0.0.1:8000/api/v1/docs @@ -173,7 +172,7 @@ echo "Checking health of v2 API ..." curl http://127.0.0.1:8000/api/v2/healthz echo "" echo "Saying hello world with v1 API ..." -curl http://127.0.0.1:8000/api/v2/hello-world +curl http://127.0.0.1:8000/api/v2/hello/world echo "" echo "Swagger docs of v2 API ..." curl http://127.0.0.1:8000/api/v2/docs diff --git a/Dockerfile b/Dockerfile index f35c3aef..ed6acd17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,29 +17,30 @@ ENV PATH="/app/.venv/bin:$PATH" RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --no-dev --no-editable + uv sync --frozen --no-install-project --all-extras --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching COPY pyproject.toml /app +COPY .python-version /app COPY uv.lock /app COPY src /app/src -COPY .env.example /app/.env.example -COPY tests /app/tests COPY LICENSE /app COPY *.md /app -COPY .python-version /app + +COPY .env.example /app/.env.example +COPY tests /app/tests + +# Install project specifics +COPY codegen/out/aignx /app/codegen/out/aignx RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --no-editable + uv sync --frozen --all-extras --no-dev --no-editable ENV AIGNOSTICS_PYTHON_SDK_RUNNING_IN_CONTAINER=1 -# API will run on port 8000 by default -EXPOSE 8000/tcp - # No healthcheck by default HEALTHCHECK NONE # But feel free to add arguments and options as needed when doing a docker run -ENTRYPOINT ["uv", "run", "--no-dev", "aignostics"] +ENTRYPOINT ["uv", "run", "--all-extras", "--no-dev", "aignostics"] diff --git a/Makefile b/Makefile index 2061d87f..27b82e76 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Makefile for running common development tasks # Define all PHONY targets -.PHONY: all act audit bump clean dist docs docker_build lint setup setup test test_scheduled update_from_template +.PHONY: all act audit bump clean codegen dist docs docker_build lint setup setup test test_scheduled test_long_running update_from_template # Main target i.e. default sessions defined in noxfile.py all: @@ -34,6 +34,10 @@ act audit bump dist docs lint setup test update_from_template: test_scheduled: uv run --all-extras nox -s test -p 3.11 -- -m scheduled +## Run tests marked as long_running +test_long_running: + uv run --all-extras nox -s test -p 3.11 -- -m long_running + ## Clean build artifacts and caches clean: rm -rf .mypy_cache @@ -81,6 +85,7 @@ help: @echo " audit - Run security and license compliance audit" @echo " bump patch|minor|major|x.y.z - Bump version" @echo " clean - Clean build artifacts and caches" + @echo " codegen - Generate API code" @echo " dist - Build wheel and sdist into dist/" @echo " docs [pdf] - Build documentation (add pdf for PDF format)" @@ -89,6 +94,7 @@ help: @echo " setup - Setup development environment" @echo " test [3.11|3.12|3.13] - Run tests (for specific Python version)" @echo " test_scheduled - Run tests marked as scheduled with Python 3.11" + @echo " test_long_running - Run tests marked as long running with Python 3.11" @echo " update_from_template - Update from template using copier" @echo "" @echo "Built with love in Berlin 🐻" diff --git a/README.md b/README.md index 869a8b91..4a6fa0ed 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ # 🔬 Aignostics Python SDK -[![License](https://img.shields.io/github/license/aignostics/python-sdk?logo=opensourceinitiative&logoColor=3DA639&labelColor=414042&color=A41831) -](https://github.com/aignostics/python-sdk/blob/main/LICENSE) +[![License](https://img.shields.io/github/license/aignostics/python-sdk?logo=opensourceinitiative&logoColor=3DA639&labelColor=414042&color=A41831)](https://github.com/aignostics/python-sdk/blob/main/LICENSE) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aignostics.svg?logo=python&color=204361&labelColor=1E2933)](https://github.com/aignostics/python-sdk/blob/main/noxfile.py) [![CI](https://github.com/aignostics/python-sdk/actions/workflows/test-and-report.yml/badge.svg)](https://github.com/aignostics/python-sdk/actions/workflows/test-and-report.yml) [![Read the Docs](https://img.shields.io/readthedocs/aignostics)](https://aignostics.readthedocs.io/en/latest/) @@ -13,7 +12,6 @@ [![Maintainability](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk) [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk) - [![Dependabot](https://img.shields.io/badge/dependabot-active-brightgreen?style=flat-square&logo=dependabot)](https://github.com/aignostics/python-sdk/security/dependabot) [![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://github.com/aignostics/python-sdk/issues?q=is%3Aissue%20state%3Aopen%20Dependency%20Dashboard) [![Coverage](https://codecov.io/gh/aignostics/python-sdk/graph/badge.svg?token=SX34YRP30E)](https://codecov.io/gh/aignostics/python-sdk) @@ -28,6 +26,7 @@ [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template) [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE3IDE2VjdsLTYgNU0yIDlWOGwxLTFoMWw0IDMgOC04aDFsNCAyIDEgMXYxNGwtMSAxLTQgMmgtMWwtOC04LTQgM0gzbC0xLTF2LTFsMy0zIi8+PC9zdmc+)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/aignostics/python-sdk) [![Open in GitHub Codespaces](https://img.shields.io/static/v1?label=GitHub%20Codespaces&message=Open&color=blue&logo=github)](https://github.com/codespaces/new/aignostics/python-sdk) +[![Better Stack Badge](https://uptime.betterstack.com/status-badges/v1/monitor/1vtu1.svg)](https://aignostics.betteruptime.com/) > [!TIP] -> 📚 [Online documentation](https://aignostics.readthedocs.io/en/latest/) - 📖 [PDF Manual](https://aignostics.readthedocs.io/_/downloads/en/latest/pdf/) +> 📚 [Online documentation](https://aignostics.readthedocs.io/en/latest/) - 📖 +> [PDF Manual](https://aignostics.readthedocs.io/_/downloads/en/latest/pdf/) > [!NOTE] -> 🧠 This project was scaffolded using the template [oe-python-template](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template) with [copier](https://copier.readthedocs.io/). +> 🧠 This project was scaffolded using the template +> [oe-python-template](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template) +> with [copier](https://copier.readthedocs.io/). --- diff --git a/SERVICE_CONNECTIONS.md b/SERVICE_CONNECTIONS.md index 9208bd3c..4ffcf025 100644 --- a/SERVICE_CONNECTIONS.md +++ b/SERVICE_CONNECTIONS.md @@ -75,6 +75,82 @@ 4. Enable Dependabot security updates 5. CodeQL analyis will be automatically set up via a GitHub action + +## Error monitoring and profiling with Sentry + +1. Goto https://sentry.io/ and sign-in - it's free for solo devs +2. Follow the instructions to create a new project and get the DSN. Copy the + value of the token into your clipboard. +3. For your local environment: Open your local `.env` file and set the + `AIGNOSTICS_SENTRY_DSN` variable to the value of the token from your + clipboard. You can check `.env.example` for the correct format. +4. For the test, preview and production stage: Goto + https://github.com/aignostics/python-sdk/settings/secrets/actions/new + and create a new repository secret called `AIGNOSTICS_SENTRY_DSN`, + pasting from your clipboard. + +## Logging and metrics with Logfire + +1. Goto https://pydantic.dev/logfire and sign-in - it's free for up to 10 + million spans/metrics per month. +2. Follow the instructions to create a new project and get the write token. Copy + the value of the token into your clipboard. +3. For your local environment: Open your local `.env` file and set the + `AIGNOSTICS_LOGFIRE_TOKEN` variable to the value of the token from + your clipboard. You can check `.env.example` for the correct format. +4. For the test, preview and production stage: Goto + https://github.com/aignostics/python-sdk/settings/secrets/actions/new + and create a new repository secret called `AIGNOSTICS_SENTRY_DSN`, + pasting from your clipboard. + +## Uptime monitoring with betterstack + +1. Goto https://betterstack.com/ and sign-in - it's free for up to 10 monitors + and one status page +2. Create a monitor pointing to the `/api/v1/healthz` endpoint of your API on + your production environment. +3. Create a status page in betterstack and add the monitor you created +4. Goto Advanced Settings / Github badge for your monitor on Betterstack and + copy the badge for yaml +5. Run copier update and paste the snippet when asked for it + +## Deploying webservice to Vercel as serverless function (optional) + +1. Ensure you enabled Vercel deployment when creating or updating the project. + If not, enable with `copier update` +2. Goto https://vercel.com/ and sign-in - it's free for solo devs and open + source projects +3. Execute `pnpm i -g vercel@latest` to install or update the Vercel CLI, see + https://vercel.com/docs/cli. +4. Execute `vercel login` to login to your Vercel account +5. In Vercel create a new project +6. Execute `vercel link` and link your repository to the newly created project +7. Execute `cat .vercel/project.json` to show the orgId and projectId +8. Goto + https://github.com/aignostics/python-sdk/settings/secrets/actions/new + and create a new repository secret called `VERCEL_ORG_ID`, copy and pasting + from the output of step 6. +9. Goto + https://github.com/aignostics/python-sdk/settings/secrets/actions/new + and create a new repository secret called `VERCEL_PROJECT_ID`, copy and + pasting from the output of step 6 +10. Goto `https://vercel.com/account/tokens` and create a new token called + `oe-python-template`. Copy the value of the token into your clipboard. +11. Goto + https://github.com/aignostics/python-sdk/settings/secrets/actions/new + and create a new repository secret called `VERCEL_TOKEN`, pasting from your + clipboard. +12. In your Vercel project go to Settings > Deployment Protection, enable + Protection Bypass for Automation, and copy the token it your clipboard. +13. Goto + https://github.com/aignostics/python-sdk/settings/secrets/actions/new + and create a new repository secret called `VERCEL_AUTOMATION_BYPASS_SECRET`, pasting from your + clipboard. This is so the smoke test post deploy via GitHub Action can validate + the deployment was successful. +14. Optional: In your Vercel project go to Settings > Environment Variables > Environments, and + add environment variables with key 'AIGNOSTICS_LOGFIRE_TOKEN' + and 'AIGNOSTICS_SENTRY_DSN' - check your `.env` file for the values + ## Polishing GitHub repository 1. Goto https://github.com/aignostics/python-sdk diff --git a/codegen/out/.openapi-generator/FILES b/codegen/out/.openapi-generator/FILES index 1a1f5837..b31b9c51 100644 --- a/codegen/out/.openapi-generator/FILES +++ b/codegen/out/.openapi-generator/FILES @@ -37,4 +37,3 @@ aignx/codegen/models/version_creation_response.py aignx/codegen/models/version_read_response.py aignx/codegen/rest.py docs/ExternalsApi.md -test/test_externals_api.py diff --git a/codegen/out/aignx/codegen/api/externals_api.py b/codegen/out/aignx/codegen/api/externals_api.py index 34da838a..4a9069a1 100644 --- a/codegen/out/aignx/codegen/api/externals_api.py +++ b/codegen/out/aignx/codegen/api/externals_api.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -3649,3 +3650,5 @@ def _register_version_v1_versions_post_serialize( _host=_host, _request_auth=_request_auth ) + + diff --git a/codegen/out/aignx/codegen/api_client.py b/codegen/out/aignx/codegen/api_client.py index 28ff5b57..5cfc4b77 100644 --- a/codegen/out/aignx/codegen/api_client.py +++ b/codegen/out/aignx/codegen/api_client.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference diff --git a/codegen/out/aignx/codegen/configuration.py b/codegen/out/aignx/codegen/configuration.py index 8657b694..07635c4c 100644 --- a/codegen/out/aignx/codegen/configuration.py +++ b/codegen/out/aignx/codegen/configuration.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference diff --git a/codegen/out/aignx/codegen/exceptions.py b/codegen/out/aignx/codegen/exceptions.py index c83a99c1..c5e6b23d 100644 --- a/codegen/out/aignx/codegen/exceptions.py +++ b/codegen/out/aignx/codegen/exceptions.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference diff --git a/codegen/out/aignx/codegen/models/application_read_response.py b/codegen/out/aignx/codegen/models/application_read_response.py index 0e7868ec..6bd4c16e 100644 --- a/codegen/out/aignx/codegen/models/application_read_response.py +++ b/codegen/out/aignx/codegen/models/application_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -90,3 +91,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "description": obj.get("description") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/application_run_status.py b/codegen/out/aignx/codegen/models/application_run_status.py index 15c12aa7..7c165877 100644 --- a/codegen/out/aignx/codegen/models/application_run_status.py +++ b/codegen/out/aignx/codegen/models/application_run_status.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -38,3 +39,5 @@ class ApplicationRunStatus(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of ApplicationRunStatus from a JSON string""" return cls(json.loads(json_str)) + + diff --git a/codegen/out/aignx/codegen/models/application_version.py b/codegen/out/aignx/codegen/models/application_version.py index 897acf35..e8a56270 100644 --- a/codegen/out/aignx/codegen/models/application_version.py +++ b/codegen/out/aignx/codegen/models/application_version.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -131,3 +132,5 @@ def to_dict(self) -> Optional[Union[Dict[str, Any], SlugVersionRequest, str]]: def to_str(self) -> str: """Returns the string representation of the actual instance""" return pprint.pformat(self.model_dump()) + + diff --git a/codegen/out/aignx/codegen/models/application_version_read_response.py b/codegen/out/aignx/codegen/models/application_version_read_response.py index 39569858..bac87039 100644 --- a/codegen/out/aignx/codegen/models/application_version_read_response.py +++ b/codegen/out/aignx/codegen/models/application_version_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -125,3 +126,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "output_artifacts": [OutputArtifactReadResponse.from_dict(_item) for _item in obj["output_artifacts"]] if obj.get("output_artifacts") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/http_validation_error.py b/codegen/out/aignx/codegen/models/http_validation_error.py index c4c2ccad..009df7c1 100644 --- a/codegen/out/aignx/codegen/models/http_validation_error.py +++ b/codegen/out/aignx/codegen/models/http_validation_error.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -90,3 +91,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "detail": [ValidationError.from_dict(_item) for _item in obj["detail"]] if obj.get("detail") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/input_artifact.py b/codegen/out/aignx/codegen/models/input_artifact.py index c9d22bf7..646b7289 100644 --- a/codegen/out/aignx/codegen/models/input_artifact.py +++ b/codegen/out/aignx/codegen/models/input_artifact.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -94,3 +95,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "metadata_schema": obj.get("metadata_schema") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/input_artifact_creation_request.py b/codegen/out/aignx/codegen/models/input_artifact_creation_request.py index 81dab994..c97cf129 100644 --- a/codegen/out/aignx/codegen/models/input_artifact_creation_request.py +++ b/codegen/out/aignx/codegen/models/input_artifact_creation_request.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -87,3 +88,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "metadata": obj.get("metadata") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/input_artifact_read_response.py b/codegen/out/aignx/codegen/models/input_artifact_read_response.py index 7c16a4cd..2f95578a 100644 --- a/codegen/out/aignx/codegen/models/input_artifact_read_response.py +++ b/codegen/out/aignx/codegen/models/input_artifact_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -94,3 +95,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "metadata_schema": obj.get("metadata_schema") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/input_artifact_schema_creation_request.py b/codegen/out/aignx/codegen/models/input_artifact_schema_creation_request.py index 1e18e972..ac0ebb60 100644 --- a/codegen/out/aignx/codegen/models/input_artifact_schema_creation_request.py +++ b/codegen/out/aignx/codegen/models/input_artifact_schema_creation_request.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -86,3 +87,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "metadata_schema": obj.get("metadata_schema") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/item_creation_request.py b/codegen/out/aignx/codegen/models/item_creation_request.py index bca56b62..2e77ef0e 100644 --- a/codegen/out/aignx/codegen/models/item_creation_request.py +++ b/codegen/out/aignx/codegen/models/item_creation_request.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -92,3 +93,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "input_artifacts": [InputArtifactCreationRequest.from_dict(_item) for _item in obj["input_artifacts"]] if obj.get("input_artifacts") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/item_result_read_response.py b/codegen/out/aignx/codegen/models/item_result_read_response.py index c5bf257d..a6e3093e 100644 --- a/codegen/out/aignx/codegen/models/item_result_read_response.py +++ b/codegen/out/aignx/codegen/models/item_result_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -106,3 +107,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "output_artifacts": [OutputArtifactResultReadResponse.from_dict(_item) for _item in obj["output_artifacts"]] if obj.get("output_artifacts") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/item_status.py b/codegen/out/aignx/codegen/models/item_status.py index 92f1064a..3a12d81f 100644 --- a/codegen/out/aignx/codegen/models/item_status.py +++ b/codegen/out/aignx/codegen/models/item_status.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -36,3 +37,5 @@ class ItemStatus(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of ItemStatus from a JSON string""" return cls(json.loads(json_str)) + + diff --git a/codegen/out/aignx/codegen/models/output_artifact.py b/codegen/out/aignx/codegen/models/output_artifact.py index ee4a3ae0..7df90d2f 100644 --- a/codegen/out/aignx/codegen/models/output_artifact.py +++ b/codegen/out/aignx/codegen/models/output_artifact.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -100,3 +101,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "visibility": obj.get("visibility") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/output_artifact_read_response.py b/codegen/out/aignx/codegen/models/output_artifact_read_response.py index 4e296bb3..3a1cf86a 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_read_response.py +++ b/codegen/out/aignx/codegen/models/output_artifact_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -97,3 +98,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "scope": obj.get("scope") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py b/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py index a1d9fa10..5507cfcc 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py +++ b/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -103,3 +104,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "download_url": obj.get("download_url") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/output_artifact_schema_creation_request.py b/codegen/out/aignx/codegen/models/output_artifact_schema_creation_request.py index d38bfb2d..4c948652 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_schema_creation_request.py +++ b/codegen/out/aignx/codegen/models/output_artifact_schema_creation_request.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -92,3 +93,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "metadata_schema": obj.get("metadata_schema") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/output_artifact_scope.py b/codegen/out/aignx/codegen/models/output_artifact_scope.py index b3359895..9aa4591c 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_scope.py +++ b/codegen/out/aignx/codegen/models/output_artifact_scope.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -32,3 +33,5 @@ class OutputArtifactScope(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of OutputArtifactScope from a JSON string""" return cls(json.loads(json_str)) + + diff --git a/codegen/out/aignx/codegen/models/output_artifact_visibility.py b/codegen/out/aignx/codegen/models/output_artifact_visibility.py index 5e72dccc..531a9789 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_visibility.py +++ b/codegen/out/aignx/codegen/models/output_artifact_visibility.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -32,3 +33,5 @@ class OutputArtifactVisibility(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of OutputArtifactVisibility from a JSON string""" return cls(json.loads(json_str)) + + diff --git a/codegen/out/aignx/codegen/models/payload_input_artifact.py b/codegen/out/aignx/codegen/models/payload_input_artifact.py index da82bcb6..24cd013a 100644 --- a/codegen/out/aignx/codegen/models/payload_input_artifact.py +++ b/codegen/out/aignx/codegen/models/payload_input_artifact.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -87,3 +88,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "download_url": obj.get("download_url") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/payload_item.py b/codegen/out/aignx/codegen/models/payload_item.py index 6ff5fc09..93fbcbae 100644 --- a/codegen/out/aignx/codegen/models/payload_item.py +++ b/codegen/out/aignx/codegen/models/payload_item.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -112,3 +113,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/payload_output_artifact.py b/codegen/out/aignx/codegen/models/payload_output_artifact.py index 8d6b98d5..90a07f79 100644 --- a/codegen/out/aignx/codegen/models/payload_output_artifact.py +++ b/codegen/out/aignx/codegen/models/payload_output_artifact.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -93,3 +94,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "metadata": TransferUrls.from_dict(obj["metadata"]) if obj.get("metadata") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/run_creation_request.py b/codegen/out/aignx/codegen/models/run_creation_request.py index 371f032f..b1565284 100644 --- a/codegen/out/aignx/codegen/models/run_creation_request.py +++ b/codegen/out/aignx/codegen/models/run_creation_request.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -96,3 +97,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "items": [ItemCreationRequest.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/run_creation_response.py b/codegen/out/aignx/codegen/models/run_creation_response.py index 295aace8..2772483c 100644 --- a/codegen/out/aignx/codegen/models/run_creation_response.py +++ b/codegen/out/aignx/codegen/models/run_creation_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -82,3 +83,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "application_run_id": obj.get("application_run_id") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/run_read_response.py b/codegen/out/aignx/codegen/models/run_read_response.py index f4653f19..7e8df261 100644 --- a/codegen/out/aignx/codegen/models/run_read_response.py +++ b/codegen/out/aignx/codegen/models/run_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -105,3 +106,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "triggered_by": obj.get("triggered_by") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/slug_version_request.py b/codegen/out/aignx/codegen/models/slug_version_request.py index 70ddb318..78d45d67 100644 --- a/codegen/out/aignx/codegen/models/slug_version_request.py +++ b/codegen/out/aignx/codegen/models/slug_version_request.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -92,3 +93,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "version": obj.get("version") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/transfer_urls.py b/codegen/out/aignx/codegen/models/transfer_urls.py index c202ff4a..f7c2e90c 100644 --- a/codegen/out/aignx/codegen/models/transfer_urls.py +++ b/codegen/out/aignx/codegen/models/transfer_urls.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -85,3 +86,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "download_url": obj.get("download_url") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/user_payload.py b/codegen/out/aignx/codegen/models/user_payload.py index de12f128..e6b58e13 100644 --- a/codegen/out/aignx/codegen/models/user_payload.py +++ b/codegen/out/aignx/codegen/models/user_payload.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -114,3 +115,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "items": [PayloadItem.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/validation_error.py b/codegen/out/aignx/codegen/models/validation_error.py index 6c2061b9..c2d41de2 100644 --- a/codegen/out/aignx/codegen/models/validation_error.py +++ b/codegen/out/aignx/codegen/models/validation_error.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -94,3 +95,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "type": obj.get("type") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/validation_error_loc_inner.py b/codegen/out/aignx/codegen/models/validation_error_loc_inner.py index 7a396747..b2c780be 100644 --- a/codegen/out/aignx/codegen/models/validation_error_loc_inner.py +++ b/codegen/out/aignx/codegen/models/validation_error_loc_inner.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -133,3 +134,5 @@ def to_dict(self) -> Optional[Union[Dict[str, Any], int, str]]: def to_str(self) -> str: """Returns the string representation of the actual instance""" return pprint.pformat(self.model_dump()) + + diff --git a/codegen/out/aignx/codegen/models/version_creation_request.py b/codegen/out/aignx/codegen/models/version_creation_request.py index b8366a1c..2dfc7257 100644 --- a/codegen/out/aignx/codegen/models/version_creation_request.py +++ b/codegen/out/aignx/codegen/models/version_creation_request.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -108,3 +109,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "output_artifacts": [OutputArtifactSchemaCreationRequest.from_dict(_item) for _item in obj["output_artifacts"]] if obj.get("output_artifacts") is not None else None }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/version_creation_response.py b/codegen/out/aignx/codegen/models/version_creation_response.py index f34891b5..c84ea15f 100644 --- a/codegen/out/aignx/codegen/models/version_creation_response.py +++ b/codegen/out/aignx/codegen/models/version_creation_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -82,3 +83,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "application_version_id": obj.get("application_version_id") }) return _obj + + diff --git a/codegen/out/aignx/codegen/models/version_read_response.py b/codegen/out/aignx/codegen/models/version_read_response.py index 66c0611c..52f01af2 100644 --- a/codegen/out/aignx/codegen/models/version_read_response.py +++ b/codegen/out/aignx/codegen/models/version_read_response.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference @@ -118,3 +119,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "created_at": obj.get("created_at") }) return _obj + + diff --git a/codegen/out/aignx/codegen/rest.py b/codegen/out/aignx/codegen/rest.py index a9c1d729..401902fb 100644 --- a/codegen/out/aignx/codegen/rest.py +++ b/codegen/out/aignx/codegen/rest.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ PAPI API Reference diff --git a/codegen/out/docs/ExternalsApi.md b/codegen/out/docs/ExternalsApi.md index 552d9cde..59e61f75 100644 --- a/codegen/out/docs/ExternalsApi.md +++ b/codegen/out/docs/ExternalsApi.md @@ -876,3 +876,4 @@ No authorization required **422** | Validation Error | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/compose.yaml b/compose.yaml index 3b3a4c2d..204084ca 100644 --- a/compose.yaml +++ b/compose.yaml @@ -3,15 +3,33 @@ services: build: . env_file: - path: .env - required: true + required: false develop: watch: - path: src action: rebuild - - path: codegen - action: rebuild restart: no profiles: - manual tty: true stdin_open: true + aignostics-api: + build: . + env_file: + - path: .env + required: false + develop: + watch: + - path: src + action: rebuild + command: serve --host=0.0.0.0 --port=8000 --no-watch + restart: always + ports: + - "8000:8000" + healthcheck: + test: [ "CMD", "curl", "-f", "http://127.0.0.1:8000/healthz" ] + interval: 5s + timeout: 2s + retries: 3 + start_period: 5s + start_interval: 1s diff --git a/docs/Makefile b/docs/Makefile index 4de76f95..3a741560 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -3,7 +3,7 @@ # You can set these variables from the command line, and also # from the environment for the first two. -SPHINXOPTS ?= -E -W --keep-going +SPHINXOPTS ?= -E --keep-going SPHINXBUILD ?= sphinx-build SOURCEDIR = source BUILDDIR = build diff --git a/docs/make.bat b/docs/make.bat index dc1312ab..747ffb7b 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,35 +1,35 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/partials/README_header.md b/docs/partials/README_header.md index 0b04981d..ae285fb9 100644 --- a/docs/partials/README_header.md +++ b/docs/partials/README_header.md @@ -1,7 +1,6 @@ # 🔬 Aignostics Python SDK -[![License](https://img.shields.io/github/license/aignostics/python-sdk?logo=opensourceinitiative&logoColor=3DA639&labelColor=414042&color=A41831) -](https://github.com/aignostics/python-sdk/blob/main/LICENSE) +[![License](https://img.shields.io/github/license/aignostics/python-sdk?logo=opensourceinitiative&logoColor=3DA639&labelColor=414042&color=A41831)](https://github.com/aignostics/python-sdk/blob/main/LICENSE) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aignostics.svg?logo=python&color=204361&labelColor=1E2933)](https://github.com/aignostics/python-sdk/blob/main/noxfile.py) [![CI](https://github.com/aignostics/python-sdk/actions/workflows/test-and-report.yml/badge.svg)](https://github.com/aignostics/python-sdk/actions/workflows/test-and-report.yml) [![Read the Docs](https://img.shields.io/readthedocs/aignostics)](https://aignostics.readthedocs.io/en/latest/) @@ -10,7 +9,6 @@ [![Maintainability](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk) [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk) - [![Dependabot](https://img.shields.io/badge/dependabot-active-brightgreen?style=flat-square&logo=dependabot)](https://github.com/aignostics/python-sdk/security/dependabot) [![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://github.com/aignostics/python-sdk/issues?q=is%3Aissue%20state%3Aopen%20Dependency%20Dashboard) [![Coverage](https://codecov.io/gh/aignostics/python-sdk/graph/badge.svg?token=SX34YRP30E)](https://codecov.io/gh/aignostics/python-sdk) @@ -25,6 +23,7 @@ [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template) [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE3IDE2VjdsLTYgNU0yIDlWOGwxLTFoMWw0IDMgOC04aDFsNCAyIDEgMXYxNGwtMSAxLTQgMmgtMWwtOC04LTQgM0gzbC0xLTF2LTFsMy0zIi8+PC9zdmc+)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/aignostics/python-sdk) [![Open in GitHub Codespaces](https://img.shields.io/static/v1?label=GitHub%20Codespaces&message=Open&color=blue&logo=github)](https://github.com/codespaces/new/aignostics/python-sdk) +[![Better Stack Badge](https://uptime.betterstack.com/status-badges/v1/monitor/1vtu1.svg)](https://aignostics.betteruptime.com/) > [!TIP] -> 📚 [Online documentation](https://aignostics.readthedocs.io/en/latest/) - 📖 [PDF Manual](https://aignostics.readthedocs.io/_/downloads/en/latest/pdf/) +> 📚 [Online documentation](https://aignostics.readthedocs.io/en/latest/) - 📖 +> [PDF Manual](https://aignostics.readthedocs.io/_/downloads/en/latest/pdf/) > [!NOTE] -> 🧠 This project was scaffolded using the template [oe-python-template](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template) with [copier](https://copier.readthedocs.io/). +> 🧠 This project was scaffolded using the template +> [oe-python-template](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template) +> with [copier](https://copier.readthedocs.io/). --- diff --git a/docs/source/_static/openapi_v1.json b/docs/source/_static/openapi_v1.json index 5c30db4f..03345399 100644 --- a/docs/source/_static/openapi_v1.json +++ b/docs/source/_static/openapi_v1.json @@ -1,3 +1,5 @@ +Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 +https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 { "openapi": "3.1.0", "info": { @@ -1910,3 +1912,6 @@ } } } +Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 +https://logfire-eu.pydantic.dev:443 "POST /v1/metrics HTTP/1.1" 200 2 +https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 diff --git a/docs/source/_static/openapi_v1.yaml b/docs/source/_static/openapi_v1.yaml index f2fa5837..55c430ff 100644 --- a/docs/source/_static/openapi_v1.yaml +++ b/docs/source/_static/openapi_v1.yaml @@ -1,3 +1,5 @@ +Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 +https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 components: schemas: ApplicationReadResponse: @@ -726,8 +728,7 @@ paths: - Externals /v1/applications/{application_id}/versions: get: - operationId: -list_versions_by_application_id_v1_applications__application_id__versions_get + operationId: list_versions_by_application_id_v1_applications__application_id__versions_get parameters: - in: path name: application_id @@ -790,8 +791,7 @@ list_versions_by_application_id_v1_applications__application_id__versions_get schema: items: $ref: '#/components/schemas/ApplicationVersionReadResponse' - title: Response List Versions By Application Id V1 Applications -Application + title: Response List Versions By Application Id V1 Applications Application Id Versions Get type: array description: Successful Response @@ -806,8 +806,7 @@ Application - Externals /v1/applications/{application_slug}: get: - operationId: -read_application_by_slug_v1_applications__application_slug__get + operationId: read_application_by_slug_v1_applications__application_slug__get parameters: - in: path name: application_slug @@ -833,9 +832,7 @@ read_application_by_slug_v1_applications__application_slug__get - Externals /v1/applications/{application_slug}/versions: get: - operationId: -list_versions_by_application_slug_v1_applications__application_slug__versions_ge -t + operationId: list_versions_by_application_slug_v1_applications__application_slug__versions_get parameters: - in: path name: application_slug @@ -898,8 +895,7 @@ t schema: items: $ref: '#/components/schemas/ApplicationVersionReadResponse' - title: Response List Versions By Application Slug V1 -Applications Application + title: Response List Versions By Application Slug V1 Applications Application Slug Versions Get type: array description: Successful Response @@ -1091,8 +1087,7 @@ Applications Application - Externals /v1/runs/{application_run_id}/results: delete: - operationId: -delete_run_results_v1_runs__application_run_id__results_delete + operationId: delete_run_results_v1_runs__application_run_id__results_delete parameters: - in: path name: application_run_id @@ -1190,8 +1185,7 @@ delete_run_results_v1_runs__application_run_id__results_delete schema: items: $ref: '#/components/schemas/ItemResultReadResponse' - title: Response List Run Results V1 Runs Application Run Id -Results + title: Response List Run Results V1 Runs Application Run Id Results Get type: array description: Successful Response @@ -1272,3 +1266,7 @@ Results - Externals servers: - url: '' +Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 +Starting new HTTPS connection (2): logfire-eu.pydantic.dev:443 +https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 +https://logfire-eu.pydantic.dev:443 "POST /v1/metrics HTTP/1.1" 200 2 diff --git a/docs/source/conf.py b/docs/source/conf.py index 16d885f2..dc7dc3eb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -9,7 +9,6 @@ "sphinx_toolbox.github", "sphinx_toolbox.source", "sphinx.ext.autodoc", - # "enum_tools.autoenum", # https://github.com/domdfcoding/enum_tools/tree/master # noqa: ERA001 "sphinx.ext.napoleon", # https://sphinxcontrib-napoleon.readthedocs.io/en/latest/ "sphinxcontrib.autodoc_pydantic", # https://autodoc-pydantic.readthedocs.io/en/stable/users/examples.html "sphinx.ext.coverage", diff --git a/docs/source/lib_reference.rst b/docs/source/lib_reference.rst index ff4b9dbf..6d9857bf 100644 --- a/docs/source/lib_reference.rst +++ b/docs/source/lib_reference.rst @@ -1,11 +1,17 @@ Library Reference ================= -.. automodule:: aignostics - :members: - .. automodule:: aignostics.client - :members: +:members: + +.. automodule:: aignostics.application +:members: -.. automodule:: aignx.codegen.api.externals_api - :members: +.. automodule:: aignostics.system +:members: + +.. automodule:: aignostics.utils +:members: + +.. automodule:: aignostics +:members: \ No newline at end of file diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index d76b3abd..831e3af8 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -1,4 +1,4 @@ Release Notes ============= -.. mdinclude:: ../../CHANGELOG.md \ No newline at end of file +.. mdinclude:: ../../CHANGELOG.md diff --git a/examples/notebook.ipynb b/examples/notebook.ipynb index 73b14a37..ff2ecaca 100644 --- a/examples/notebook.ipynb +++ b/examples/notebook.ipynb @@ -6,15 +6,18 @@ "metadata": {}, "outputs": [ { -"name": "stdout", -"output_type": "stream", -"text": [ -"Hello, world! The value of THE_VAR is not defined\n" +"data": { +"text/plain": [ +"'Hello, world!'" ] +}, +"execution_count": 1, +"metadata": {}, +"output_type": "execute_result" } ], "source": [ -"from aignostics import Service\n", +"from aignostics.hello import Service\n", "\n", "service = Service()\n", "message = service.get_hello_world()\n", diff --git a/examples/notebook.py b/examples/notebook.py index a0445b2b..60efe386 100644 --- a/examples/notebook.py +++ b/examples/notebook.py @@ -6,7 +6,7 @@ @app.cell def _(): - from aignostics import Service + from aignostics.hello import Service service = Service() message = service.get_hello_world() diff --git a/examples/script.py b/examples/script.py index bcfb5744..1201f94c 100644 --- a/examples/script.py +++ b/examples/script.py @@ -3,7 +3,7 @@ from dotenv import load_dotenv from rich.console import Console -from aignostics import Service +from aignostics.hello import Service console = Console() diff --git a/examples/streamlit.py b/examples/streamlit.py deleted file mode 100644 index b2e48d41..00000000 --- a/examples/streamlit.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Streamlit web application that demonstrates a simple interface for Aignostics Python SDK. - -This module creates a web interface using Streamlit to demonstrate the usage of the service provided by -Aignostics Python SDK. -""" - -import streamlit as st - -from aignostics import ( - Service, - __version__, -) - -sidebar = st.sidebar -sidebar.write( - f" [Aignostics Python SDK v{__version__}](https://aignostics.readthedocs.io/en/latest/)", -) -sidebar.write("Built with love in Berlin 🐻") - -st.title("🔬 Aignostics Python SDK ") - -# Initialize the service -service = Service() - -# Get the message -message = service.get_hello_world() - -# Print the message -st.write(f"{message}") diff --git a/noxfile.py b/noxfile.py index 32edf5b7..3b2ca886 100644 --- a/noxfile.py +++ b/noxfile.py @@ -262,7 +262,7 @@ def _generate_openapi_schemas(session: nox.Session) -> None: Path("docs/source/_static").mkdir(parents=True, exist_ok=True) formats = { - "yaml": {"ext": "yaml", "args": []}, + "yaml": {"ext": "yaml", "args": ["--output-format=yaml"]}, "json": {"ext": "json", "args": ["--output-format=json"]}, } @@ -272,7 +272,7 @@ def _generate_openapi_schemas(session: nox.Session) -> None: with output_path.open("w", encoding="utf-8") as f: cmd_args = [ "aignostics", - "platform", + "system", "openapi", f"--api-version={version}", *format_info["args"], @@ -465,12 +465,46 @@ def docs_pdf(session: nox.Session) -> None: @nox.session(python=["3.11", "3.12", "3.13"]) def test(session: nox.Session) -> None: """Run tests with pytest.""" - _setup_venv(session, True) + _setup_venv(session) + session.run("rm", "-rf", ".coverage", external=True) + + # Build pytest arguments with skip_with_act filter if needed pytest_args = ["pytest", "--disable-warnings", JUNIT_XML, "-n", "auto", "--dist", "loadgroup"] if _is_act_environment(): pytest_args.extend(["-k", NOT_SKIP_WITH_ACT]) + pytest_args.extend(["-m", "not sequential"]) + pytest_args.extend(session.posargs) + session.run(*pytest_args) + # Sequential tests + sequential_args = [ + "pytest", + "--cov-append", + "--disable-warnings", + JUNIT_XML, + "-n", + "auto", + "--dist", + "loadgroup", + ] + if _is_act_environment(): + sequential_args.extend(["-k", NOT_SKIP_WITH_ACT]) + sequential_args.extend(["-m", "sequential"]) + sequential_args.extend(session.posargs) + + session.run(*sequential_args) + + session.run( + "bash", + "-c", + ( + "docker compose ls --format json | jq -r '.[].Name' | " + "grep ^pytest | xargs -I {} docker compose -p {} down --remove-orphans" + ), + external=True, + ) + @nox.session(python=["3.13"], default=False) def setup(session: nox.Session) -> None: diff --git a/pyproject.toml b/pyproject.toml index 053d5659..de98508a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,9 +63,22 @@ requires-python = ">=3.11, <4.0" dependencies = [ # From Template - "pydantic>=2.11.1", + "fastapi[standard,all]>=0.115.12", + "logfire[system-metrics]>=3.13.1", + "opentelemetry-instrumentation-fastapi>=0.53b0", + "opentelemetry-instrumentation-httpx>=0.53b0", + "opentelemetry-instrumentation-jinja2>=0.53b0", + "opentelemetry-instrumentation-requests>=0.53b0", + "opentelemetry-instrumentation-sqlite3>=0.53b0", + "opentelemetry-instrumentation-tornado>=0.53b0", + "opentelemetry-instrumentation-urllib>=0.53b0", + "opentelemetry-instrumentation-urllib3>=0.53b0", + "psutil>=7.0.0", + "pydantic>=2.11.3", "pydantic-settings>=2.8.1", + "sentry-sdk>=2.25.1", "typer>=0.15.1", + "uptime>=3.0.1", # Custom "appdirs>=1.4.4", "google-cloud-storage>=3.1.0", @@ -74,7 +87,8 @@ dependencies = [ "jsf>=0.11.2", "jsonschema>=4.23.0", "pyjwt[crypto]>=2.10.1", - "python-dotenv>=1.1.0", # Can be removed later + "python-dateutil>=2.9.0.post0", + "pyyaml>=6.0", "requests>=2.32.3", "requests-oauthlib>=2.0.0", "tqdm>=4.67.1", @@ -105,12 +119,12 @@ packages = ["src/aignostics", "codegen/out/aignx"] [project.optional-dependencies] examples = [ "streamlit>=1.44.1", - "marimo>=0.12.2", + "marimo>=0.12.8", "jupyter>=1.1.1", "jinja2>=3.1.6", ] -# formats = ["openslide-python>=1.4.1", "openslide-bin>=4.0.0.6"] aws = ["boto3>=1.37.27"] +# formats = ["openslide-python>=1.4.1", "openslide-bin>=4.0.0.6"] [dependency-groups] dev = [ @@ -124,20 +138,20 @@ dev = [ "matplotlib>=3.10.1", "mypy>=1.5.0", "nox[uv]>=2025.2.9", - "pip-audit>=2.8.0", + "pip-audit>=2.9.0", "pip-licenses @ git+https://github.com/neXenio/pip-licenses.git@master", # https://github.com/raimon49/pip-licenses/pull/224 "pre-commit>=4.1.0", - "pyright>=1.1.398", + "pyright>=1.1.399", "pytest>=8.3.5", "pytest-asyncio>=0.26.0", - "pytest-cov>=6.1.0", - "pytest-docker>=3.2.0", + "pytest-cov>=6.1.1", + "pytest-docker>=3.2.1", "pytest-env>=1.1.5", "pytest-regressions>=2.7.0", "pytest-subprocess>=1.5.3", "pytest-timeout>=2.3.1", "pytest-xdist[psutil]>=3.6.1", - "ruff>=0.11.2", + "ruff>=0.11.5", "sphinx>=8.2.3", "sphinx-autobuild>=2024.10.3", "sphinx-copybutton>=0.5.2", @@ -168,8 +182,9 @@ line-length = 120 extend-exclude = [ ".fixme", "notebook.py", - "playbook.py", # TODO (Helmut): refactor that code and reenable - "codegen", # TODO (Helmut): check if codegen can be tweaked to generate better code + "template/*.py", + "playbook.py", # TODO (Andreas): refactor and reenable, + "codegen", ] [tool.ruff.lint] @@ -199,7 +214,7 @@ ignore = [ ] [tool.ruff.lint.per-file-ignores] -"tests/**/*.py" = [ +"**/tests/**/*.py" = [ # we are more relaxed in tests, while sill applying hundreds of rules "S101", # asserts allowed in tests... "ARG", # unused function args -> fixtures nevertheless are functionally relevant... @@ -263,10 +278,12 @@ asyncio_default_fixture_loop_scope = "function" env = ["COVERAGE_FILE=.coverage", "COVERAGE_PROCESS_START=pyproject.toml"] markers = [ # From Template - "no_extras: tests that do require no extras installed", - "scheduled: tests to run on a schedule", - "sequential: exclude from parallel test execution", - "skip_with_act: don't run with act", + "no_extras: Tests that do require no extras installed.", + "scheduled: Tests to run on a schedule. They will still be part on non-scheduled test executions.", + "sequential: Exclude from parallel test execution.", + "skip_with_act: Don't run with act.", + "docker: tests That require Docker.", + "long_running: Tests that take a long time to run. Tests marked as long runing excluded from execution by default. Enable by passing any -m your_marker that matches a marker of the test.", # Custom # Nothing yet ] diff --git a/sitecustomize.py b/sitecustomize.py new file mode 100644 index 00000000..9302f6b1 --- /dev/null +++ b/sitecustomize.py @@ -0,0 +1,5 @@ +"""Site customization module to enable test coverage computation in subprocesses.""" + +import coverage + +coverage.process_startup() diff --git a/sonar-project.properties b/sonar-project.properties index 6ccf0488..cbda81b8 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -8,6 +8,5 @@ sonar.links.ci=https://github.com/aignostics/python-sdk/actions sonar.links.issues=https://github.com/aignostics/python-sdk/issues sonar.python.coverage.reportPaths=reports/coverage.xml sonar.python.version=3.11, 3.12, 3.13 -sonar.coverage.exclusions=noxfile.py, tests/**, examples/**, docs/**, codegen/** -sonar.exclusions=examples/**, docs/**, codegen/** -sonar.cpd.exclusions=noxfile.py +sonar.coverage.exclusions=noxfile.py, template/**, tests/**, examples/**, docs/**, dist/**, dist_vercel/**, codegen/** +sonar.exclusions=template/**, examples/**, docs/**, dist/**, dist_vercel/**, codegen/** \ No newline at end of file diff --git a/src/aignostics/__init__.py b/src/aignostics/__init__.py index ff6f960d..2e4b3883 100644 --- a/src/aignostics/__init__.py +++ b/src/aignostics/__init__.py @@ -1,68 +1,6 @@ -"""Python SDK providing access to Aignostics AI services.""" +"""Copier template to scaffold Python projects compliant with best practices and modern tooling.""" -from .constants import ( - API_ROOT_DEV, - API_ROOT_PRODUCTION, - API_ROOT_STAGING, - AUDIENCE_DEV, - AUDIENCE_PRODUCTION, - AUDIENCE_STAGING, - AUTHORIZATION_BASE_URL_DEV, - AUTHORIZATION_BASE_URL_PRODUCTION, - AUTHORIZATION_BASE_URL_STAGING, - DEVICE_URL_DEV, - DEVICE_URL_PRODUCTION, - DEVICE_URL_STAGING, - JWS_JSON_URL_DEV, - JWS_JSON_URL_PRODUCTION, - JWS_JSON_URL_STAGING, - REDIRECT_URI_DEV, - REDIRECT_URI_PRODUCTION, - REDIRECT_URI_STAGING, - TOKEN_URL_DEV, - TOKEN_URL_PRODUCTION, - TOKEN_URL_STAGING, - __project_name__, - __project_path__, - __version__, -) -from .exceptions import OpenAPISchemaError -from .models import Health, HealthStatus -from .platform import Platform -from .types import APIVersion, InfoOutputFormat, JsonType, JsonValue, OpenAPIOutputFormat +from .constants import MODULES_TO_INSTRUMENT +from .utils.boot import boot -__all__ = [ - "API_ROOT_DEV", - "API_ROOT_PRODUCTION", - "API_ROOT_STAGING", - "AUDIENCE_DEV", - "AUDIENCE_PRODUCTION", - "AUDIENCE_STAGING", - "AUTHORIZATION_BASE_URL_DEV", - "AUTHORIZATION_BASE_URL_PRODUCTION", - "AUTHORIZATION_BASE_URL_STAGING", - "DEVICE_URL_DEV", - "DEVICE_URL_PRODUCTION", - "DEVICE_URL_STAGING", - "JWS_JSON_URL_DEV", - "JWS_JSON_URL_PRODUCTION", - "JWS_JSON_URL_STAGING", - "REDIRECT_URI_DEV", - "REDIRECT_URI_PRODUCTION", - "REDIRECT_URI_STAGING", - "TOKEN_URL_DEV", - "TOKEN_URL_PRODUCTION", - "TOKEN_URL_STAGING", - "APIVersion", - "Health", - "HealthStatus", - "InfoOutputFormat", - "JsonType", - "JsonValue", - "OpenAPIOutputFormat", - "OpenAPISchemaError", - "Platform", - "__project_name__", - "__project_path__", - "__version__", -] +boot(modules_to_instrument=MODULES_TO_INSTRUMENT) diff --git a/src/aignostics/application/__init__.py b/src/aignostics/application/__init__.py new file mode 100644 index 00000000..7a274f1c --- /dev/null +++ b/src/aignostics/application/__init__.py @@ -0,0 +1,7 @@ +"""Application module.""" + +from ._cli import cli + +__all__ = [ + "cli", +] diff --git a/src/aignostics/application/_cli.py b/src/aignostics/application/_cli.py new file mode 100644 index 00000000..a861a301 --- /dev/null +++ b/src/aignostics/application/_cli.py @@ -0,0 +1,107 @@ +"""CLI (Command Line Interface) of Aignostics Python SDK.""" + +import typer + +import aignostics.client +from aignostics.utils import console, get_logger + +logger = get_logger(__name__) + +cli = typer.Typer(name="application", help="Application commands") + +bucket_app = typer.Typer() +cli.add_typer(bucket_app, name="bucket", help="Transfer bucket provide by platform") + +datasset_app = typer.Typer() +cli.add_typer(datasset_app, name="dataset", help="Datasets for use as input for applications") + +metadata_app = typer.Typer() +cli.add_typer(metadata_app, name="metadata", help="Metadata required as input for applications") + +run_app = typer.Typer() +cli.add_typer(run_app, name="run", help="Runs of applications") + +result_app = typer.Typer() +run_app.add_typer(result_app, name="result", help="Results of applications runs") + + +@bucket_app.command("ls") +def bucket_ls() -> None: + """List contents of tranfer bucket.""" + console.print("bucket ls") + + +@bucket_app.command("purge") +def bucket_purge() -> None: + """Purge content of transfer bucket.""" + console.print("bucket purged.") + + +@cli.command("list") +def application_list() -> None: + """List available applications.""" + client = aignostics.client.Client() + applications = client.applications.list() + console.print(applications) + + +@cli.command("describe") +def application_describe() -> None: + """Describe application.""" + console.print("describe application") + + +@datasset_app.command("download") +def dataset_download() -> None: + """Download dataset.""" + console.print("dataset download") + + +@metadata_app.command("generate") +def metadata_generate() -> None: + """Generate metadata.""" + console.print("generate metadata") + + +@run_app.command("submit") +def run_submit() -> None: + """Create run.""" + console.print("submit run") + + +@run_app.command("list") +def run_list() -> None: + """List runs.""" + client = aignostics.client.Client() + runs = client.runs.list() + console.print(runs) + + +@run_app.command("describe") +def run_describe() -> None: + """Describe run.""" + console.print("The run") + + +@run_app.command("cancel") +def run_cancel() -> None: + """Cancel run.""" + console.print("canceled run") + + +@result_app.command("describe") +def result_describe() -> None: + """Describe the result of an application run.""" + console.print("describe result") + + +@result_app.command("download") +def result_download() -> None: + """Download the result of an application run.""" + console.print("download result") + + +@result_app.command("delete") +def result_delete() -> None: + """Delete the result of an application run.""" + console.print("delete resuilt") diff --git a/src/aignostics/cli.py b/src/aignostics/cli.py index 8936a522..df05e0b4 100644 --- a/src/aignostics/cli.py +++ b/src/aignostics/cli.py @@ -1,172 +1,22 @@ """CLI (Command Line Interface) of Aignostics Python SDK.""" -from typing import Annotated +import sys import typer -import yaml -import aignostics.client +from .constants import MODULES_TO_INSTRUMENT +from .utils import __version__, boot, console, get_logger, prepare_cli -from . import APIVersion, InfoOutputFormat, OpenAPIOutputFormat, Platform, __version__ -from .utils import console, prepare_cli +boot(MODULES_TO_INSTRUMENT) +logger = get_logger(__name__) -_platform = Platform() -cli = typer.Typer(help="Command Line Interface of the aignostics platform") - -platform_app = typer.Typer() -cli.add_typer(platform_app, name="platform", help="Platform diagnostics and utilities") - -bucket_app = typer.Typer() -platform_app.add_typer(bucket_app, name="bucket", help="Transfer bucket provide by platform") - -application_app = typer.Typer() -cli.add_typer(application_app, name="application", help="aignostics applications") - -datasset_app = typer.Typer() -application_app.add_typer(datasset_app, name="dataset", help="Datasets for use as input for applications") - -metadata_app = typer.Typer() -application_app.add_typer(metadata_app, name="metadata", help="Metadata required as input for applications") - -run_app = typer.Typer() -application_app.add_typer(run_app, name="run", help="Runs of applications") - -result_app = typer.Typer() -run_app.add_typer(result_app, name="result", help="Results of applications runs") - - -@platform_app.command("install") -def install() -> None: - """Complete and validate installation of the CLI.""" - _platform.install() - - -@platform_app.command("health") -def health() -> None: - """Indicate if aignostics platform is healthy.""" - console.print(_platform.healthy()) - - -@platform_app.command("info") -def info( - output_format: Annotated[ - InfoOutputFormat, typer.Option(help="Output format", case_sensitive=False) - ] = InfoOutputFormat.YAML, - env: Annotated[bool, typer.Option(help="Include environment variables in output")] = False, - filter_secrets: Annotated[bool, typer.Option(help="Filter out secret values from environment variables")] = True, -) -> None: - """Print info about service configuration.""" - info = _platform.info(env=env, filter_secrets=filter_secrets) - match output_format: - case InfoOutputFormat.JSON: - console.print_json(data=info) - case InfoOutputFormat.YAML: - console.print(yaml.dump(info, default_flow_style=False), end="") - - -@platform_app.command("openapi") -def openapi( - api_version: Annotated[APIVersion, typer.Option(help="API Version", case_sensitive=False)] = APIVersion.V1, - output_format: Annotated[ - OpenAPIOutputFormat, typer.Option(help="Output format", case_sensitive=False) - ] = OpenAPIOutputFormat.YAML, -) -> None: - """Dump the OpenAPI specification of to stdout.""" - match api_version: - case APIVersion.V1: - schema = Platform.openapi_schema() - match output_format: - case OpenAPIOutputFormat.JSON: - console.print_json(data=schema) - case OpenAPIOutputFormat.YAML: - console.print(yaml.dump(schema, default_flow_style=False), end="") - - -@bucket_app.command("ls") -def bucket_ls() -> None: - """List contents of tranfer bucket.""" - console.print("bucket ls") - - -@bucket_app.command("purge") -def bucket_purge() -> None: - """Purge content of transfer bucket.""" - console.print("bucket purged.") - - -@application_app.command("list") -def application_list() -> None: - """List available applications.""" - papi_client = aignostics.client.Client() - applications = papi_client.applications.list() - console.print(applications) - - -@application_app.command("describe") -def application_describe() -> None: - """Describe application.""" - papi_client = aignostics.client.Client() - applications = papi_client.applications.list() - console.print(applications) - - -@datasset_app.command("download") -def dataset_download() -> None: - """Download dataset.""" - console.print("dataset download") - - -@metadata_app.command("generate") -def metadata_generate() -> None: - """Generate metadata.""" - console.print("generate metadata") - - -@run_app.command("submit") -def run_submit() -> None: - """Create run.""" - console.print("submit run") - - -@run_app.command("list") -def run_list() -> None: - """List runs.""" - papi_client = aignostics.client.Client() - runs = papi_client.runs.list() - console.print(runs) - - -@run_app.command("describe") -def run_describe() -> None: - """Describe run.""" - console.print("The run") - - -@run_app.command("cancel") -def run_cancel() -> None: - """Cancel run.""" - console.print("canceled run") - - -@result_app.command("describe") -def result_describe() -> None: - """Describe the result of an application run.""" - console.print("describe result") - - -@result_app.command("download") -def result_download() -> None: - """Download the result of an application run.""" - console.print("download result") - - -@result_app.command("delete") -def result_delete() -> None: - """Delete the result of an application run.""" - console.print("delete resuilt") - - -prepare_cli(cli, f"🔬 Aignostics Python SDK v{__version__} - built with love in Berlin 🐻") +cli = typer.Typer(help="Command Line Interface of ") +prepare_cli(cli, f"🧠 Aignostics Python SDK v{__version__} - built with love in Berlin 🐻") if __name__ == "__main__": # pragma: no cover - cli() # pragma: no cover + try: + cli() + except Exception as e: # noqa: BLE001 + logger.critical("Fatal error occurred: %s", e) + console.print(f"Fatal error occurred: {e}", style="error") + sys.exit(1) diff --git a/src/aignostics/client/__init__.py b/src/aignostics/client/__init__.py index 25bb963c..7751e43f 100644 --- a/src/aignostics/client/__init__.py +++ b/src/aignostics/client/__init__.py @@ -6,13 +6,64 @@ for all interactions with the Aignostics platform. """ -from aignostics.client._client import Client -from aignostics.client._messages import AUTHENTICATION_FAILED, NOT_YET_IMPLEMENTED -from aignostics.client._settings import authentication_settings +from ._client import Client +from ._constants import ( + API_ROOT_DEV, + API_ROOT_PRODUCTION, + API_ROOT_STAGING, + AUDIENCE_DEV, + AUDIENCE_PRODUCTION, + AUDIENCE_STAGING, + AUTHORIZATION_BASE_URL_DEV, + AUTHORIZATION_BASE_URL_PRODUCTION, + AUTHORIZATION_BASE_URL_STAGING, + DEVICE_URL_DEV, + DEVICE_URL_PRODUCTION, + DEVICE_URL_STAGING, + JWS_JSON_URL_DEV, + JWS_JSON_URL_PRODUCTION, + JWS_JSON_URL_STAGING, + REDIRECT_URI_DEV, + REDIRECT_URI_PRODUCTION, + REDIRECT_URI_STAGING, + TOKEN_URL_DEV, + TOKEN_URL_PRODUCTION, + TOKEN_URL_STAGING, +) +from ._messages import AUTHENTICATION_FAILED, NOT_YET_IMPLEMENTED, UNKNOWN_ENDPOINT_URL +from ._settings import Settings, settings +from ._utils import calculate_file_crc32c, download_file, mime_type_to_file_ending __all__ = [ + "API_ROOT_DEV", + "API_ROOT_PRODUCTION", + "API_ROOT_STAGING", + "AUDIENCE_DEV", + "AUDIENCE_PRODUCTION", + "AUDIENCE_STAGING", "AUTHENTICATION_FAILED", + "AUTHORIZATION_BASE_URL_DEV", + "AUTHORIZATION_BASE_URL_PRODUCTION", + "AUTHORIZATION_BASE_URL_STAGING", + "DEVICE_URL_DEV", + "DEVICE_URL_PRODUCTION", + "DEVICE_URL_STAGING", + "JWS_JSON_URL_DEV", + "JWS_JSON_URL_PRODUCTION", + "JWS_JSON_URL_STAGING", "NOT_YET_IMPLEMENTED", + "NOT_YET_IMPLEMENTED", + "REDIRECT_URI_DEV", + "REDIRECT_URI_PRODUCTION", + "REDIRECT_URI_STAGING", + "TOKEN_URL_DEV", + "TOKEN_URL_PRODUCTION", + "TOKEN_URL_STAGING", + "UNKNOWN_ENDPOINT_URL", "Client", - "authentication_settings", + "Settings", + "calculate_file_crc32c", + "download_file", + "mime_type_to_file_ending", + "settings", ] diff --git a/src/aignostics/client/_authentication.py b/src/aignostics/client/_authentication.py index f4c290b9..a1a8afa1 100644 --- a/src/aignostics/client/_authentication.py +++ b/src/aignostics/client/_authentication.py @@ -13,7 +13,7 @@ from requests_oauthlib import OAuth2Session from ._messages import AUTHENTICATION_FAILED, INVALID_REDIRECT_URI -from ._settings import authentication_settings +from ._settings import settings class AuthenticationResult(BaseModel): @@ -36,8 +36,8 @@ def get_token(use_cache: bool = True) -> str: Raises: RuntimeError: If token retrieval fails. """ - if use_cache and authentication_settings().token_file.exists(): - stored_token = Path(authentication_settings().token_file).read_text(encoding="utf-8") + if use_cache and settings().token_file.exists(): + stored_token = Path(settings().token_file).read_text(encoding="utf-8") # Parse stored string "token:expiry_timestamp" parts = stored_token.split(":") token, expiry_str = parts @@ -57,8 +57,8 @@ def get_token(use_cache: bool = True) -> str: # Store new token with expiry if use_cache: timestamp = claims["exp"] - authentication_settings().token_file.parent.mkdir(parents=True, exist_ok=True) - Path(authentication_settings().token_file).write_text(f"{new_token}:{timestamp}", encoding="utf-8") + settings().token_file.parent.mkdir(parents=True, exist_ok=True) + Path(settings().token_file).write_text(f"{new_token}:{timestamp}", encoding="utf-8") return new_token @@ -76,7 +76,7 @@ def _authenticate() -> str: RuntimeError: If authentication fails. AssertionError: If the returned token doesn't have the expected format. """ - if refresh_token := authentication_settings().refresh_token: + if refresh_token := settings().refresh_token: token = _token_from_refresh_token(refresh_token) elif _can_open_browser(): token = _perform_authorization_code_with_pkce_flow() @@ -100,14 +100,14 @@ def verify_and_decode_token(token: str) -> dict[str, str]: Raises: RuntimeError: If token verification or decoding fails. """ - jwk_client = jwt.PyJWKClient(authentication_settings().jws_json_url) + jwk_client = jwt.PyJWKClient(settings().jws_json_url) try: # Get the public key from the JWK client key = jwk_client.get_signing_key_from_jwt(token).key # Verify and decode the token using the public key return t.cast( "dict[str, str]", - jwt.decode(token, key=key, algorithms=["RS256"], audience=authentication_settings().audience), + jwt.decode(token, key=key, algorithms=["RS256"], audience=settings().audience), ) except jwt.exceptions.PyJWTError as e: raise RuntimeError(AUTHENTICATION_FAILED) from e @@ -142,15 +142,15 @@ def _perform_authorization_code_with_pkce_flow() -> str: RuntimeError: If authentication fails. """ session = OAuth2Session( - authentication_settings().client_id_interactive.get_secret_value(), - scope=authentication_settings().scope_elements, - redirect_uri=authentication_settings().redirect_uri, + settings().client_id_interactive.get_secret_value(), + scope=settings().scope_elements, + redirect_uri=settings().redirect_uri, pkce="S256", ) authorization_url, _ = session.authorization_url( - authentication_settings().authorization_base_url, + settings().authorization_base_url, access_type="offline", - audience=authentication_settings().audience, + audience=settings().audience, ) authentication_result = AuthenticationResult() @@ -171,7 +171,7 @@ def do_GET(self) -> None: # noqa: N802 auth_code = query["code"][0] try: # Exchange code for token - token = session.fetch_token(authentication_settings().token_url, code=auth_code, include_client_id=True) + token = session.fetch_token(settings().token_url, code=auth_code, include_client_id=True) # Store the token authentication_result.token = token["access_token"] # Send success response @@ -204,10 +204,12 @@ def log_message(self, _format: str, *_args) -> None: # type: ignore[no-untyped- return # Create and start the server - parsed_redirect = parse.urlparse(authentication_settings().redirect_uri) + parsed_redirect = parse.urlparse(settings().redirect_uri) host, port = parsed_redirect.hostname, parsed_redirect.port if not host or not port: raise RuntimeError(INVALID_REDIRECT_URI) + # TODO(Andreas): This fails if the application runs multiple times in parallel, which is quite an issue. + # At least we must fail with better info for the user, and actually block another run with HTTPServer((host, port), OAuthCallbackHandler) as server: # Call Auth0 with challenge and redirect to localhost with code after successful authN webbrowser.open_new(authorization_url) @@ -233,13 +235,13 @@ def _perform_device_flow() -> str | None: RuntimeError: If authentication fails or is denied. """ response = requests.post( - authentication_settings().device_url, + settings().device_url, data={ - "client_id": authentication_settings().client_id_device.get_secret_value(), - "scope": authentication_settings().scope_elements, - "audience": authentication_settings().audience, + "client_id": settings().client_id_device.get_secret_value(), + "scope": settings().scope_elements, + "audience": settings().audience, }, - timeout=authentication_settings().request_timeout_seconds, + timeout=settings().request_timeout_seconds, ) try: response.raise_for_status() @@ -259,14 +261,14 @@ def _perform_device_flow() -> str | None: while True: try: json_response = requests.post( - authentication_settings().token_url, + settings().token_url, headers={"Accept": "application/json"}, data={ "grant_type": "urn:ietf:params:oauth:grant-type:device_code", "device_code": device_code, - "client_id": authentication_settings().client_id_device.get_secret_value(), + "client_id": settings().client_id_device.get_secret_value(), }, - timeout=authentication_settings().request_timeout_seconds, + timeout=settings().request_timeout_seconds, ).json() if "error" in json_response: if json_response["error"] in {"authorization_pending", "slow_down"}: @@ -296,14 +298,14 @@ def _token_from_refresh_token(refresh_token: SecretStr) -> str | None: """ try: response = requests.post( - authentication_settings().token_url, + settings().token_url, headers={"Accept": "application/json"}, data={ "grant_type": "refresh_token", - "client_id": authentication_settings().client_id_interactive.get_secret_value(), + "client_id": settings().client_id_interactive.get_secret_value(), "refresh_token": refresh_token.get_secret_value(), }, - timeout=authentication_settings().request_timeout_seconds, + timeout=settings().request_timeout_seconds, ) response.raise_for_status() return t.cast("str", response.json()["access_token"]) diff --git a/src/aignostics/client/_client.py b/src/aignostics/client/_client.py index a23ddfea..44bb52c9 100644 --- a/src/aignostics/client/_client.py +++ b/src/aignostics/client/_client.py @@ -6,7 +6,8 @@ from aignostics.client.resources.applications import Applications, Versions from aignostics.client.resources.runs import Runs -from ._settings import authentication_settings +from ._constants import API_ROOT_DEV, API_ROOT_PRODUCTION, API_ROOT_STAGING +from ._settings import settings class Client: @@ -47,9 +48,30 @@ def get_api_client(cache_token: bool = True) -> ExternalsApi: token = get_token(use_cache=cache_token) client = ApiClient( Configuration( - host=authentication_settings().api_root, + host=settings().api_root, ), header_name="Authorization", header_value=f"Bearer {token}", ) return ExternalsApi(client) + + @staticmethod + def get_info() -> dict[str, dict]: # type: ignore[type-arg] + """Retrieves process information. + + Returns: + dict[str, dict]: Process information including platform API roots. + """ + return { + "platform": { + "production": { + "API_ROOT": API_ROOT_PRODUCTION, + }, + "staging": { + "API_ROOT": API_ROOT_STAGING, + }, + "dev": { + "API_ROOT": API_ROOT_DEV, + }, + } + } diff --git a/src/aignostics/client/_constants.py b/src/aignostics/client/_constants.py new file mode 100644 index 00000000..ab2c9143 --- /dev/null +++ b/src/aignostics/client/_constants.py @@ -0,0 +1,28 @@ +"""Client specific constants.""" + +TODO_URL = "https://todo" +API_ROOT_PRODUCTION = "https://platform.aignostics.com" +AUDIENCE_PRODUCTION = "https://aignostics-platform-samia" +AUTHORIZATION_BASE_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/authorize" +TOKEN_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/oauth/token" # noqa: S105 +REDIRECT_URI_PRODUCTION = "http://localhost:8080/" +DEVICE_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/oauth/device/code" +JWS_JSON_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/.well-known/jwks.json" + + +API_ROOT_STAGING = "https://platform-staging.aignostics.com" +# TODO (Andreas): hhva: please fill in +AUDIENCE_STAGING = TODO_URL +AUTHORIZATION_BASE_URL_STAGING = TODO_URL +TOKEN_URL_STAGING = TODO_URL +REDIRECT_URI_STAGING = TODO_URL +DEVICE_URL_STAGING = TODO_URL +JWS_JSON_URL_STAGING = TODO_URL + +API_ROOT_DEV = "https://platform-dev.aignostics.com" +AUDIENCE_DEV = "https://dev-8ouohmmrbuh2h4vu-samia" +AUTHORIZATION_BASE_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/authorize" +TOKEN_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/oauth/token" # noqa: S105 +REDIRECT_URI_DEV = "http://localhost:8080/" +DEVICE_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/oauth/device/code" +JWS_JSON_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/.well-known/jwks.json" diff --git a/src/aignostics/client/_settings.py b/src/aignostics/client/_settings.py index ef33e338..aaeebf08 100644 --- a/src/aignostics/client/_settings.py +++ b/src/aignostics/client/_settings.py @@ -1,11 +1,17 @@ +"""Settings of the Python SDK.""" + +import logging import os from pathlib import Path +from typing import Annotated, TypeVar import appdirs -from pydantic import SecretStr, computed_field, model_validator +from pydantic import Field, PlainSerializer, SecretStr, computed_field, model_validator from pydantic_settings import BaseSettings, SettingsConfigDict -from aignostics import ( +from aignostics.utils import OpaqueSettings, __project_name__, load_settings + +from ._constants import ( API_ROOT_PRODUCTION, AUDIENCE_DEV, AUDIENCE_PRODUCTION, @@ -25,32 +31,81 @@ TOKEN_URL_DEV, TOKEN_URL_PRODUCTION, TOKEN_URL_STAGING, - __project_name__, ) - from ._messages import UNKNOWN_ENDPOINT_URL +logger = logging.getLogger(__name__) + +T = TypeVar("T", bound=BaseSettings) + + +class Settings(OpaqueSettings): + """Configuration settings for the Aignostics SDK. + + This class handles configuration settings loaded from environment variables, + configuration files, or default values. It manages authentication endpoints, + client credentials, token storage, and other SDK behaviors. + + Attributes: + client_id_device (SecretStr): Client ID for device authorization flow. + client_id_interactive (SecretStr): Client ID for interactive authorization flow. + api_root (str): Base URL of the Aignostics API. + scope (str): OAuth scopes required by the SDK. + scope_elements (list[str]): OAuth scopes split into individual elements. + audience (str): OAuth audience claim. + authorization_base_url (str): Authorization endpoint for OAuth flows. + token_url (str): Token endpoint for OAuth flows. + redirect_uri (str): Redirect URI for OAuth authorization code flow. + device_url (str): Device authorization endpoint for device flow. + jws_json_url (str): URL for JWS key set. + refresh_token (SecretStr | None): OAuth refresh token if available. + cache_dir (str): Directory for caching tokens and other data. + token_file (Path): Path to the token storage file. + request_timeout_seconds (int): Timeout for API requests in seconds. + authorization_backoff_seconds (int): Backoff time for authorization retries in seconds. + """ -class AuthenticationSettings(BaseSettings): model_config = SettingsConfigDict( env_prefix=f"{__project_name__.upper()}_", env_file=( - os.getenv(f"{__project_name__.upper()}_ENV_FILE", Path.home() / f".{__project_name__}/env"), os.getenv(f"{__project_name__.upper()}_ENV_FILE", Path.home() / f".{__project_name__}/.env"), + Path(".env"), ), env_file_encoding="utf-8", extra="ignore", ) - client_id_device: SecretStr - client_id_interactive: SecretStr - api_root: str = API_ROOT_PRODUCTION + client_id_device: Annotated[ + SecretStr, + PlainSerializer( + func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always" + ), # allow to unhide sensitive info from CLI or if user presents valid token via API + Field(description="OAuth Client ID Interactive"), + ] + client_id_interactive: Annotated[ + SecretStr, + PlainSerializer( + func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always" + ), # allow to unhide sensitive info from CLI or if user presents valid token via API + Field(description="OAuth Client ID Interactive"), + ] + api_root: Annotated[ + str, + Field(description="URL of the API root", default=API_ROOT_PRODUCTION), + ] scope: str = "offline_access" @computed_field # type: ignore[prop-decorator] @property def scope_elements(self) -> list[str]: + """Get the OAuth scope elements as a list. + + Splits the scope string by comma and strips whitespace from each element. + + Returns: + list[str]: List of individual scope elements. + """ if not self.scope: return [] return [element.strip() for element in self.scope.split(",")] @@ -69,13 +124,32 @@ def scope_elements(self) -> list[str]: @computed_field # type: ignore[prop-decorator] @property def token_file(self) -> Path: + """Get the path to the token file. + + Returns: + Path: The path to the file where the authentication token is stored. + """ return Path(self.cache_dir) / ".token" request_timeout_seconds: int = 30 authorization_backoff_seconds: int = 3 @model_validator(mode="before") - def pre_init(cls, values): # type: ignore[no-untyped-def] # noqa: ANN001, ANN202, N805 + def pre_init(cls, values: dict) -> dict: # type: ignore[type-arg] # noqa: N805 + """Initialize auth-related fields based on the API root. + + This validator sets the appropriate authentication URLs and parameters + based on the target environment (production, staging, or development). + + Args: + values: The input data dictionary to validate. + + Returns: + The updated values dictionary with all environment-specific fields populated. + + Raises: + ValueError: If the API root URL is not recognized. + """ # See https://github.com/pydantic/pydantic/issues/9789 api_root = values.get("api_root", API_ROOT_PRODUCTION) match api_root: @@ -106,10 +180,10 @@ def pre_init(cls, values): # type: ignore[no-untyped-def] # noqa: ANN001, ANN2 return values -__cached_authentication_settings: AuthenticationSettings | None = None +__cached_settings: Settings | None = None -def authentication_settings() -> AuthenticationSettings: +def settings() -> Settings: """Lazy load authentication settings from the environment or a file. * Given we use Pydantic Settings, validation is done automatically. @@ -120,7 +194,7 @@ def authentication_settings() -> AuthenticationSettings: Returns: AuthenticationSettings: The loaded authentication settings. """ - global __cached_authentication_settings # noqa: PLW0603 - if __cached_authentication_settings is None: - __cached_authentication_settings = AuthenticationSettings() # pyright: ignore[reportCallIssue] - return __cached_authentication_settings + global __cached_settings # noqa: PLW0603 + if __cached_settings is None: + __cached_settings = load_settings(Settings) # pyright: ignore[reportCallIssue] + return __cached_settings diff --git a/src/aignostics/client/utils.py b/src/aignostics/client/_utils.py similarity index 100% rename from src/aignostics/client/utils.py rename to src/aignostics/client/_utils.py diff --git a/src/aignostics/client/resources/__init__.py b/src/aignostics/client/resources/__init__.py new file mode 100644 index 00000000..78237a26 --- /dev/null +++ b/src/aignostics/client/resources/__init__.py @@ -0,0 +1 @@ +"""Resources exposed by the client.""" diff --git a/src/aignostics/client/resources/runs.py b/src/aignostics/client/resources/runs.py index db1e1d09..78813d12 100644 --- a/src/aignostics/client/resources/runs.py +++ b/src/aignostics/client/resources/runs.py @@ -22,8 +22,8 @@ from jsonschema.exceptions import ValidationError from jsonschema.validators import validate +from aignostics.client._utils import calculate_file_crc32c, download_file, mime_type_to_file_ending from aignostics.client.resources.applications import Versions -from aignostics.client.utils import calculate_file_crc32c, download_file, mime_type_to_file_ending class ApplicationRun: diff --git a/src/aignostics/constants.py b/src/aignostics/constants.py index 86848ad0..02a51cb7 100644 --- a/src/aignostics/constants.py +++ b/src/aignostics/constants.py @@ -1,35 +1,4 @@ -"""Constants used throughout Aignostics Python SDK's codebase .""" +"""Constants for the Aignostics Python SDK.""" -import importlib.metadata -import pathlib - -__project_name__ = __name__.split(".")[0] -__project_path__ = str(pathlib.Path(__file__).parent.parent.parent) -__version__ = importlib.metadata.version(__project_name__) - -TODO_URL = "https://todo" -API_ROOT_PRODUCTION = "https://platform.aignostics.com" -# TODO (Andreas): hhva: please fill in -AUDIENCE_PRODUCTION = TODO_URL -AUTHORIZATION_BASE_URL_PRODUCTION = TODO_URL -TOKEN_URL_PRODUCTION = TODO_URL -REDIRECT_URI_PRODUCTION = TODO_URL -DEVICE_URL_PRODUCTION = TODO_URL -JWS_JSON_URL_PRODUCTION = TODO_URL - -API_ROOT_STAGING = "https://platform-staging.aignostics.com" -# TODO (Andreas): hhva: please fill in -AUDIENCE_STAGING = TODO_URL -AUTHORIZATION_BASE_URL_STAGING = TODO_URL -TOKEN_URL_STAGING = TODO_URL -REDIRECT_URI_STAGING = TODO_URL -DEVICE_URL_STAGING = TODO_URL -JWS_JSON_URL_STAGING = TODO_URL - -API_ROOT_DEV = "https://platform-dev.aignostics.com" -AUDIENCE_DEV = "https://dev-8ouohmmrbuh2h4vu-samia" -AUTHORIZATION_BASE_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/authorize" -TOKEN_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/oauth/token" # noqa: S105 -REDIRECT_URI_DEV = "http://localhost:8080/" -DEVICE_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/oauth/device/code" -JWS_JSON_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/.well-known/jwks.json" +API_VERSIONS = {"v1": "1.0.0"} +MODULES_TO_INSTRUMENT = ["aignostics.client", "aignostics.application"] diff --git a/src/aignostics/models.py b/src/aignostics/models.py deleted file mode 100644 index 089d7c36..00000000 --- a/src/aignostics/models.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Models used throughout Aignostics Python SDK's codebase .""" - -from enum import StrEnum - -from pydantic import BaseModel - - -class HealthStatus(StrEnum): - """Health status enumeration.""" - - UP = "UP" - DOWN = "DOWN" - - -class Health(BaseModel): - """Health status model.""" - - status: HealthStatus - reason: str | None = None diff --git a/src/aignostics/platform.py b/src/aignostics/platform.py deleted file mode 100644 index df291cc8..00000000 --- a/src/aignostics/platform.py +++ /dev/null @@ -1,151 +0,0 @@ -"""Service providing platform diagnostics and utilities.""" - -import json -import os -import platform -import sys -from pathlib import Path -from typing import Any - -from dotenv import load_dotenv - -from . import OpenAPISchemaError -from .client import authentication_settings -from .constants import ( - API_ROOT_DEV, - API_ROOT_PRODUCTION, - API_ROOT_STAGING, - __project_name__, - __project_path__, - __version__, -) -from .settings import Settings -from .types import JsonType -from .utils.process import get_process_info - -load_dotenv() - - -class Platform: - """Service providing platform diagnostics and utilities.""" - - _settings: Settings - - def __init__(self) -> None: - """Initialize service.""" - self._settings = Settings() # pyright: ignore[reportCallIssue] - false positive - self.is_healthy = True - - def healthy(self) -> bool: - """ - Check if the platform is healthy. - - Returns: - bool: True if the platform is healthy, False otherwise. - """ - return self.is_healthy - - def info(self, env: bool = True, filter_secrets: bool = True) -> dict[str, Any]: - """ - For diagnostics compile info about user and platform environment. - - Returns: - dict: Info about user and environment, including organisation, - execution environment, local and remote platform. - """ - info_dict = { - "user": { - "name": "TODO", - "email": "TODO", - "id": "TODO", - "organisation": { - "name": "TODO", - "id": "TODO", - "tier": "TODO", - }, - }, - "local": { - "sdk": { - "version": __version__, - "name": __project_name__, - "path": __project_path__, - }, - "execution": { - "interpreter_path": sys.executable, - "command_line": " ".join(sys.argv), - "entry_point": sys.argv[0] if sys.argv else None, - "process_info": json.loads(get_process_info().model_dump_json()), - }, - "platform": { - "os": { - "system": platform.system(), - "release": platform.release(), - "version": platform.version(), - "machine": platform.machine(), - "processor": platform.processor(), - }, - "python": { - "version": platform.python_version(), - "compiler": platform.python_compiler(), - "implementation": platform.python_implementation(), - }, - }, - "settings": { - "core": json.loads(self._settings.model_dump_json()), - "authentication": json.loads(authentication_settings().model_dump_json()), - }, - }, - "remote": { - "platform": { - "production": { - "API_ROOT": API_ROOT_PRODUCTION, - }, - "staging": { - "API_ROOT": API_ROOT_STAGING, - }, - "dev": { - "API_ROOT": API_ROOT_DEV, - }, - } - }, - } - - if env: - if filter_secrets: - info_dict["local"]["execution"]["env"] = { # type: ignore[index] - k: v - for k, v in os.environ.items() - if not ( - "token" in k.lower() - or "key" in k.lower() - or "secret" in k.lower() - or "password" in k.lower() - or "auth" in k.lower() - ) - } - else: - info_dict["local"]["execution"]["env"] = dict(os.environ) # type: ignore[index] - - return info_dict - - def install(self) -> None: - """Complete and validate installation of the CLI.""" - # TODO (Helmut, Andreas): Build - - @staticmethod - def openapi_schema() -> JsonType: - """ - Get OpenAPI schema of the webservice API provided by the platform. - - Returns: - dict[str, object]: OpenAPI schema. - - Raises: - OpenAPISchemaError: If the OpenAPI schema file cannot be found or is not valid JSON. - """ - schema_path = Path(__file__).parent.parent.parent / "codegen" / "in" / "api.json" - try: - with schema_path.open(encoding="utf-8") as f: - return json.load(f) # type: ignore[no-any-return] - except (FileNotFoundError, json.JSONDecodeError) as e: - raise OpenAPISchemaError(e) from e diff --git a/src/aignostics/settings.py b/src/aignostics/settings.py deleted file mode 100644 index ff6804ac..00000000 --- a/src/aignostics/settings.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Settings of Aignostics Python SDK.""" - -from enum import StrEnum -from typing import Annotated - -from pydantic import Field -from pydantic_settings import BaseSettings, SettingsConfigDict - -from . import __project_name__ - - -class Language(StrEnum): - """Supported languages.""" - - GERMAN = "de_DE" - US_ENGLISH = "en_US" - - -class Settings(BaseSettings): - """Settings.""" - - model_config = SettingsConfigDict( - env_prefix=f"{__project_name__.upper()}_", - extra="ignore", - env_file=".env", - env_file_encoding="utf-8", - ) - - language: Annotated[ - Language, - Field( - Language.US_ENGLISH, - description="Language to use for output - defaults to US english.", - ), - ] diff --git a/src/aignostics/system/__init__.py b/src/aignostics/system/__init__.py new file mode 100644 index 00000000..fe20ef16 --- /dev/null +++ b/src/aignostics/system/__init__.py @@ -0,0 +1,11 @@ +"""Hello module.""" + +from ._cli import cli +from ._service import Service +from ._settings import Settings + +__all__ = [ + "Service", + "Settings", + "cli", +] diff --git a/src/aignostics/system/_cli.py b/src/aignostics/system/_cli.py new file mode 100644 index 00000000..c9c60ca5 --- /dev/null +++ b/src/aignostics/system/_cli.py @@ -0,0 +1,125 @@ +"""System CLI commands.""" + +import json +from enum import StrEnum +from typing import Annotated + +import typer +import yaml + +from ..constants import API_VERSIONS # noqa: TID252 +from ..utils import console, get_logger # noqa: TID252 +from ._service import Service + +logger = get_logger(__name__) + +cli = typer.Typer(name="system", help="System commands") + +_service = Service() + + +class OutputFormat(StrEnum): + """ + Enum representing the supported output formats. + + This enum defines the possible formats for output data: + - YAML: Output data in YAML format + - JSON: Output data in JSON format + + Usage: + format = OutputFormat.YAML + print(f"Using {format} format") + """ + + YAML = "yaml" + JSON = "json" + + +@cli.command() +def health( + output_format: Annotated[ + OutputFormat, typer.Option(help="Output format", case_sensitive=False) + ] = OutputFormat.JSON, +) -> None: + """Determine and print system health. + + Args: + output_format (OutputFormat): Output format (JSON or YAML). + """ + match output_format: + case OutputFormat.JSON: + console.print_json(data=_service.health().model_dump()) + case OutputFormat.YAML: + console.print( + yaml.dump(data=json.loads(_service.health().model_dump_json()), width=80, default_flow_style=False), + end="", + ) + + +@cli.command() +def info( + include_environ: Annotated[bool, typer.Option(help="Include environment variables")] = False, + filter_secrets: Annotated[bool, typer.Option(help="Filter secrets")] = True, + output_format: Annotated[ + OutputFormat, typer.Option(help="Output format", case_sensitive=False) + ] = OutputFormat.JSON, +) -> None: + """Determine and print system info. + + Args: + include_environ (bool): Include environment variables. + filter_secrets (bool): Filter secrets from the output. + output_format (OutputFormat): Output format (JSON or YAML). + """ + info = _service.info(include_environ=include_environ, filter_secrets=filter_secrets) + match output_format: + case OutputFormat.JSON: + console.print_json(data=info) + case OutputFormat.YAML: + console.print(yaml.dump(info, width=80, default_flow_style=False), end="") + + +@cli.command() +def openapi( + api_version: Annotated[ + str, typer.Option(help=f"API Version. Available: {', '.join(API_VERSIONS.keys())}", case_sensitive=False) + ] = next(iter(API_VERSIONS.keys())), + output_format: Annotated[ + OutputFormat, typer.Option(help="Output format", case_sensitive=False) + ] = OutputFormat.JSON, +) -> None: + """Dump the OpenAPI specification. + + Args: + api_version (str): API version to dump. + output_format (OutputFormat): Output format (JSON or YAML). + + Raises: + typer.Exit: If an invalid API version is provided. + """ + match api_version: + case "v1": + schema = Service.openapi_schema() + case _: + available_versions = ", ".join(API_VERSIONS.keys()) + console.print( + f"[bold red]Error:[/] Invalid API version '{api_version}'. Available versions: {available_versions}" + ) + raise typer.Exit(code=1) + match output_format: + case OutputFormat.JSON: + console.print_json(data=schema) + case OutputFormat.YAML: + console.print(yaml.dump(schema, default_flow_style=False), end="") + + +@cli.command() +def install() -> None: + """Complete installation.""" + console.print("Installation complete.") + + +@cli.command("whoami") +def whoami() -> None: + """Print user info.""" + console.print("TK (whoami)") diff --git a/src/aignostics/exceptions.py b/src/aignostics/system/_exceptions.py similarity index 86% rename from src/aignostics/exceptions.py rename to src/aignostics/system/_exceptions.py index f4912724..e0a20046 100644 --- a/src/aignostics/exceptions.py +++ b/src/aignostics/system/_exceptions.py @@ -1,4 +1,4 @@ -"""Exceptions of Aignostics Python SDK.""" +"""Exceptions of system module.""" class OpenAPISchemaError(ValueError): diff --git a/src/aignostics/system/_service.py b/src/aignostics/system/_service.py new file mode 100644 index 00000000..f79da622 --- /dev/null +++ b/src/aignostics/system/_service.py @@ -0,0 +1,188 @@ +"""System service.""" + +import json +import os +import platform +import pwd +import sys +import typing as t +from pathlib import Path +from typing import Any + +from pydantic_settings import BaseSettings +from uptime import boottime, uptime + +from ..utils import ( # noqa: TID252 + UNHIDE_SENSITIVE_INFO, + BaseService, + Health, + __env__, + __project_name__, + __project_path__, + __repository_url__, + __version__, + get_logger, + get_process_info, + load_settings, + locate_subclasses, +) +from ._exceptions import OpenAPISchemaError +from ._settings import Settings + +logger = get_logger(__name__) + +JsonType: t.TypeAlias = list["JsonValue"] | t.Mapping[str, "JsonValue"] +JsonValue: t.TypeAlias = str | int | float | JsonType | None + + +class Service(BaseService): + """System service.""" + + _settings: Settings + + def __init__(self) -> None: + """Initialize service.""" + super().__init__(Settings) + + @staticmethod + def _is_healthy() -> bool: + """Check if the service itself is healthy. + + Returns: + bool: True if the service is healthy, False otherwise. + """ + return True + + def health(self) -> Health: + """Determine aggregate health of the system. + + - Health exposed by implementations of BaseService in other + modules is automatically included into the health tree. + - See utils/_health.py:Health for an explanation of the health tree. + + Returns: + Health: The aggregate health of the system. + """ + components: dict[str, Health] = {} + for service_class in locate_subclasses(BaseService): + if service_class is not Service: + components[f"{service_class.__module__}.{service_class.__name__}"] = service_class().health() + + # Set the system health status based on is_healthy attribute + status = Health.Code.UP if self._is_healthy() else Health.Code.DOWN + reason = None if self._is_healthy() else "System marked as unhealthy" + return Health(status=status, components=components, reason=reason) + + def is_token_valid(self, token: str) -> bool: + """Check if the presented token is valid. + + Returns: + bool: True if the token is valid, False otherwise. + """ + logger.info(token) + if not self._settings.token: + logger.warning("Token is not set in settings.") + return False + return token == self._settings.token.get_secret_value() + + @staticmethod + def info(include_environ: bool = False, filter_secrets: bool = True) -> dict[str, Any]: + """ + Get info about configuration of service. + + - Runtime information is automatically compiled. + - Settings are automatically aggregated from all implementations of + Pydantic BaseSettings in this package. + - Info exposed by implementations of BaseService in other modules is + automatically included into the info dict. + + Returns: + dict[str, Any]: Service configuration. + """ + bootdatetime = boottime() + rtn = { + "package": { + "version": __version__, + "name": __project_name__, + "repository": __repository_url__, + "local": __project_path__, + }, + "runtime": { + "environment": __env__, + "python": { + "version": platform.python_version(), + "compiler": platform.python_compiler(), + "implementation": platform.python_implementation(), + }, + "interpreter_path": sys.executable, + "command_line": " ".join(sys.argv), + "entry_point": sys.argv[0] if sys.argv else None, + "process_info": json.loads(get_process_info().model_dump_json()), + "username": pwd.getpwuid(os.getuid())[0], + "host": { + "system": platform.system(), + "release": platform.release(), + "version": platform.version(), + "machine": platform.machine(), + "processor": platform.processor(), + "hostname": platform.node(), + "ip_address": platform.uname().node, + "cpu_count": os.cpu_count(), + "uptime": uptime(), + "boottime": bootdatetime.isoformat() if bootdatetime else None, + }, + }, + } + + if include_environ: + if filter_secrets: + rtn["runtime"]["environ"] = { + k: v + for k, v in os.environ.items() + if not ( + "token" in k.lower() + or "key" in k.lower() + or "secret" in k.lower() + or "password" in k.lower() + or "auth" in k.lower() + ) + } + else: + rtn["runtime"]["environ"] = dict(os.environ) + + settings = {} + for settings_class in locate_subclasses(BaseSettings): + settings_instance = load_settings(settings_class) + env_prefix = settings_instance.model_config.get("env_prefix", "") + settings_dict = json.loads( + settings_instance.model_dump_json(context={UNHIDE_SENSITIVE_INFO: not filter_secrets}) + ) + for key, value in settings_dict.items(): + flat_key = f"{env_prefix}{key}".upper() + settings[flat_key] = value + rtn["settings"] = settings + + for service_class in locate_subclasses(BaseService): + if service_class is not Service: + service = service_class() + rtn[service.key()] = service.info() + + return rtn + + @staticmethod + def openapi_schema() -> JsonType: + """ + Get OpenAPI schema of the webservice API provided by the platform. + + Returns: + dict[str, object]: OpenAPI schema. + + Raises: + OpenAPISchemaError: If the OpenAPI schema file cannot be found or is not valid JSON. + """ + schema_path = Path(__file__).parent.parent.parent.parent / "codegen" / "in" / "api.json" + try: + with schema_path.open(encoding="utf-8") as f: + return json.load(f) # type: ignore[no-any-return] + except (FileNotFoundError, json.JSONDecodeError) as e: + raise OpenAPISchemaError(e) from e diff --git a/src/aignostics/system/_settings.py b/src/aignostics/system/_settings.py new file mode 100644 index 00000000..a97992de --- /dev/null +++ b/src/aignostics/system/_settings.py @@ -0,0 +1,31 @@ +"""Settings of the system module.""" + +from typing import Annotated + +from pydantic import Field, PlainSerializer, SecretStr +from pydantic_settings import SettingsConfigDict + +from ..utils import OpaqueSettings, __env_file__, __project_name__ # noqa: TID252 + + +class Settings(OpaqueSettings): + """Settings.""" + + model_config = SettingsConfigDict( + env_prefix=f"{__project_name__.upper()}_SYSTEM_", + extra="ignore", + env_file=__env_file__, + env_file_encoding="utf-8", + ) + + token: Annotated[ + SecretStr | None, + PlainSerializer(func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always"), + Field( + description=( + "Secret token to present when performing sensitive operations such as " + "retrieving info via webservice API" + ), + default=None, + ), + ] diff --git a/src/aignostics/types.py b/src/aignostics/types.py deleted file mode 100644 index 60baf7d8..00000000 --- a/src/aignostics/types.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Types of Aignostics Python SDK.""" - -import typing as t -from enum import StrEnum - -JsonType: t.TypeAlias = list["JsonValue"] | t.Mapping[str, "JsonValue"] -JsonValue: t.TypeAlias = str | int | float | JsonType | None - - -class APIVersion(StrEnum): - """ - Enum representing the API versions. - - This enum defines the supported API verions: - - V1: Output doc for v1 API - - Usage: - version = APIVersion.V1 - print(f"Using {version} version") - - """ - - V1 = "v1" - - -class OpenAPIOutputFormat(StrEnum): - """ - Enum representing the supported output formats. - - This enum defines the possible formats for output data: - - YAML: Output data in YAML format - - JSON: Output data in JSON format - - Usage: - format = OpenAPIOutputFormat.YAML - print(f"Using {format} format") - """ - - YAML = "yaml" - JSON = "json" - - -class InfoOutputFormat(StrEnum): - """ - Enum representing the supported output formats. - - This enum defines the possible formats for output data: - - YAML: Output data in YAML format - - JSON: Output data in JSON format - - Usage: - format = InfoOutputFormat.YAML - print(f"Using {format} format") - """ - - YAML = "yaml" - JSON = "json" diff --git a/src/aignostics/utils/__init__.py b/src/aignostics/utils/__init__.py index f8d3a371..46b5a385 100644 --- a/src/aignostics/utils/__init__.py +++ b/src/aignostics/utils/__init__.py @@ -1,11 +1,60 @@ -"""Utility functions and classes for the starbridge package.""" +"""Utilities module.""" -from .cli import prepare_cli -from .console import console -from .process import get_process_info +from ._cli import prepare_cli +from ._console import console +from ._constants import ( + __author_email__, + __author_name__, + __base__url__, + __documentation__url__, + __env__, + __env_file__, + __is_development_mode__, + __is_running_in_container__, + __project_name__, + __project_path__, + __repository_url__, + __version__, +) +from ._di import locate_implementations, locate_subclasses +from ._health import Health +from ._log import LogSettings, get_logger +from ._logfire import LogfireSettings +from ._process import ProcessInfo, get_process_info +from ._sentry import SentrySettings +from ._service import BaseService +from ._settings import UNHIDE_SENSITIVE_INFO, OpaqueSettings, load_settings, strip_to_none_before_validator +from .boot import boot __all__ = [ + "UNHIDE_SENSITIVE_INFO", + "BaseService", + "Health", + "LogSettings", + "LogSettings", + "LogfireSettings", + "OpaqueSettings", + "ProcessInfo", + "SentrySettings", + "__author_email__", + "__author_name__", + "__base__url__", + "__documentation__url__", + "__env__", + "__env_file__", + "__is_development_mode__", + "__is_running_in_container__", + "__project_name__", + "__project_path__", + "__repository_url__", + "__version__", + "boot", "console", + "get_logger", "get_process_info", + "load_settings", + "locate_implementations", + "locate_subclasses", "prepare_cli", + "strip_to_none_before_validator", ] diff --git a/src/aignostics/utils/cli.py b/src/aignostics/utils/_cli.py similarity index 90% rename from src/aignostics/utils/cli.py rename to src/aignostics/utils/_cli.py index 7824fe55..fb675c47 100644 --- a/src/aignostics/utils/cli.py +++ b/src/aignostics/utils/_cli.py @@ -5,6 +5,8 @@ import typer +from ._di import locate_implementations + def prepare_cli(cli: typer.Typer, epilog: str) -> None: """ @@ -13,8 +15,11 @@ def prepare_cli(cli: typer.Typer, epilog: str) -> None: Args: cli (typer.Typer): Typer instance epilog (str): Epilog to add - """ + for _cli in locate_implementations(typer.Typer): + if _cli != cli: + cli.add_typer(_cli) + cli.info.epilog = epilog cli.info.no_args_is_help = True if not any(arg.endswith("typer") for arg in Path(sys.argv[0]).parts): @@ -36,7 +41,6 @@ def _add_epilog_recursively(cli: typer.Typer, epilog: str) -> None: Args: cli (typer.Typer): Typer instance epilog (str): Epilog to add - """ cli.info.epilog = epilog for group in cli.registered_groups: @@ -51,11 +55,10 @@ def _add_epilog_recursively(cli: typer.Typer, epilog: str) -> None: def _no_args_is_help_recursively(cli: typer.Typer) -> None: """ - Add epilog to all typers in the tree. + Show help if no command is given by the user. Args: cli (typer.Typer): Typer instance - """ for group in cli.registered_groups: if isinstance(group, typer.models.TyperInfo): diff --git a/src/aignostics/utils/console.py b/src/aignostics/utils/_console.py similarity index 83% rename from src/aignostics/utils/console.py rename to src/aignostics/utils/_console.py index 9349c5e9..76d0a9b2 100644 --- a/src/aignostics/utils/console.py +++ b/src/aignostics/utils/_console.py @@ -1,4 +1,4 @@ -"""Define styling for typer, overriding defaults.""" +"""Themed rich console.""" from rich.console import Console from rich.theme import Theme diff --git a/src/aignostics/utils/_constants.py b/src/aignostics/utils/_constants.py new file mode 100644 index 00000000..eec5e78b --- /dev/null +++ b/src/aignostics/utils/_constants.py @@ -0,0 +1,59 @@ +"""Constants used throughout.""" + +import os +import sys +from importlib import metadata +from pathlib import Path + +from dotenv import load_dotenv + +load_dotenv() + +__project_name__ = __name__.split(".")[0] +__project_path__ = str(Path(__file__).parent.parent.parent) +__version__ = metadata.version(__project_name__) +__is_development_mode__ = "uvx" not in sys.argv[0].lower() +__is_running_in_container__ = os.getenv(f"{__project_name__.upper()}_RUNNING_IN_CONTAINER") +__env__ = os.getenv("ENV", os.getenv("VERCEL_ENV", "local")) +__env_file__ = [ + Path.home() / f".{__project_name__}" / ".env", + Path.home() / f".{__project_name__}" / f".env.{__env__}", + Path(".env"), + Path(f".env.{__env__}"), +] +env_file_path = os.getenv(f"{__project_name__.upper()}_ENV_FILE") +if env_file_path: + __env_file__.insert(2, Path(env_file_path)) + +vercel_base_url = os.getenv("VERCEL_URL", None) +if vercel_base_url: + vercel_base_url = "https://" + vercel_base_url +__base__url__ = os.getenv(__project_name__.upper() + "_BASE_URL", None) +if not __base__url__ and vercel_base_url: + __base__url__ = vercel_base_url + + +def get_project_url_by_label(prefix: str) -> str: + """Get labeled Project-URL. + + See https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-project-url + + Args: + prefix(str): The prefix to match at the beginning of URL entries. + + Returns: + The extracted URL string if found, or an empty string if not found. + """ + for url_entry in metadata.metadata(__project_name__).get_all("Project-URL", []): + if url_entry.startswith(prefix): + return str(url_entry.split(", ", 1)[1]) + + return "" + + +_authors = metadata.metadata(__project_name__).get_all("Author-email", []) +_author = _authors[0] if _authors else None +__author_name__ = _author.split("<")[0].strip() if _author else None +__author_email__ = _author.split("<")[1].strip(" >") if _author else None +__repository_url__ = get_project_url_by_label("Source") +__documentation__url__ = get_project_url_by_label("Documentation") diff --git a/src/aignostics/utils/_di.py b/src/aignostics/utils/_di.py new file mode 100644 index 00000000..ced5c194 --- /dev/null +++ b/src/aignostics/utils/_di.py @@ -0,0 +1,70 @@ +"""Module for dynamic import and discovery of implementations and subclasses.""" + +import importlib +import pkgutil +from inspect import isclass +from typing import Any + +from ._constants import __project_name__ + +_implementation_cache: dict[Any, list[Any]] = {} +_subclass_cache: dict[Any, list[Any]] = {} + + +def locate_implementations(_class: type[Any]) -> list[Any]: + """ + Dynamically discover all instances of some class. + + Args: + _class (type[Any]): Class to search for. + + Returns: + list[Any]: List of discovered implementations of the given class. + """ + if _class in _implementation_cache: + return _implementation_cache[_class] + + implementations = [] + package = importlib.import_module(__project_name__) + + for _, name, _ in pkgutil.iter_modules(package.__path__): + module = importlib.import_module(f"{__project_name__}.{name}") + # Check all members of the module + for member_name in dir(module): + member = getattr(module, member_name) + if isinstance(member, _class): + implementations.append(member) + + _implementation_cache[_class] = implementations + return implementations + + +def locate_subclasses(_class: type[Any]) -> list[Any]: + """ + Dynamically discover all classes that are subclasses of some type. + + Args: + _class (type[Any]): Parent class of subclasses to search for. + + Returns: + list[type[Any]]: List of discovered subclasses of the given class. + """ + if _class in _subclass_cache: + return _subclass_cache[_class] + + subclasses = [] + package = importlib.import_module(__project_name__) + + for _, name, _ in pkgutil.iter_modules(package.__path__): + try: + module = importlib.import_module(f"{__project_name__}.{name}") + # Check all members of the module + for member_name in dir(module): + member = getattr(module, member_name) + if isclass(member) and issubclass(member, _class) and member != _class: + subclasses.append(member) + except ImportError: + continue + + _subclass_cache[_class] = subclasses + return subclasses diff --git a/src/aignostics/utils/_health.py b/src/aignostics/utils/_health.py new file mode 100644 index 00000000..11377cc5 --- /dev/null +++ b/src/aignostics/utils/_health.py @@ -0,0 +1,107 @@ +"""Health models and status definitions for service health checks.""" + +from enum import StrEnum +from typing import ClassVar, Self + +from pydantic import BaseModel, Field, model_validator + + +class _HealthStatus(StrEnum): + UP = "UP" + DOWN = "DOWN" + + +class Health(BaseModel): + """Represents the health status of a service with optional components and failure reasons. + + - A health object can have child components, i.e. health forms a tree. + - Any node in the tree can set itself to DOWN. In this case the node is required + to set the reason attribute. If reason is not set when DOWN, + automatic model validation of the tree will fail. + - DOWN'ness is propagated to parent health objects. I.e. the health of a parent + node is automatically set to DOWN if any of its child components are DOWN. The + child components leading to this will be listed in the reason. + - The root of the health tree is computed in the system module. The health of other + modules is automatically picked up by the system module. + """ + + Code: ClassVar[type[_HealthStatus]] = _HealthStatus + status: _HealthStatus + reason: str | None = None + components: dict[str, "Health"] = Field(default_factory=dict) + + def compute_health_from_components(self) -> Self: + """Recursively compute health status from components. + + - If health is already DOWN, it remains DOWN with its original reason. + - If health is UP but any component is DOWN, health becomes DOWN with + a reason listing all failed components. + + Returns: + Self: The updated health instance with computed status. + """ + # Skip recomputation if already known to be DOWN + if self.status == _HealthStatus.DOWN: + return self + + # No components means we keep the existing status + if not self.components: + return self + + # Find all DOWN components + down_components = [] + for component_name, component in self.components.items(): + # Recursively compute health for each component + component.compute_health_from_components() + if component.status == _HealthStatus.DOWN: + down_components.append(component_name) + + # If any components are DOWN, mark the parent as DOWN + if down_components: + self.status = _HealthStatus.DOWN + if len(down_components) == 1: + self.reason = f"Component '{down_components[0]}' is DOWN" + else: + component_list = "', '".join(down_components) + self.reason = f"Components '{component_list}' are DOWN" + + return self + + @model_validator(mode="after") + def validate_health_state(self) -> Self: + """Validate the health state and ensure consistency. + + - Compute overall health based on component health + - Ensure UP status has no associated reason + - Ensure DOWN status always has a reason + + Returns: + Self: The validated model instance with correct health status. + + Raises: + ValueError: If validation fails due to inconsistency. + """ + # First compute health from components + self.compute_health_from_components() + + # Validate that UP status has no reason + if (self.status == _HealthStatus.UP) and self.reason: + msg = f"Health {self.status} must not have reason" + raise ValueError(msg) + + # Validate that DOWN status always has a reason + if (self.status == _HealthStatus.DOWN) and not self.reason: + msg = "Health DOWN must have a reason" + raise ValueError(msg) + + return self + + def __str__(self) -> str: + """Return string representation of health status with optional reason for DOWN state. + + Returns: + str: The health status value, with reason appended if status is DOWN. + """ + if self.status == _HealthStatus.DOWN and self.reason: + return f"{self.status.value}: {self.reason}" + return self.status.value diff --git a/src/aignostics/utils/_log.py b/src/aignostics/utils/_log.py new file mode 100644 index 00000000..d10c380b --- /dev/null +++ b/src/aignostics/utils/_log.py @@ -0,0 +1,122 @@ +"""Logging configuration and utilities.""" + +import logging as python_logging +import typing as t +from logging import FileHandler +from typing import Annotated, Literal + +import click +import logfire +from pydantic import Field +from pydantic_settings import BaseSettings, SettingsConfigDict +from rich.console import Console +from rich.logging import RichHandler + +from ._constants import __env_file__, __project_name__ +from ._settings import load_settings + + +def get_logger(name: str | None) -> python_logging.Logger: + """ + Get a logger instance with the given name or project name as default. + + Args: + name(str): The name for the logger. If None, uses project name. + + Returns: + Logger: Configured logger instance. + """ + if (name is None) or (name == __project_name__): + return python_logging.getLogger(__project_name__) + return python_logging.getLogger(f"{__project_name__}.{name}") + + +class LogSettings(BaseSettings): + """Settings for configuring logging behavior.""" + + model_config = SettingsConfigDict( + env_prefix=f"{__project_name__.upper()}_LOG_", + extra="ignore", + env_file=__env_file__, + env_file_encoding="utf-8", + ) + + level: Annotated[ + Literal["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"], + Field(description="Logging level", default="INFO"), + ] + file_enabled: Annotated[ + bool, + Field(description="Enable logging to file", default=False), + ] + file_name: Annotated[ + str, + Field(description="Name of the log file", default=f"{__project_name__}.log"), + ] + console_enabled: Annotated[ + bool, + Field(description="Enable logging to console", default=False), + ] + + +class CustomFilter(python_logging.Filter): + """Custom filter for log records.""" + + @staticmethod + def filter(_record: python_logging.LogRecord) -> bool: + """ + Filter log records based on custom criteria. + + Args: + record: The log record to filter. + + Returns: + bool: True if record should be logged, False otherwise. + """ + return True + + +def logging_initialize(log_to_logfire: bool = False) -> None: + """Initialize logging configuration.""" + log_filter = CustomFilter() + + handlers = [] + + settings = load_settings(LogSettings) + + if settings.file_enabled: + file_handler = python_logging.FileHandler(settings.file_name) + file_formatter = python_logging.Formatter( + fmt="%(asctime)s %(process)d %(levelname)s %(name)s %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + file_handler.setFormatter(file_formatter) + file_handler.addFilter(log_filter) + handlers.append(file_handler) + + if settings.console_enabled: + rich_handler = RichHandler( + console=Console(stderr=True), + markup=True, + rich_tracebacks=True, + tracebacks_suppress=[click], + show_time=True, + omit_repeated_times=True, + show_path=True, + show_level=True, + enable_link_path=True, + ) + rich_handler.addFilter(log_filter) + handlers.append(t.cast("FileHandler", rich_handler)) + + if log_to_logfire: + logfire_handler = logfire.LogfireLoggingHandler() + logfire_handler.addFilter(log_filter) + handlers.append(t.cast("FileHandler", logfire_handler)) + + python_logging.basicConfig( + level=settings.level, + format="%(name)s %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + handlers=handlers, + ) diff --git a/src/aignostics/utils/_logfire.py b/src/aignostics/utils/_logfire.py new file mode 100644 index 00000000..42c9c918 --- /dev/null +++ b/src/aignostics/utils/_logfire.py @@ -0,0 +1,69 @@ +"""Logfire integration for logging and instrumentation.""" + +from typing import Annotated + +import logfire +from pydantic import BeforeValidator, Field, PlainSerializer, SecretStr +from pydantic_settings import SettingsConfigDict + +from ._constants import __env__, __env_file__, __project_name__, __repository_url__, __version__ +from ._settings import OpaqueSettings, load_settings, strip_to_none_before_validator + + +class LogfireSettings(OpaqueSettings): + """Configuration settings for Logfire integration.""" + + model_config = SettingsConfigDict( + env_prefix=f"{__project_name__.upper()}_LOGFIRE_", + env_file=__env_file__, + env_file_encoding="utf-8", + extra="ignore", + ) + + token: Annotated[ + SecretStr | None, + BeforeValidator(strip_to_none_before_validator), + PlainSerializer(func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always"), + Field(description="Logfire token. Leave empty to disable logfire.", examples=["YOUR_TOKEN"], default=None), + ] + instrument_system_metrics: Annotated[ + bool, + Field(description="Enable system metrics instrumentation", default=False), + ] + + +def logfire_initialize(modules: list["str"]) -> bool: + """Initialize Logfire integration. + + Args: + modules(list["str"]): List of modules to be instrumented. + + Returns: + bool: True if initialized successfully False otherwise + """ + settings = load_settings(LogfireSettings) + + if settings.token is None: + return False + + logfire.configure( + send_to_logfire="if-token-present", + token=settings.token.get_secret_value(), + environment=__env__, + service_name=__project_name__, + console=False, + code_source=logfire.CodeSource( + repository=__repository_url__, + revision=__version__, + root_path="", + ), + ) + + if settings.instrument_system_metrics: + logfire.instrument_system_metrics(base="full") + + logfire.instrument_pydantic() + + logfire.install_auto_tracing(modules=modules, min_duration=0.0) + + return True diff --git a/src/aignostics/utils/process.py b/src/aignostics/utils/_process.py similarity index 99% rename from src/aignostics/utils/process.py rename to src/aignostics/utils/_process.py index e20cc20a..480bbd23 100644 --- a/src/aignostics/utils/process.py +++ b/src/aignostics/utils/_process.py @@ -27,7 +27,6 @@ def get_process_info() -> ProcessInfo: Returns: ProcessInfo: Object containing process information. - """ current_process = psutil.Process() parent = current_process.parent() diff --git a/src/aignostics/utils/_sentry.py b/src/aignostics/utils/_sentry.py new file mode 100644 index 00000000..8eaee97d --- /dev/null +++ b/src/aignostics/utils/_sentry.py @@ -0,0 +1,102 @@ +"""Sentry integration for application monitoring.""" + +from typing import Annotated + +import sentry_sdk +from pydantic import BeforeValidator, Field, PlainSerializer, SecretStr +from pydantic_settings import SettingsConfigDict +from sentry_sdk.integrations.typer import TyperIntegration + +from ._constants import __env__, __env_file__, __project_name__, __version__ +from ._settings import OpaqueSettings, load_settings, strip_to_none_before_validator + + +class SentrySettings(OpaqueSettings): + """Configuration settings for Sentry integration.""" + + model_config = SettingsConfigDict( + env_prefix=f"{__project_name__.upper()}_SENTRY_", + env_file=__env_file__, + env_file_encoding="utf-8", + extra="ignore", + ) + + dsn: Annotated[ + SecretStr | None, + BeforeValidator(strip_to_none_before_validator), + PlainSerializer(func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always"), + Field(description="Sentry DSN", examples=["https://SECRET@SECRET.ingest.de.sentry.io/SECRET"], default=None), + ] + + debug: Annotated[ + bool, + Field(description="Debug (https://docs.sentry.io/platforms/python/configuration/options/)", default=False), + ] + + send_default_pii: Annotated[ + bool, + Field( + description="Send default personal identifiable information (https://docs.sentry.io/platforms/python/configuration/options/)", + default=False, + ), + ] + + max_breadcrumbs: Annotated[ + int, + Field( + description="Max breadcrumbs (https://docs.sentry.io/platforms/python/configuration/options/#max_breadcrumbs)", + ge=0, + default=50, + ), + ] + sample_rate: Annotated[ + float, + Field( + ge=0.0, + description="Sample Rate (https://docs.sentry.io/platforms/python/configuration/sampling/#sampling-error-events)", + default=1.0, + ), + ] + traces_sample_rate: Annotated[ + float, + Field( + ge=0.0, + description="Traces Sample Rate (https://docs.sentry.io/platforms/python/configuration/sampling/#configuring-the-transaction-sample-rate)", + default=1.0, + ), + ] + profiles_sample_rate: Annotated[ + float, + Field( + ge=0.0, + description="Traces Sample Rate (https://docs.sentry.io/platforms/python/tracing/#configure)", + default=1.0, + ), + ] + + +def sentry_initialize() -> bool: + """Initialize Sentry integration. + + Returns: + bool: True if initialized successfully, False otherwise + """ + settings = load_settings(SentrySettings) + + if settings.dsn is None: + return False + + sentry_sdk.init( + release=f"{__project_name__}@{__version__}", # https://docs.sentry.io/platforms/python/configuration/releases/, + environment=__env__, + dsn=settings.dsn.get_secret_value().strip(), + max_breadcrumbs=settings.max_breadcrumbs, + debug=settings.debug, + send_default_pii=settings.send_default_pii, + sample_rate=settings.sample_rate, + traces_sample_rate=settings.traces_sample_rate, + profiles_sample_rate=settings.profiles_sample_rate, + integrations=[TyperIntegration()], + ) + + return True diff --git a/src/aignostics/utils/_service.py b/src/aignostics/utils/_service.py new file mode 100644 index 00000000..6d605401 --- /dev/null +++ b/src/aignostics/utils/_service.py @@ -0,0 +1,39 @@ +"""Base class for services.""" + +from abc import ABC, abstractmethod +from typing import Any, TypeVar + +from pydantic_settings import BaseSettings + +from ._health import Health +from ._settings import load_settings + +T = TypeVar("T", bound=BaseSettings) + + +class BaseService(ABC): + """Base class for services.""" + + _settings: BaseSettings + + def __init__(self, settings_class: type[T] | None = None) -> None: + """ + Initialize service with optional settings. + + Args: + settings_class: Optional settings class to load configuration. + """ + if settings_class is not None: + self._settings = load_settings(settings_class) + + def key(self) -> str: + """Return the module name of the instance.""" + return self.__module__.split(".")[-2] + + @abstractmethod + def health(self) -> Health: + """Get health of this service. Override in subclass.""" + + @abstractmethod + def info(self) -> dict[str, Any]: + """Get info of this service. Override in subclass.""" diff --git a/src/aignostics/utils/_settings.py b/src/aignostics/utils/_settings.py new file mode 100644 index 00000000..3aab9a7a --- /dev/null +++ b/src/aignostics/utils/_settings.py @@ -0,0 +1,89 @@ +"""Utilities around Pydantic settings.""" + +import json +import logging +import sys +from pathlib import Path +from typing import TypeVar + +from pydantic import FieldSerializationInfo, SecretStr, ValidationError +from pydantic_settings import BaseSettings +from rich.panel import Panel +from rich.text import Text + +from ._console import console + +T = TypeVar("T", bound=BaseSettings) + +logger = logging.getLogger(__name__) + +UNHIDE_SENSITIVE_INFO = "unhide_sensitive_info" + + +def strip_to_none_before_validator(v: str | None) -> str | None: + if v is None: + return None + v = v.strip() + if not v: + return None + return v + + +class OpaqueSettings(BaseSettings): + @staticmethod + def serialize_sensitive_info(input_value: SecretStr, info: FieldSerializationInfo) -> str | None: + if not input_value: + return None + if info.context.get(UNHIDE_SENSITIVE_INFO, False): # type: ignore + return input_value.get_secret_value() + return str(input_value) + + +def load_settings(settings_class: type[T]) -> T: + """ + Load settings with error handling and nice formatting. + + Args: + settings_class: The Pydantic settings class to instantiate + + Returns: + (T): Instance of the settings class + + Raises: + SystemExit: If settings validation fails + """ + try: + return settings_class() + except ValidationError as e: + errors = json.loads(e.json()) + text = Text() + text.append( + "Validation error(s): \n\n", + style="debug", + ) + + prefix = settings_class.model_config.get("env_prefix", "") + for error in errors: + env_var = f"{prefix}{error['loc'][0]}".upper() + logger.fatal(f"Configuration invalid! {env_var}: {error['msg']}") + text.append(f"• {env_var}", style="yellow bold") + text.append(f": {error['msg']}\n") + + text.append( + "\nCheck settings defined in the process environment and in file ", + style="info", + ) + env_file = str(settings_class.model_config.get("env_file", ".env") or ".env") + text.append( + str(Path(__file__).parent.parent.parent.parent / env_file), + style="bold blue underline", + ) + + console.print( + Panel( + text, + title="Configuration invalid!", + border_style="error", + ), + ) + sys.exit(78) diff --git a/src/aignostics/utils/boot.py b/src/aignostics/utils/boot.py new file mode 100644 index 00000000..8fa9e99a --- /dev/null +++ b/src/aignostics/utils/boot.py @@ -0,0 +1,86 @@ +"""Boot sequence.""" + +import os +import sys + +from ._log import logging_initialize +from ._logfire import logfire_initialize +from ._sentry import sentry_initialize + +_boot_called = False + + +def boot(modules_to_instrument: list[str]) -> None: + """Boot the application. + + Args: + modules_to_instrument (list): List of modules to be instrumented. + repository_url (str): URL of the repository. + repository_root_path (str): The root path of the repository. Default is the root path. + """ + global _boot_called # noqa: PLW0603 + if _boot_called: + return + _boot_called = True + sentry_initialize() + log_to_logfire = logfire_initialize(modules_to_instrument) + logging_initialize(log_to_logfire) + _amend_library_path() + _parse_env_args() + _log_boot_message() + + +from ._constants import __project_name__, __version__ # noqa: E402 +from ._log import get_logger # noqa: E402 +from ._process import get_process_info # noqa: E402 + + +def _parse_env_args() -> None: + """Parse --env arguments from command line and add to environment if prefix matches. + + - Last but not least removes those args so typer does not complain about them. + """ + i = 1 # Start after script name + to_remove = [] + prefix = f"{__project_name__.upper()}_" + + while i < len(sys.argv): + current_arg = sys.argv[i] + + # Handle "--env KEY=VALUE" or "-e KEY=VALUE" format (two separate arguments) + if (current_arg in {"--env", "-e"}) and i + 1 < len(sys.argv): + key_value = sys.argv[i + 1] + if "=" in key_value: + key, value = key_value.split("=", 1) + if key.startswith(prefix): + os.environ[key] = value.strip("\"'") + to_remove.extend([i, i + 1]) + i += 2 + continue + + i += 1 + + # Remove processed arguments from sys.argv in reverse order + for index in sorted(to_remove, reverse=True): + del sys.argv[index] + + +def _amend_library_path() -> None: + """Patch environment variables before any other imports.""" + if "DYLD_FALLBACK_LIBRARY_PATH" not in os.environ: + os.environ["DYLD_FALLBACK_LIBRARY_PATH"] = f"{os.getenv('HOMEBREW_PREFIX', '/opt/homebrew')}/lib/" + + +def _log_boot_message() -> None: + """Log boot message with version and process information.""" + logger = get_logger(__name__) + process_info = get_process_info() + logger.info( + "⭐ Booting %s v%s (project root %s, pid %s), parent '%s' (pid %s)", + __project_name__, + __version__, + process_info.project_root, + process_info.pid, + process_info.parent.name, + process_info.parent.pid, + ) diff --git a/tests/__init__.py b/tests/__init__.py index 3a3c8893..4851adef 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -"""Test suite for Aignostics Python SDK.""" +"""Test suite of Aignostics Python SDK.""" diff --git a/tests/aignostics/__init__.py b/tests/aignostics/__init__.py new file mode 100644 index 00000000..daf30e80 --- /dev/null +++ b/tests/aignostics/__init__.py @@ -0,0 +1 @@ +"""Test suite for package {{ import_package_name }}.""" diff --git a/tests/aignostics/application/__init__.py b/tests/aignostics/application/__init__.py new file mode 100644 index 00000000..b64cd422 --- /dev/null +++ b/tests/aignostics/application/__init__.py @@ -0,0 +1 @@ +"""Tests of application module.""" diff --git a/tests/aignostics/cli/core_test.py b/tests/aignostics/application/cli_test.py similarity index 58% rename from tests/aignostics/cli/core_test.py rename to tests/aignostics/application/cli_test.py index b91aeef4..38b55729 100644 --- a/tests/aignostics/cli/core_test.py +++ b/tests/aignostics/application/cli_test.py @@ -3,13 +3,8 @@ import pytest from typer.testing import CliRunner -from aignostics import ( - __version__, -) from aignostics.cli import cli -BUILT_WITH_LOVE = "built with love in Berlin" - @pytest.fixture def runner() -> CliRunner: @@ -17,79 +12,16 @@ def runner() -> CliRunner: return CliRunner() -def test_cli_built_with_love(runner) -> None: - """Check epilog shown.""" - result = runner.invoke(cli, ["--help"]) - assert result.exit_code == 0 - assert BUILT_WITH_LOVE in result.output - assert __version__ in result.output - - -@pytest.mark.scheduled -def test_cli_health(runner: CliRunner) -> None: - """Check health is true.""" - result = runner.invoke(cli, ["platform", "health"]) - assert result.exit_code == 0 - assert "True" in result.output - - -def test_cli_info(runner: CliRunner) -> None: - """Check info command returns system information.""" - result = runner.invoke(cli, ["platform", "info"]) - assert result.exit_code == 0 - assert "CPython" in result.output - - -def test_cli_info_json(runner: CliRunner) -> None: - """Check info command returns system information.""" - result = runner.invoke(cli, ["platform", "info", "--output-format", "json"]) - assert result.exit_code == 0 - assert "CPython" in result.output - - -def test_cli_info_full(runner: CliRunner) -> None: - """Check info command returns system information.""" - result = runner.invoke(cli, ["platform", "info", "--env", "--no-filter-secrets"]) - assert result.exit_code == 0 - assert "HOME" in result.output - - -def test_cli_openapi_yaml(runner: CliRunner) -> None: - """Check openapi command outputs YAML schema.""" - result = runner.invoke(cli, ["platform", "openapi"]) - assert result.exit_code == 0 - # Check for common OpenAPI YAML elements - assert "openapi:" in result.output - assert "info:" in result.output - assert "paths:" in result.output - - -def test_cli_openapi_json(runner: CliRunner) -> None: - """Check openapi command outputs JSON schema.""" - result = runner.invoke(cli, ["platform", "openapi", "--output-format", "json"]) - assert result.exit_code == 0 - # Check for common OpenAPI JSON elements - assert '"openapi":' in result.output - assert '"info":' in result.output - assert '"paths":' in result.output - - -def test_cli_install(runner: CliRunner) -> None: - """Check install command runs successfully.""" - result = runner.invoke(cli, ["platform", "install"]) - assert result.exit_code == 0 - - def test_cli_bucket_ls(runner: CliRunner) -> None: """Check bucket ls command runs successfully.""" - result = runner.invoke(cli, ["platform", "bucket", "ls"]) + result = runner.invoke(cli, ["application", "bucket", "ls"]) assert result.exit_code == 0 assert "bucket ls" in result.output def test_cli_bucket_purge(runner: CliRunner) -> None: """Check bucket purge command runs successfully.""" - result = runner.invoke(cli, ["platform", "bucket", "purge"]) + result = runner.invoke(cli, ["application", "bucket", "purge"]) assert result.exit_code == 0 assert "bucket purged" in result.output @@ -127,6 +59,8 @@ def test_cli_run_submit(runner: CliRunner) -> None: assert "submit run" in result.output +# TODO(Andreas): Check, just call uv run aignostics application run list +@pytest.mark.skip(reason="This test is skipped because it fails with inconsistent auth stated.") def test_cli_run_list(runner: CliRunner) -> None: """Check run list command runs successfully.""" result = runner.invoke(cli, ["application", "run", "list"]) diff --git a/tests/aignostics/cli_test.py b/tests/aignostics/cli_test.py new file mode 100644 index 00000000..edf0c203 --- /dev/null +++ b/tests/aignostics/cli_test.py @@ -0,0 +1,91 @@ +"""Tests to verify the CLI functionality of OE Python Template.""" + +import os +import subprocess +import sys + +import pytest +from typer.testing import CliRunner + +from aignostics.cli import cli +from aignostics.utils import ( + __version__, +) + +BUILT_WITH_LOVE = "built with love in Berlin" +THE_VALUE = "THE_VALUE" + + +@pytest.fixture +def runner() -> CliRunner: + """Provide a CLI test runner fixture.""" + return CliRunner() + + +def test_cli_built_with_love(runner) -> None: + """Check epilog shown.""" + result = runner.invoke(cli, ["--help"]) + assert result.exit_code == 0 + assert BUILT_WITH_LOVE in result.output + assert __version__ in result.output + + +def test_cli_fails_on_invalid_setting_with_env_arg() -> None: + """Check system fails on boot with invalid setting using subprocess.""" + # Run the CLI as a subprocess with environment variable + result = subprocess.run( + [ + sys.executable, + "-m", + "aignostics.cli", + "system", + "info", + "--env", + "AIGNOSTICS_LOG_LEVEL=FAIL", + ], + capture_output=True, + text=True, + check=False, + ) + + # Check the return code (78 indicates validation failed) + assert result.returncode == 78 + # Check that the error message is in the stderr + assert "Input should be 'CRITICAL'" in result.stdout + + +def test_cli_fails_on_invalid_setting_with_environ(runner) -> None: + """Check system fails on boot with invalid setting using CliRunner and environment variables.""" + # Set the environment variable directly + with runner.isolated_filesystem(): + # Set environment variable for the test + env = os.environ.copy() + env["AIGNOSTICS_LOG_LEVEL"] = "DEBUG" + + # custom + env["AIGNOSTICS_CLIENT_ID_DEVICE"] = THE_VALUE + env["AIGNOSTICS_CLIENT_ID_INTERACTIVE"] = THE_VALUE + # end custon + + # Run the CLI with the runner + result = runner.invoke(cli, ["system", "info"], env=env) + + # Check the exit code (0 indicates all good) + assert result.exit_code == 0 + + # Set environment variable for the test + env = os.environ.copy() + env["AIGNOSTICS_LOG_LEVEL"] = "FAIL" + + # custom + env["AIGNOSTICS_CLIENT_ID_DEVICE"] = THE_VALUE + env["AIGNOSTICS_CLIENT_ID_INTERACTIVE"] = THE_VALUE + # end custon + + # Run the CLI with the runner + result = runner.invoke(cli, ["system", "info"], env=env) + + # Check the exit code (78 indicates validation failed) + assert result.exit_code == 78 + # Check that the error message is in the output + assert "Input should be 'CRITICAL'" in result.output diff --git a/tests/aignostics/client/__init__.py b/tests/aignostics/client/__init__.py new file mode 100644 index 00000000..185dfe7f --- /dev/null +++ b/tests/aignostics/client/__init__.py @@ -0,0 +1 @@ +"""Tests of client module.""" diff --git a/tests/aignostics/client/authentication_test.py b/tests/aignostics/client/authentication_test.py index 8ad3af4f..1834f542 100644 --- a/tests/aignostics/client/authentication_test.py +++ b/tests/aignostics/client/authentication_test.py @@ -29,7 +29,7 @@ def mock_settings() -> MagicMock: Yields: MagicMock: A mock of the authentication settings. """ - with patch("aignostics.client._authentication.authentication_settings") as mock_settings: + with patch("aignostics.client._authentication.settings") as mock_settings: settings = MagicMock() # Using tmp_path in a controlled test environment is acceptable for testing settings.token_file = Path("mock_token_path") # Avoid hardcoded /tmp path diff --git a/tests/aignostics/client/scheduled_test.py b/tests/aignostics/client/scheduled_test.py index 3d46c58a..daba07f7 100644 --- a/tests/aignostics/client/scheduled_test.py +++ b/tests/aignostics/client/scheduled_test.py @@ -19,7 +19,7 @@ ) import aignostics.client -from aignostics.client.utils import _generate_signed_url, calculate_file_crc32c, mime_type_to_file_ending +from aignostics.client._utils import _generate_signed_url, calculate_file_crc32c, mime_type_to_file_ending def three_spots_payload() -> list[ItemCreationRequest]: diff --git a/tests/aignostics/client/settings_test.py b/tests/aignostics/client/settings_test.py index 928b4ec4..3ef580b7 100644 --- a/tests/aignostics/client/settings_test.py +++ b/tests/aignostics/client/settings_test.py @@ -8,7 +8,7 @@ import pytest from pydantic import SecretStr -from aignostics import ( +from aignostics.client import ( API_ROOT_DEV, API_ROOT_PRODUCTION, API_ROOT_STAGING, @@ -30,10 +30,11 @@ TOKEN_URL_DEV, TOKEN_URL_PRODUCTION, TOKEN_URL_STAGING, - __project_name__, + UNKNOWN_ENDPOINT_URL, + Settings, + settings, ) -from aignostics.client._messages import UNKNOWN_ENDPOINT_URL -from aignostics.client._settings import AuthenticationSettings, authentication_settings +from aignostics.utils import __project_name__ @pytest.fixture @@ -52,26 +53,23 @@ def mock_env_vars(): # noqa: ANN201 @pytest.fixture def reset_cached_settings(): # noqa: ANN201 """Reset the cached authentication settings.""" - from aignostics.client._settings import __cached_authentication_settings + from aignostics.client._settings import __cached_settings # Store original - original = __cached_authentication_settings + original = __cached_settings - # Reset for test - from aignostics.client import _settings - - _settings.__cached_authentication_settings = None + settings.__cached_settings = None yield # Restore original - _settings.__cached_authentication_settings = original + settings.__cached_settings = original def test_authentication_settings_production(mock_env_vars, reset_cached_settings) -> None: """Test authentication settings with production API root.""" # Create settings with production API root - settings = AuthenticationSettings( + settings = Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), api_root=API_ROOT_PRODUCTION, @@ -97,7 +95,7 @@ def test_authentication_settings_production(mock_env_vars, reset_cached_settings def test_authentication_settings_staging(mock_env_vars) -> None: """Test authentication settings with staging API root.""" - settings = AuthenticationSettings( + settings = Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), api_root=API_ROOT_STAGING, @@ -114,7 +112,7 @@ def test_authentication_settings_staging(mock_env_vars) -> None: def test_authentication_settings_dev(mock_env_vars) -> None: """Test authentication settings with dev API root.""" - settings = AuthenticationSettings( + settings = Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), api_root=API_ROOT_DEV, @@ -132,7 +130,7 @@ def test_authentication_settings_dev(mock_env_vars) -> None: def test_authentication_settings_unknown_api_root(mock_env_vars) -> None: """Test authentication settings with unknown API root raises ValueError.""" with pytest.raises(ValueError, match=UNKNOWN_ENDPOINT_URL): - AuthenticationSettings( + Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), api_root="https://unknown.example.com", @@ -141,7 +139,7 @@ def test_authentication_settings_unknown_api_root(mock_env_vars) -> None: def test_scope_elements_empty() -> None: """Test scope_elements property with empty scope.""" - settings = AuthenticationSettings( + settings = Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), scope="", @@ -152,7 +150,7 @@ def test_scope_elements_empty() -> None: def test_scope_elements_multiple() -> None: """Test scope_elements property with multiple scopes.""" - settings = AuthenticationSettings( + settings = Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), scope="offline_access, profile, email", @@ -163,7 +161,7 @@ def test_scope_elements_multiple() -> None: def test_authentication_settings_with_refresh_token(mock_env_vars) -> None: """Test authentication settings with refresh token.""" - settings = AuthenticationSettings( + settings = Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), refresh_token=SecretStr("test-refresh-token"), @@ -175,19 +173,20 @@ def test_authentication_settings_with_refresh_token(mock_env_vars) -> None: def test_lazy_authentication_settings(mock_env_vars, reset_cached_settings) -> None: """Test lazy loading of authentication settings.""" # First call should create the settings - settings1 = authentication_settings() + settings1 = settings() assert settings1 is not None # Second call should return the same instance - settings2 = authentication_settings() + settings2 = settings() assert settings2 is settings1 +@pytest.mark.sequential def test_authentication_settings_with_env_vars(mock_env_vars, reset_cached_settings) -> None: """Test authentication settings from environment variables.""" - settings = authentication_settings() - assert settings.client_id_device.get_secret_value() == "test-client-id-device" - assert settings.client_id_interactive.get_secret_value() == "test-client-id-interactive" + settings1 = settings() + assert settings1.client_id_device.get_secret_value() == "test-client-id-device" + assert settings1.client_id_interactive.get_secret_value() == "test-client-id-interactive" # TODO(Helmut): fixme @@ -196,14 +195,14 @@ def test_custom_env_file_location(mock_env_vars) -> None: """Test custom env file location.""" custom_env_file = "/home/dummy/test_env_file" with mock.patch.dict(os.environ, {f"{__project_name__.upper()}_ENV_FILE": custom_env_file}): - settings = AuthenticationSettings.model_config + settings = Settings.model_config assert custom_env_file in settings["env_file"] def test_custom_cache_dir(mock_env_vars) -> None: """Test custom cache directory.""" custom_cache_dir = "/home/dummy/test_cache_dir" - settings = AuthenticationSettings( + settings = Settings( client_id_device=SecretStr("test-client-id-device"), client_id_interactive=SecretStr("test-client-id-interactive"), cache_dir=custom_cache_dir, diff --git a/tests/aignostics/client/utils_test.py b/tests/aignostics/client/utils_test.py index a0456d6e..6966515b 100644 --- a/tests/aignostics/client/utils_test.py +++ b/tests/aignostics/client/utils_test.py @@ -2,7 +2,7 @@ import pytest -from aignostics.client.utils import mime_type_to_file_ending +from aignostics.client import mime_type_to_file_ending class TestMimeTypeToFileEnding: diff --git a/tests/aignostics/cli/docker_test.py b/tests/aignostics/docker_test.py similarity index 72% rename from tests/aignostics/cli/docker_test.py rename to tests/aignostics/docker_test.py index f2ce767f..6cc0d84e 100644 --- a/tests/aignostics/cli/docker_test.py +++ b/tests/aignostics/docker_test.py @@ -1,4 +1,4 @@ -"""Tests to verify the CLI functionality of Aignostics Python SDK.""" +"""Tests to verify the CLI functionality of OE Python Template works with Docker.""" import pytest @@ -7,9 +7,11 @@ @pytest.mark.xdist_group(name="docker") @pytest.mark.skip_with_act -@pytest.mark.skip +@pytest.mark.docker +@pytest.mark.long_running +@pytest.mark.scheduled def test_core_docker_cli_help_with_love(docker_services) -> None: """Test the CLI help command with docker services returns expected output.""" - out = docker_services._docker_compose.execute("run aignostics --help ") + out = docker_services._docker_compose.execute("run aignostics --help") out_str = out.decode("utf-8") assert "built with love in Berlin" in out_str diff --git a/tests/aignostics/system/__init__.py b/tests/aignostics/system/__init__.py new file mode 100644 index 00000000..b347f6bb --- /dev/null +++ b/tests/aignostics/system/__init__.py @@ -0,0 +1 @@ +"""Tests of system module.""" diff --git a/tests/aignostics/system/cli_test.py b/tests/aignostics/system/cli_test.py new file mode 100644 index 00000000..1b8b7462 --- /dev/null +++ b/tests/aignostics/system/cli_test.py @@ -0,0 +1,88 @@ +"""Tests to verify the CLI functionality of the system module.""" + +import os + +import pytest +from typer.testing import CliRunner + +from aignostics.cli import cli + +THE_VALUE = "THE_VALUE" + + +@pytest.fixture +def runner() -> CliRunner: + """Provide a CLI test runner fixture.""" + return CliRunner() + + +@pytest.mark.scheduled +def test_cli_health(runner: CliRunner) -> None: + """Check health is true.""" + result = runner.invoke(cli, ["system", "health"]) + assert result.exit_code == 0 + assert "UP" in result.output + + +def test_cli_info(runner: CliRunner) -> None: + """Check health is true.""" + result = runner.invoke(cli, ["system", "info"]) + assert result.exit_code == 0 + assert "aignostics.log" in result.output + + +def test_cli_info_secrets(runner: CliRunner) -> None: + """Check secrets only shown if requested.""" + with runner.isolated_filesystem(): + # Set environment variable for the test + env = os.environ.copy() + env["AIGNOSTICS_SYSTEM_TOKEN"] = THE_VALUE + + # custom + env["AIGNOSTICS_CLIENT_ID_DEVICE"] = THE_VALUE + env["AIGNOSTICS_CLIENT_ID_INTERACTIVE"] = THE_VALUE + # end custon + + # Run the CLI with the runner + result = runner.invoke(cli, ["system", "info"], env=env) + assert result.exit_code == 0 + assert THE_VALUE not in result.output + + # Run the CLI with the runner + result = runner.invoke(cli, ["system", "info", "--no-filter-secrets"], env=env) + assert result.exit_code == 0 + assert THE_VALUE in result.output + + +def test_cli_openapi_yaml(runner: CliRunner) -> None: + """Check openapi command outputs YAML schema.""" + result = runner.invoke(cli, ["system", "openapi", "--output-format", "yaml"]) + assert result.exit_code == 0 + # Check for common OpenAPI YAML elements + assert "ApplicationRunStatus:" in result.output + + result = runner.invoke(cli, ["system", "openapi", "--api-version", "v3", "--output-format", "yaml"]) + assert result.exit_code == 1 + assert "Error: Invalid API version 'v3'. Available versions: v1" in result.output + + +def test_cli_openapi_json(runner: CliRunner) -> None: + """Check openapi command outputs JSON schema.""" + result = runner.invoke(cli, ["system", "openapi"]) + assert result.exit_code == 0 + # Check for common OpenAPI JSON elements + assert '"openapi":' in result.output + assert '"info":' in result.output + assert '"paths":' in result.output + + +def test_cli_install(runner: CliRunner) -> None: + """Check install command runs successfully.""" + result = runner.invoke(cli, ["system", "install"]) + assert result.exit_code == 0 + + +def test_cli_whoami(runner: CliRunner) -> None: + """Check install command runs successfully.""" + result = runner.invoke(cli, ["system", "whoami"]) + assert result.exit_code == 0 diff --git a/tests/aignostics/system/service_test.py b/tests/aignostics/system/service_test.py new file mode 100644 index 00000000..afc6ec1e --- /dev/null +++ b/tests/aignostics/system/service_test.py @@ -0,0 +1,36 @@ +"""Tests of the system service.""" + +import os +from unittest import mock + +from aignostics.system._service import Service + + +def test_is_token_valid() -> None: + """Test that is_token_valid works correctly with environment variable.""" + # Set the environment variable for the test + the_value = "the_value" + with mock.patch.dict(os.environ, {"AIGNOSTICS_SYSTEM_TOKEN": the_value}): + # Create a new service instance to pick up the environment variable + service = Service() + + # Test with matching token + assert service.is_token_valid(the_value) is True + + # Test with non-matching token + assert service.is_token_valid("wrong-value") is False + + # Test with empty token + assert service.is_token_valid("") is False + + +def test_is_token_valid_when_not_set() -> None: + """Test that is_token_valid handles the case when no token is set.""" + # Ensure the environment variable is not set + with mock.patch.dict(os.environ, {"AIGNOSTICS_SYSTEM_TOKEN": ""}, clear=True): + # Create a new service instance with no token set + service = Service() + + # Should return False for any token when no token is set + assert service.is_token_valid("any-token") is False + assert service.is_token_valid("") is False diff --git a/tests/conftest.py b/tests/conftest.py index d9500480..4b9d8a0d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,15 +1,74 @@ """Common test fixtures and configuration.""" +import os from pathlib import Path import pytest +def pytest_collection_modifyitems(config, items) -> None: + """Modify collected test items by skipping tests marked as 'long_running' unless matching marker given. + + Args: + config: The pytest configuration object. + items: The list of collected test items. + """ + if not config.getoption("-m"): + skip_me = pytest.mark.skip(reason="skipped as no marker given on execution using '-m'") + for item in items: + if "long_running" in item.keywords: + item.add_marker(skip_me) + + @pytest.fixture(scope="session") def docker_compose_file(pytestconfig) -> str: """Get the path to the docker compose file. + Args: + pytestconfig: The pytest configuration object. + Returns: str: The path to the docker compose file. """ + # We want to test the compose.yaml file in the root of the project. return str(Path(pytestconfig.rootdir) / "compose.yaml") + + +@pytest.fixture(scope="session") +def docker_setup() -> list[str] | str: + """Commands to run when spinning up services. + + Args: + scope: The scope of the fixture. + + Returns: + list[str] | str: The commands to run. + """ + # You can consider to return an empty list so you can decide on the + # commands to run in the test itself + return ["up --build -d"] + + +def docker_compose_project_name() -> str: + """Generate a project name using the current process PID. + + Returns: + str: The project name. + """ + # You can consider to override this with a project name to reuse the stack + # across test executions. + return f"pytest{os.getpid()}" + + +def pytest_sessionfinish(session, exitstatus) -> None: + """Run after the test session ends. + + Does change behavior if no test matching the marker is found: + - Sets the exit status to 0 instead of 5. + + Args: + session: The pytest session object. + exitstatus: The exit status of the test session. + """ + if exitstatus == 5: + session.exitstatus = 0 diff --git a/tests/fixtures/.keep b/tests/fixtures/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py new file mode 100644 index 00000000..10ce9158 --- /dev/null +++ b/tests/fixtures/__init__.py @@ -0,0 +1 @@ +"""Fixtures shared accross test suite.""" diff --git a/uv.lock b/uv.lock index b610d74d..84feedf7 100644 --- a/uv.lock +++ b/uv.lock @@ -16,19 +16,33 @@ version = "0.0.10" source = { editable = "." } dependencies = [ { name = "appdirs" }, + { name = "fastapi", extra = ["all", "standard"] }, { name = "google-cloud-storage" }, { name = "google-crc32c" }, { name = "httpx" }, { name = "jsf" }, { name = "jsonschema" }, + { name = "logfire", extra = ["system-metrics"] }, + { name = "opentelemetry-instrumentation-fastapi" }, + { name = "opentelemetry-instrumentation-httpx" }, + { name = "opentelemetry-instrumentation-jinja2" }, + { name = "opentelemetry-instrumentation-requests" }, + { name = "opentelemetry-instrumentation-sqlite3" }, + { name = "opentelemetry-instrumentation-tornado" }, + { name = "opentelemetry-instrumentation-urllib" }, + { name = "opentelemetry-instrumentation-urllib3" }, + { name = "psutil" }, { name = "pydantic" }, { name = "pydantic-settings" }, { name = "pyjwt", extra = ["crypto"] }, - { name = "python-dotenv" }, + { name = "python-dateutil" }, + { name = "pyyaml" }, { name = "requests" }, { name = "requests-oauthlib" }, + { name = "sentry-sdk" }, { name = "tqdm" }, { name = "typer" }, + { name = "uptime" }, { name = "urllib3" }, ] @@ -89,6 +103,7 @@ dev = [ requires-dist = [ { name = "appdirs", specifier = ">=1.4.4" }, { name = "boto3", marker = "extra == 'aws'", specifier = ">=1.37.27" }, + { name = "fastapi", extras = ["standard", "all"], specifier = ">=0.115.12" }, { name = "google-cloud-storage", specifier = ">=3.1.0" }, { name = "google-crc32c", specifier = ">=1.7.1" }, { name = "httpx", specifier = ">=0.28.1" }, @@ -96,16 +111,29 @@ requires-dist = [ { name = "jsf", specifier = ">=0.11.2" }, { name = "jsonschema", specifier = ">=4.23.0" }, { name = "jupyter", marker = "extra == 'examples'", specifier = ">=1.1.1" }, - { name = "marimo", marker = "extra == 'examples'", specifier = ">=0.12.2" }, - { name = "pydantic", specifier = ">=2.11.1" }, + { name = "logfire", extras = ["system-metrics"], specifier = ">=3.13.1" }, + { name = "marimo", marker = "extra == 'examples'", specifier = ">=0.12.8" }, + { name = "opentelemetry-instrumentation-fastapi", specifier = ">=0.53b0" }, + { name = "opentelemetry-instrumentation-httpx", specifier = ">=0.53b0" }, + { name = "opentelemetry-instrumentation-jinja2", specifier = ">=0.53b0" }, + { name = "opentelemetry-instrumentation-requests", specifier = ">=0.53b0" }, + { name = "opentelemetry-instrumentation-sqlite3", specifier = ">=0.53b0" }, + { name = "opentelemetry-instrumentation-tornado", specifier = ">=0.53b0" }, + { name = "opentelemetry-instrumentation-urllib", specifier = ">=0.53b0" }, + { name = "opentelemetry-instrumentation-urllib3", specifier = ">=0.53b0" }, + { name = "psutil", specifier = ">=7.0.0" }, + { name = "pydantic", specifier = ">=2.11.3" }, { name = "pydantic-settings", specifier = ">=2.8.1" }, { name = "pyjwt", extras = ["crypto"], specifier = ">=2.10.1" }, - { name = "python-dotenv", specifier = ">=1.1.0" }, + { name = "python-dateutil", specifier = ">=2.9.0.post0" }, + { name = "pyyaml", specifier = ">=6.0" }, { name = "requests", specifier = ">=2.32.3" }, { name = "requests-oauthlib", specifier = ">=2.0.0" }, + { name = "sentry-sdk", specifier = ">=2.25.1" }, { name = "streamlit", marker = "extra == 'examples'", specifier = ">=1.44.1" }, { name = "tqdm", specifier = ">=4.67.1" }, { name = "typer", specifier = ">=0.15.1" }, + { name = "uptime", specifier = ">=3.0.1" }, { name = "urllib3", specifier = ">=2.2.3" }, ] provides-extras = ["examples", "aws"] @@ -122,20 +150,20 @@ dev = [ { name = "matplotlib", specifier = ">=3.10.1" }, { name = "mypy", specifier = ">=1.5.0" }, { name = "nox", extras = ["uv"], specifier = ">=2025.2.9" }, - { name = "pip-audit", specifier = ">=2.8.0" }, + { name = "pip-audit", specifier = ">=2.9.0" }, { name = "pip-licenses", git = "https://github.com/neXenio/pip-licenses.git?rev=master" }, { name = "pre-commit", specifier = ">=4.1.0" }, - { name = "pyright", specifier = ">=1.1.398" }, + { name = "pyright", specifier = ">=1.1.399" }, { name = "pytest", specifier = ">=8.3.5" }, { name = "pytest-asyncio", specifier = ">=0.26.0" }, - { name = "pytest-cov", specifier = ">=6.1.0" }, - { name = "pytest-docker", specifier = ">=3.2.0" }, + { name = "pytest-cov", specifier = ">=6.1.1" }, + { name = "pytest-docker", specifier = ">=3.2.1" }, { name = "pytest-env", specifier = ">=1.1.5" }, { name = "pytest-regressions", specifier = ">=2.7.0" }, { name = "pytest-subprocess", specifier = ">=1.5.3" }, { name = "pytest-timeout", specifier = ">=2.3.1" }, { name = "pytest-xdist", extras = ["psutil"], specifier = ">=3.6.1" }, - { name = "ruff", specifier = ">=0.11.2" }, + { name = "ruff", specifier = ">=0.11.5" }, { name = "sphinx", specifier = ">=8.2.3" }, { name = "sphinx-autobuild", specifier = ">=2024.10.3" }, { name = "sphinx-copybutton", specifier = ">=0.5.2" }, @@ -301,6 +329,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f8/ed/e97229a566617f2ae958a6b13e7cc0f585470eac730a73e9e82c32a3cdd2/arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", size = 66419 }, ] +[[package]] +name = "asgiref" +version = "3.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828 }, +] + [[package]] name = "asttokens" version = "3.0.0" @@ -925,6 +962,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/2c/3e3afb1df3dc8a8deeb143f6ac41acbfdfae4f03a54c760871c56832a554/dependency_groups-1.3.0-py3-none-any.whl", hash = "sha256:1abf34d712deda5581e80d507512664d52b35d1c2d7caf16c85e58ca508547e0", size = 8597 }, ] +[[package]] +name = "deprecated" +version = "1.2.18" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/97/06afe62762c9a8a86af0cfb7bfdab22a43ad17138b07af5b1a58442690a2/deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d", size = 2928744 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/c6/ac0b6c1e2d138f1002bcf799d330bd6d85084fece321e662a14223794041/Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec", size = 9998 }, +] + [[package]] name = "detect-secrets" version = "1.5.0" @@ -960,6 +1009,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 }, ] +[[package]] +name = "dnspython" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/4a/263763cb2ba3816dd94b08ad3a33d5fdae34ecb856678773cc40a3605829/dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1", size = 345197 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632 }, +] + [[package]] name = "docutils" version = "0.21.2" @@ -982,6 +1040,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/11/208f72084084d3f6a2ed5ebfdfc846692c3f7ad6dce65e400194924f7eed/domdf_python_tools-3.10.0-py3-none-any.whl", hash = "sha256:5e71c1be71bbcc1f881d690c8984b60e64298ec256903b3147f068bc33090c36", size = 126860 }, ] +[[package]] +name = "email-validator" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/ce/13508a1ec3f8bb981ae4ca79ea40384becc868bfae97fd1c942bb3a001b1/email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7", size = 48967 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/ee/bf0adb559ad3c786f12bcbc9296b3f5675f529199bef03e2df281fa1fadb/email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", size = 33521 }, +] + [[package]] name = "enum-tools" version = "0.12.0" @@ -1025,6 +1096,63 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/a1/8936bc8e79af80ca38288dd93ed44ed1f9d63beb25447a4c59e746e01f8d/faker-37.1.0-py3-none-any.whl", hash = "sha256:dc2f730be71cb770e9c715b13374d80dbcee879675121ab51f9683d262ae9a1c", size = 1918783 }, ] +[[package]] +name = "fastapi" +version = "0.115.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164 }, +] + +[package.optional-dependencies] +all = [ + { name = "email-validator" }, + { name = "fastapi-cli", extra = ["standard"] }, + { name = "httpx" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "orjson" }, + { name = "pydantic-extra-types" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "pyyaml" }, + { name = "ujson" }, + { name = "uvicorn", extra = ["standard"] }, +] +standard = [ + { name = "email-validator" }, + { name = "fastapi-cli", extra = ["standard"] }, + { name = "httpx" }, + { name = "jinja2" }, + { name = "python-multipart" }, + { name = "uvicorn", extra = ["standard"] }, +] + +[[package]] +name = "fastapi-cli" +version = "0.0.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "rich-toolkit" }, + { name = "typer" }, + { name = "uvicorn", extra = ["standard"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/73/82a5831fbbf8ed75905bacf5b2d9d3dfd6f04d6968b29fe6f72a5ae9ceb1/fastapi_cli-0.0.7.tar.gz", hash = "sha256:02b3b65956f526412515907a0793c9094abd4bfb5457b389f645b0ea6ba3605e", size = 16753 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/e6/5daefc851b514ce2287d8f5d358ae4341089185f78f3217a69d0ce3a390c/fastapi_cli-0.0.7-py3-none-any.whl", hash = "sha256:d549368ff584b2804336c61f192d86ddea080c11255f375959627911944804f4", size = 10705 }, +] + +[package.optional-dependencies] +standard = [ + { name = "uvicorn", extra = ["standard"] }, +] + [[package]] name = "fastjsonschema" version = "2.21.1" @@ -1287,6 +1415,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, ] +[[package]] +name = "httptools" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/26/bb526d4d14c2774fe07113ca1db7255737ffbb119315839af2065abfdac3/httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069", size = 199029 }, + { url = "https://files.pythonhosted.org/packages/a6/17/3e0d3e9b901c732987a45f4f94d4e2c62b89a041d93db89eafb262afd8d5/httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a", size = 103492 }, + { url = "https://files.pythonhosted.org/packages/b7/24/0fe235d7b69c42423c7698d086d4db96475f9b50b6ad26a718ef27a0bce6/httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975", size = 462891 }, + { url = "https://files.pythonhosted.org/packages/b1/2f/205d1f2a190b72da6ffb5f41a3736c26d6fa7871101212b15e9b5cd8f61d/httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636", size = 459788 }, + { url = "https://files.pythonhosted.org/packages/6e/4c/d09ce0eff09057a206a74575ae8f1e1e2f0364d20e2442224f9e6612c8b9/httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721", size = 433214 }, + { url = "https://files.pythonhosted.org/packages/3e/d2/84c9e23edbccc4a4c6f96a1b8d99dfd2350289e94f00e9ccc7aadde26fb5/httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988", size = 434120 }, + { url = "https://files.pythonhosted.org/packages/d0/46/4d8e7ba9581416de1c425b8264e2cadd201eb709ec1584c381f3e98f51c1/httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17", size = 88565 }, + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683 }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337 }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796 }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837 }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289 }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779 }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634 }, + { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214 }, + { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431 }, + { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121 }, + { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805 }, + { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858 }, + { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042 }, + { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682 }, +] + [[package]] name = "httpx" version = "0.28.1" @@ -1329,6 +1486,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769 }, ] +[[package]] +name = "importlib-metadata" +version = "8.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/08/c1395a292bb23fd03bdf572a1357c5a733d3eecbab877641ceacab23db6e/importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580", size = 55767 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/9d/0fb148dc4d6fa4a7dd1d8378168d9b4cd8d4560a6fbf6f0121c5fc34eb68/importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e", size = 26971 }, +] + [[package]] name = "iniconfig" version = "2.1.0" @@ -1828,6 +1997,29 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/53/84/8a89614b2e7eeeaf0a68a4046d6cfaea4544c8619ea02595ebeec9b2bae3/license_expression-30.4.1-py3-none-any.whl", hash = "sha256:679646bc3261a17690494a3e1cada446e5ee342dbd87dcfa4a0c24cc5dce13ee", size = 111457 }, ] +[[package]] +name = "logfire" +version = "3.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "executing" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-sdk" }, + { name = "protobuf" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/60/8bffe248b2261cd22808e49a882de70e93b2fc7548582daa1009a0ecf9a5/logfire-3.13.1.tar.gz", hash = "sha256:56cd1133bf93d25d2cd44c004df131183997d479a163290e9aab81d58118889a", size = 471902 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/5f/8a05978d8a4ddb13cf04acf7f510b461b76db8d5547cfefe50e42e8a16e8/logfire-3.13.1-py3-none-any.whl", hash = "sha256:b1c662dcb88fbdcfa1b6561f20ed0e758778e5542b21618cca71fee3c45c27eb", size = 191891 }, +] + +[package.optional-dependencies] +system-metrics = [ + { name = "opentelemetry-instrumentation-system-metrics" }, +] + [[package]] name = "lxml" version = "5.3.2" @@ -1889,7 +2081,7 @@ wheels = [ [[package]] name = "marimo" -version = "0.12.4" +version = "0.12.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -1910,9 +2102,9 @@ dependencies = [ { name = "uvicorn" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/74/9825fd4318bac7a921bb56581407495ce83f6221b9ae1310efdab3c8fd40/marimo-0.12.4.tar.gz", hash = "sha256:2635246a2ae1c685110c7ae64b26b9f098b3b18e948d0bbd780baf025279201c", size = 10712066 } +sdist = { url = "https://files.pythonhosted.org/packages/42/f5/3a7a8637b2c606b3dc66cb5887d0ab638ec29b3cc98931658994c2106d5a/marimo-0.12.8.tar.gz", hash = "sha256:d2d627924a32c73a9491f84e4358df8c83bbe0d4d35d38112f3020b1be32aef1", size = 10727118 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/fa/8e1c719fc75c9f06d90471757b016a1b50c2e35a8a73f422db7537b44891/marimo-0.12.4-py3-none-any.whl", hash = "sha256:b22f38563b0d8811ecf3ed422a906962a040bda914e72ffb74bb4a972ecfcd1e", size = 11070089 }, + { url = "https://files.pythonhosted.org/packages/eb/38/7894596a93c988c9506212ffc5005acf4a8f3877feebfe7598f317adc138/marimo-0.12.8-py3-none-any.whl", hash = "sha256:b4724d224d4bd9dffa4251d1b659a531c7419fe7eb6dea416763845094983f50", size = 11083695 }, ] [[package]] @@ -2345,6 +2537,327 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", size = 151688 }, ] +[[package]] +name = "opentelemetry-api" +version = "1.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "deprecated" }, + { name = "importlib-metadata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7b/34/e701d77900123af17a11dbaf0c9f527fa7ef94b8f02b2c55bed94477890a/opentelemetry_api-1.32.0.tar.gz", hash = "sha256:2623280c916f9b19cad0aa4280cb171265f19fd2909b0d47e4f06f7c83b02cb5", size = 64134 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/e8/d05fd19c1c7e7e230ab44c366791179fd64c843bc587c257a56e853893c5/opentelemetry_api-1.32.0-py3-none-any.whl", hash = "sha256:15df743c765078611f376037b0d9111ec5c1febf2ec9440cdd919370faa1ce55", size = 65285 }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/23/d1/17cae7d133d9e826050f999e282650c7aa7a45cc44e2bab9ca25b65a9bb7/opentelemetry_exporter_otlp_proto_common-1.32.0.tar.gz", hash = "sha256:2bca672f2a279c4f517115e635c0cc1269d07b2982a36681c521f7e56179a222", size = 20624 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/54/b5fd2489edc26280b3065afb2bfa2b3ebfda224af94d5d560cb5e38eba4c/opentelemetry_exporter_otlp_proto_common-1.32.0-py3-none-any.whl", hash = "sha256:277a63a18768b3b460d082a489f6f80d4ae2c1e6b185bb701c6bd4e91405e4bd", size = 18814 }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "deprecated" }, + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a4/12/73653c6ad0a8dd63fe314ae10682f80b8ad3aad0c4d15661f355c5ba2fed/opentelemetry_exporter_otlp_proto_http-1.32.0.tar.gz", hash = "sha256:a5dfd94603da86e313e4f4fb8d181fd3b64a7c2a9c7b408c3653d2b1bc68d14f", size = 15129 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/09/431d56e8ee769afd3dea847ef4851e453c81d71d0d48b8832d2936273f9c/opentelemetry_exporter_otlp_proto_http-1.32.0-py3-none-any.whl", hash = "sha256:e2ffecd6d2220eaf1291a46339f109bc0a57ee7c4c6abb8174df418bf00ce01f", size = 17241 }, +] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "packaging" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/93/3b7cc47eb1dd4a347a46d47cafb92767a4ee518d3cbb931d114b4c15d97a/opentelemetry_instrumentation-0.53b0.tar.gz", hash = "sha256:f2c21d71a3cdf28c656e3d90d247ee7558fb9b0239b3d9e9190266499dbed9d2", size = 27902 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/a5/353c9511673615f51b45e0c6a0ba4881370104848f6da7471898fc9cf84f/opentelemetry_instrumentation-0.53b0-py3-none-any.whl", hash = "sha256:70600778fd567c9c5fbfca181378ae179c0dec3ff613171707d3d77c360ff105", size = 30694 }, +] + +[[package]] +name = "opentelemetry-instrumentation-asgi" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a5/43/8bf33d949202ce2f66e184ed5343208ab2b73a85175d77469338bfc24fb1/opentelemetry_instrumentation_asgi-0.53b0.tar.gz", hash = "sha256:b82d7cecdd6a4239ee87e1c629bfd7dae208142ddbb24528d9a9274eb2bc4e44", size = 24231 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/87/c38d049c82436a2b889117f96e0cbab6e98a619407f68eeebd128c1b8ff0/opentelemetry_instrumentation_asgi-0.53b0-py3-none-any.whl", hash = "sha256:a2e242e0633541150bf8e42ed983f8aeec94acb397bc67a3dbdb47933bfdc7f8", size = 16338 }, +] + +[[package]] +name = "opentelemetry-instrumentation-dbapi" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/91/b1ce1ff5dd21e8b58a7ad140fb7965e1b81146e16197b6cb01716e226f4e/opentelemetry_instrumentation_dbapi-0.53b0.tar.gz", hash = "sha256:64baa1499094789e8af65384f9d100238417c05d419d940fdcce2db30353f882", size = 14143 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/4d/4908faa5d2303812f03a333e937d149306d6c8ce53424eccf0681a602cf7/opentelemetry_instrumentation_dbapi-0.53b0-py3-none-any.whl", hash = "sha256:0a3134a6ba366b0b8455412f86d0e689657db5f2b7296dc4d76810aa33257943", size = 12450 }, +] + +[[package]] +name = "opentelemetry-instrumentation-fastapi" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-instrumentation-asgi" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2b/c4/480029aaec9151f4d38c9bffa5f686a7ed86387ddba2344af0fb634df2e1/opentelemetry_instrumentation_fastapi-0.53b0.tar.gz", hash = "sha256:a901ded31595d6e64d35c92379c08d8314baffc8715653ac42349b6140c725ce", size = 19324 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/58/cb008bffa3e59bd3a6a8c9796f5439c9e4d00e95c2c912d41a84d929d482/opentelemetry_instrumentation_fastapi-0.53b0-py3-none-any.whl", hash = "sha256:c29b7b3f5ca5aeb89436a605ac481467630bc761a241cc4258058ba00e6d40ed", size = 12128 }, +] + +[[package]] +name = "opentelemetry-instrumentation-httpx" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/8f/c8432ce48bba5b3a8b1d6a686986ab58a256dcac648d9bea4de4648f04c6/opentelemetry_instrumentation_httpx-0.53b0.tar.gz", hash = "sha256:35b3f84ff0f9cd4ee88b9878776eacdada288136a1a2e87a66120096c4901258", size = 17734 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/26/03e736ed2ef50614a20af7317f447b9a41db505877d44810b0dfb7bc86a5/opentelemetry_instrumentation_httpx-0.53b0-py3-none-any.whl", hash = "sha256:b460764ebe98a0fb8f0939848fc577c16e5be7904aa390b8bd6d8f1b40008cca", size = 14131 }, +] + +[[package]] +name = "opentelemetry-instrumentation-jinja2" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/e5/ecc50073a0ad5313ff45e270477985d24df6c7c9ca71f205c303a381f3c9/opentelemetry_instrumentation_jinja2-0.53b0.tar.gz", hash = "sha256:e5e8a4aed9b3d0abbbf3ad14fb6ebb7ee0cb7a5cfa8e098695cb27a5b42cfcbf", size = 8468 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/18/22d90db173a1fb00d7f859adb22982b1183fa59d6a94247d9529e65ebfd1/opentelemetry_instrumentation_jinja2-0.53b0-py3-none-any.whl", hash = "sha256:d05a7218ca66a719093e034aa881332d4cd91a74ad14063f9432b6706bababd6", size = 9427 }, +] + +[[package]] +name = "opentelemetry-instrumentation-requests" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/bb/39983a82eef85dc26779797dc61b423b46c2c10c7fd10bdb86ab98667129/opentelemetry_instrumentation_requests-0.53b0.tar.gz", hash = "sha256:e6e1d2e9d2e98ce6993f0f4224e5f5cd42cb8843cf594aaa6ff436682c0a200a", size = 14377 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/3f/df98d052613e11e643ed2aeaa660a91d2adbd334b346c5f9a5e8b7c82ab1/opentelemetry_instrumentation_requests-0.53b0-py3-none-any.whl", hash = "sha256:d3fe68fee86e281223d5590f1c37f69b86db7dacd6d69e4a879a32c2281cc2c7", size = 12746 }, +] + +[[package]] +name = "opentelemetry-instrumentation-sqlite3" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-instrumentation-dbapi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/ad/5d08e2a7feb474fc363ab41ff9d5f7fa207485db2633c08c9e16e886832f/opentelemetry_instrumentation_sqlite3-0.53b0.tar.gz", hash = "sha256:4c82214228af8b1fdbef921458c42d204770fc283e7054a23e043e657ae16fab", size = 7931 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/7a/8a8a8d39006db41587392ceda54583bc54c8c04360a47cae216fbc2ce8d6/opentelemetry_instrumentation_sqlite3-0.53b0-py3-none-any.whl", hash = "sha256:39895e81c821192485ef132e1a9fa3865dfaf49a7a6a0a714866b693b27bc844", size = 9340 }, +] + +[[package]] +name = "opentelemetry-instrumentation-system-metrics" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "psutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/24/67d93a698f9a9c6c14f5f39b0520e6116099ad3a3836a2792c9a2d16c42b/opentelemetry_instrumentation_system_metrics-0.53b0.tar.gz", hash = "sha256:fbcc15900f5e8a0c99d85ee6cb9529ecfcbfbe9e6b6d6e158ac80340f40df779", size = 15008 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/26/6678e948955301821f3ef0e3f21138df2b6b0980b5b5ca960ee743c6bee5/opentelemetry_instrumentation_system_metrics-0.53b0-py3-none-any.whl", hash = "sha256:d0c57bc9bb0b5828113d562b9530c399189e1c66b22a7a40a8f2a3966cd6dfbe", size = 13093 }, +] + +[[package]] +name = "opentelemetry-instrumentation-tornado" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d4/b9/39f23cee423083fd1ffcac4494ada724f8aef0d17c54f5f682c8bc454577/opentelemetry_instrumentation_tornado-0.53b0.tar.gz", hash = "sha256:41fb3928767194d72733557b1364d13d6a26baabd47d9a0e129c42697fa417e3", size = 17085 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/2e/ab23c83855ccadc6b4bb54fabb9a91e3f55b04be4a5bb41ae49fefbd0eed/opentelemetry_instrumentation_tornado-0.53b0-py3-none-any.whl", hash = "sha256:03a86b72cef422eaac58332886aeb0daf4b044c683f56752c6ab9aa49886a861", size = 15319 }, +] + +[[package]] +name = "opentelemetry-instrumentation-urllib" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/a8/65be8833eba7500ea801410253f9233ad694d023cbbbee3458cb7f3852ea/opentelemetry_instrumentation_urllib-0.53b0.tar.gz", hash = "sha256:1cbbc161a5e2a6a268edce777eb766aae7de79f74b177669eb4f4a20e4cf2f7c", size = 13790 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/cc/83dd2ab34556926662133d6860195590c26960f132dc27e4e1b34f318f19/opentelemetry_instrumentation_urllib-0.53b0-py3-none-any.whl", hash = "sha256:6c650f13b37f1ce9a3b743d184491b54cf099dedd95d3ac259b6404fb06b686b", size = 12626 }, +] + +[[package]] +name = "opentelemetry-instrumentation-urllib3" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/4b/5a9fcc20123d1b211bf4d7e5801212a40462ec69ddbf220bd241b9129299/opentelemetry_instrumentation_urllib3-0.53b0.tar.gz", hash = "sha256:6741157ade407d971c4ffabda843461c0ad1d3d3b87eecdf8c4f64d46ccfa395", size = 15696 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/8c/0753c35e8464ae52abd039b0c0463342b4a3da3373cbdaa77bbb42bee3b2/opentelemetry_instrumentation_urllib3-0.53b0-py3-none-any.whl", hash = "sha256:ab743da7e564068fc7aaaf686c7cb219fe54ff2bcf8aa2cdb7cde14000ed9679", size = 13126 }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/49/1fa0b05e49667c964b59e08770f80c08a17075fe9b5cdea2bb18ae9bf40d/opentelemetry_proto-1.32.0.tar.gz", hash = "sha256:f8b70ae52f4ef8a4e4c0760e87c9071e07ece2618c080d4839bef44c0156cd44", size = 34359 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/7d/6246def5239d9e70861b00e713bd51a880aabdd5d09b3d2453eaadc73a08/opentelemetry_proto-1.32.0-py3-none-any.whl", hash = "sha256:f699269dc037e18fba05442580a8682c9fbd0f4c7f5addfed82c44be0c53c5ff", size = 55852 }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e8/0c/842aed73035cab0302ec70057f3180f4f023974d74bd9764ef3046f358fb/opentelemetry_sdk-1.32.0.tar.gz", hash = "sha256:5ff07fb371d1ab1189fa7047702e2e888b5403c5efcbb18083cae0d5aa5f58d2", size = 161043 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/6a/b8cb562234bd94bcf12ad3058ef7f31319b94a8df65130ce9cc2ff3c8d55/opentelemetry_sdk-1.32.0-py3-none-any.whl", hash = "sha256:ed252d035c22a15536c1f603ca089298daab60850fc2f5ddfa95d95cc1c043ea", size = 118990 }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "deprecated" }, + { name = "opentelemetry-api" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/c4/213d23239df175b420b74c6e25899c482701e6614822dc51f8c20dae7e2d/opentelemetry_semantic_conventions-0.53b0.tar.gz", hash = "sha256:05b7908e1da62d72f9bf717ed25c72f566fe005a2dd260c61b11e025f2552cf6", size = 114343 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/23/0bef11f394f828f910f32567d057f097dbaba23edf33114018a380a0d0bf/opentelemetry_semantic_conventions-0.53b0-py3-none-any.whl", hash = "sha256:561da89f766ab51615c0e72b12329e0a1bc16945dbd62c8646ffc74e36a1edff", size = 188441 }, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.53b0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/83/c3b4641f79f1cc9979c4d5ae8cd8125fa0ddad965044688cd5a7acd4c0be/opentelemetry_util_http-0.53b0.tar.gz", hash = "sha256:521111872be0cdfd4346e15e9d4822aeeb8501b094c721ef49c26277b286084e", size = 8044 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/25/f2f7c8d288abdbb32bbef5756f2b7812e6f1a0ab9315d99ad44f3e57fb9c/opentelemetry_util_http-0.53b0-py3-none-any.whl", hash = "sha256:eca40d8cd1c1149081142c44756c0a2da0be306931339b839e1b436a9de101a4", size = 7303 }, +] + +[[package]] +name = "orjson" +version = "3.10.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/c7/03913cc4332174071950acf5b0735463e3f63760c80585ef369270c2b372/orjson-3.10.16.tar.gz", hash = "sha256:d2aaa5c495e11d17b9b93205f5fa196737ee3202f000aaebf028dc9a73750f10", size = 5410415 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/29/43f91a5512b5d2535594438eb41c5357865fd5e64dec745d90a588820c75/orjson-3.10.16-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44fcbe1a1884f8bc9e2e863168b0f84230c3d634afe41c678637d2728ea8e739", size = 249180 }, + { url = "https://files.pythonhosted.org/packages/0c/36/2a72d55e266473c19a86d97b7363bb8bf558ab450f75205689a287d5ce61/orjson-3.10.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78177bf0a9d0192e0b34c3d78bcff7fe21d1b5d84aeb5ebdfe0dbe637b885225", size = 138510 }, + { url = "https://files.pythonhosted.org/packages/bb/ad/f86d6f55c1a68b57ff6ea7966bce5f4e5163f2e526ddb7db9fc3c2c8d1c4/orjson-3.10.16-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12824073a010a754bb27330cad21d6e9b98374f497f391b8707752b96f72e741", size = 132373 }, + { url = "https://files.pythonhosted.org/packages/5e/8b/d18f2711493a809f3082a88fda89342bc8e16767743b909cd3c34989fba3/orjson-3.10.16-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddd41007e56284e9867864aa2f29f3136bb1dd19a49ca43c0b4eda22a579cf53", size = 136773 }, + { url = "https://files.pythonhosted.org/packages/a1/dc/ce025f002f8e0749e3f057c4d773a4d4de32b7b4c1fc5a50b429e7532586/orjson-3.10.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0877c4d35de639645de83666458ca1f12560d9fa7aa9b25d8bb8f52f61627d14", size = 138029 }, + { url = "https://files.pythonhosted.org/packages/0e/1b/cf9df85852b91160029d9f26014230366a2b4deb8cc51fabe68e250a8c1a/orjson-3.10.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a09a539e9cc3beead3e7107093b4ac176d015bec64f811afb5965fce077a03c", size = 142677 }, + { url = "https://files.pythonhosted.org/packages/92/18/5b1e1e995bffad49dc4311a0bdfd874bc6f135fd20f0e1f671adc2c9910e/orjson-3.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31b98bc9b40610fec971d9a4d67bb2ed02eec0a8ae35f8ccd2086320c28526ca", size = 132800 }, + { url = "https://files.pythonhosted.org/packages/d6/eb/467f25b580e942fcca1344adef40633b7f05ac44a65a63fc913f9a805d58/orjson-3.10.16-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0ce243f5a8739f3a18830bc62dc2e05b69a7545bafd3e3249f86668b2bcd8e50", size = 135451 }, + { url = "https://files.pythonhosted.org/packages/8d/4b/9d10888038975cb375982e9339d9495bac382d5c976c500b8d6f2c8e2e4e/orjson-3.10.16-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:64792c0025bae049b3074c6abe0cf06f23c8e9f5a445f4bab31dc5ca23dbf9e1", size = 412358 }, + { url = "https://files.pythonhosted.org/packages/3b/e2/cfbcfcc4fbe619e0ca9bdbbfccb2d62b540bbfe41e0ee77d44a628594f59/orjson-3.10.16-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea53f7e68eec718b8e17e942f7ca56c6bd43562eb19db3f22d90d75e13f0431d", size = 152772 }, + { url = "https://files.pythonhosted.org/packages/b9/d6/627a1b00569be46173007c11dde3da4618c9bfe18409325b0e3e2a82fe29/orjson-3.10.16-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a741ba1a9488c92227711bde8c8c2b63d7d3816883268c808fbeada00400c164", size = 137225 }, + { url = "https://files.pythonhosted.org/packages/0a/7b/a73c67b505021af845b9f05c7c848793258ea141fa2058b52dd9b067c2b4/orjson-3.10.16-cp311-cp311-win32.whl", hash = "sha256:c7ed2c61bb8226384c3fdf1fb01c51b47b03e3f4536c985078cccc2fd19f1619", size = 141733 }, + { url = "https://files.pythonhosted.org/packages/f4/22/5e8217c48d68c0adbfb181e749d6a733761074e598b083c69a1383d18147/orjson-3.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:cd67d8b3e0e56222a2e7b7f7da9031e30ecd1fe251c023340b9f12caca85ab60", size = 133784 }, + { url = "https://files.pythonhosted.org/packages/5d/15/67ce9d4c959c83f112542222ea3b9209c1d424231d71d74c4890ea0acd2b/orjson-3.10.16-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6d3444abbfa71ba21bb042caa4b062535b122248259fdb9deea567969140abca", size = 249325 }, + { url = "https://files.pythonhosted.org/packages/da/2c/1426b06f30a1b9ada74b6f512c1ddf9d2760f53f61cdb59efeb9ad342133/orjson-3.10.16-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:30245c08d818fdcaa48b7d5b81499b8cae09acabb216fe61ca619876b128e184", size = 133621 }, + { url = "https://files.pythonhosted.org/packages/9e/88/18d26130954bc73bee3be10f95371ea1dfb8679e0e2c46b0f6d8c6289402/orjson-3.10.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0ba1d0baa71bf7579a4ccdcf503e6f3098ef9542106a0eca82395898c8a500a", size = 138270 }, + { url = "https://files.pythonhosted.org/packages/4f/f9/6d8b64fcd58fae072e80ee7981be8ba0d7c26ace954e5cd1d027fc80518f/orjson-3.10.16-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb0beefa5ef3af8845f3a69ff2a4aa62529b5acec1cfe5f8a6b4141033fd46ef", size = 132346 }, + { url = "https://files.pythonhosted.org/packages/16/3f/2513fd5bc786f40cd12af569c23cae6381aeddbefeed2a98f0a666eb5d0d/orjson-3.10.16-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6daa0e1c9bf2e030e93c98394de94506f2a4d12e1e9dadd7c53d5e44d0f9628e", size = 136845 }, + { url = "https://files.pythonhosted.org/packages/6d/42/b0e7b36720f5ab722b48e8ccf06514d4f769358dd73c51abd8728ef58d0b/orjson-3.10.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da9019afb21e02410ef600e56666652b73eb3e4d213a0ec919ff391a7dd52aa", size = 138078 }, + { url = "https://files.pythonhosted.org/packages/a3/a8/d220afb8a439604be74fc755dbc740bded5ed14745ca536b304ed32eb18a/orjson-3.10.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:daeb3a1ee17b69981d3aae30c3b4e786b0f8c9e6c71f2b48f1aef934f63f38f4", size = 142712 }, + { url = "https://files.pythonhosted.org/packages/8c/88/7e41e9883c00f84f92fe357a8371edae816d9d7ef39c67b5106960c20389/orjson-3.10.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fed80eaf0e20a31942ae5d0728849862446512769692474be5e6b73123a23b", size = 133136 }, + { url = "https://files.pythonhosted.org/packages/e9/ca/61116095307ad0be828ea26093febaf59e38596d84a9c8d765c3c5e4934f/orjson-3.10.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73390ed838f03764540a7bdc4071fe0123914c2cc02fb6abf35182d5fd1b7a42", size = 135258 }, + { url = "https://files.pythonhosted.org/packages/dc/1b/09493cf7d801505f094c9295f79c98c1e0af2ac01c7ed8d25b30fcb19ada/orjson-3.10.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a22bba012a0c94ec02a7768953020ab0d3e2b884760f859176343a36c01adf87", size = 412326 }, + { url = "https://files.pythonhosted.org/packages/ea/02/125d7bbd7f7a500190ddc8ae5d2d3c39d87ed3ed28f5b37cfe76962c678d/orjson-3.10.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5385bbfdbc90ff5b2635b7e6bebf259652db00a92b5e3c45b616df75b9058e88", size = 152800 }, + { url = "https://files.pythonhosted.org/packages/f9/09/7658a9e3e793d5b3b00598023e0fb6935d0e7bbb8ff72311c5415a8ce677/orjson-3.10.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:02c6279016346e774dd92625d46c6c40db687b8a0d685aadb91e26e46cc33e1e", size = 137516 }, + { url = "https://files.pythonhosted.org/packages/29/87/32b7a4831e909d347278101a48d4cf9f3f25901b2295e7709df1651f65a1/orjson-3.10.16-cp312-cp312-win32.whl", hash = "sha256:7ca55097a11426db80f79378e873a8c51f4dde9ffc22de44850f9696b7eb0e8c", size = 141759 }, + { url = "https://files.pythonhosted.org/packages/35/ce/81a27e7b439b807bd393585271364cdddf50dc281fc57c4feef7ccb186a6/orjson-3.10.16-cp312-cp312-win_amd64.whl", hash = "sha256:86d127efdd3f9bf5f04809b70faca1e6836556ea3cc46e662b44dab3fe71f3d6", size = 133944 }, + { url = "https://files.pythonhosted.org/packages/87/b9/ff6aa28b8c86af9526160905593a2fe8d004ac7a5e592ee0b0ff71017511/orjson-3.10.16-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:148a97f7de811ba14bc6dbc4a433e0341ffd2cc285065199fb5f6a98013744bd", size = 249289 }, + { url = "https://files.pythonhosted.org/packages/6c/81/6d92a586149b52684ab8fd70f3623c91d0e6a692f30fd8c728916ab2263c/orjson-3.10.16-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1d960c1bf0e734ea36d0adc880076de3846aaec45ffad29b78c7f1b7962516b8", size = 133640 }, + { url = "https://files.pythonhosted.org/packages/c2/88/b72443f4793d2e16039ab85d0026677932b15ab968595fb7149750d74134/orjson-3.10.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a318cd184d1269f68634464b12871386808dc8b7c27de8565234d25975a7a137", size = 138286 }, + { url = "https://files.pythonhosted.org/packages/c3/3c/72a22d4b28c076c4016d5a52bd644a8e4d849d3bb0373d9e377f9e3b2250/orjson-3.10.16-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df23f8df3ef9223d1d6748bea63fca55aae7da30a875700809c500a05975522b", size = 132307 }, + { url = "https://files.pythonhosted.org/packages/8a/a2/f1259561bdb6ad7061ff1b95dab082fe32758c4bc143ba8d3d70831f0a06/orjson-3.10.16-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b94dda8dd6d1378f1037d7f3f6b21db769ef911c4567cbaa962bb6dc5021cf90", size = 136739 }, + { url = "https://files.pythonhosted.org/packages/3d/af/c7583c4b34f33d8b8b90cfaab010ff18dd64e7074cc1e117a5f1eff20dcf/orjson-3.10.16-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f12970a26666a8775346003fd94347d03ccb98ab8aa063036818381acf5f523e", size = 138076 }, + { url = "https://files.pythonhosted.org/packages/d7/59/d7fc7fbdd3d4a64c2eae4fc7341a5aa39cf9549bd5e2d7f6d3c07f8b715b/orjson-3.10.16-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15a1431a245d856bd56e4d29ea0023eb4d2c8f71efe914beb3dee8ab3f0cd7fb", size = 142643 }, + { url = "https://files.pythonhosted.org/packages/92/0e/3bd8f2197d27601f16b4464ae948826da2bcf128af31230a9dbbad7ceb57/orjson-3.10.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83655cfc247f399a222567d146524674a7b217af7ef8289c0ff53cfe8db09f0", size = 133168 }, + { url = "https://files.pythonhosted.org/packages/af/a8/351fd87b664b02f899f9144d2c3dc848b33ac04a5df05234cbfb9e2a7540/orjson-3.10.16-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fa59ae64cb6ddde8f09bdbf7baf933c4cd05734ad84dcf4e43b887eb24e37652", size = 135271 }, + { url = "https://files.pythonhosted.org/packages/ba/b0/a6d42a7d412d867c60c0337d95123517dd5a9370deea705ea1be0f89389e/orjson-3.10.16-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ca5426e5aacc2e9507d341bc169d8af9c3cbe88f4cd4c1cf2f87e8564730eb56", size = 412444 }, + { url = "https://files.pythonhosted.org/packages/79/ec/7572cd4e20863f60996f3f10bc0a6da64a6fd9c35954189a914cec0b7377/orjson-3.10.16-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6fd5da4edf98a400946cd3a195680de56f1e7575109b9acb9493331047157430", size = 152737 }, + { url = "https://files.pythonhosted.org/packages/a9/19/ceb9e8fed5403b2e76a8ac15f581b9d25780a3be3c9b3aa54b7777a210d5/orjson-3.10.16-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:980ecc7a53e567169282a5e0ff078393bac78320d44238da4e246d71a4e0e8f5", size = 137482 }, + { url = "https://files.pythonhosted.org/packages/1b/78/a78bb810f3786579dbbbd94768284cbe8f2fd65167cd7020260679665c17/orjson-3.10.16-cp313-cp313-win32.whl", hash = "sha256:28f79944dd006ac540a6465ebd5f8f45dfdf0948ff998eac7a908275b4c1add6", size = 141714 }, + { url = "https://files.pythonhosted.org/packages/81/9c/b66ce9245ff319df2c3278acd351a3f6145ef34b4a2d7f4b0f739368370f/orjson-3.10.16-cp313-cp313-win_amd64.whl", hash = "sha256:fe0a145e96d51971407cb8ba947e63ead2aa915db59d6631a355f5f2150b56b7", size = 133954 }, +] + [[package]] name = "overrides" version = "7.7.0" @@ -2515,7 +3028,7 @@ wheels = [ [[package]] name = "pip-audit" -version = "2.8.0" +version = "2.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cachecontrol", extra = ["filecache"] }, @@ -2528,9 +3041,9 @@ dependencies = [ { name = "rich" }, { name = "toml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e8/c8/44ccea85bd2024f1ebe55eb6cdaf1f2183359176689eed3c0b01926c24ad/pip_audit-2.8.0.tar.gz", hash = "sha256:9816cbd94de6f618a8965c117433006b3d565a708dc05d5a7be47ab65b66fa05", size = 51073 } +sdist = { url = "https://files.pythonhosted.org/packages/cc/7f/28fad19a9806f796f13192ab6974c07c4a04d9cbb8e30dd895c3c11ce7ee/pip_audit-2.9.0.tar.gz", hash = "sha256:0b998410b58339d7a231e5aa004326a294e4c7c6295289cdc9d5e1ef07b1f44d", size = 52089 } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/0c/be5c42643284b2cfc5d9d36b576b7465268a163bd7df481a3979a3d87a0b/pip_audit-2.8.0-py3-none-any.whl", hash = "sha256:200f50d56cb6fba3a9189c20d53250354f72f161d63b6ef77ae5de2b53044566", size = 57002 }, + { url = "https://files.pythonhosted.org/packages/43/9e/f4dfd9d3dadb6d6dc9406f1111062f871e2e248ed7b584cca6020baf2ac1/pip_audit-2.9.0-py3-none-any.whl", hash = "sha256:348b16e60895749a0839875d7cc27ebd692e1584ebe5d5cb145941c8e25a80bd", size = 58634 }, ] [[package]] @@ -2798,7 +3311,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.2" +version = "2.11.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -2806,9 +3319,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b0/41/832125a41fe098b58d1fdd04ae819b4dc6b34d6b09ed78304fd93d4bc051/pydantic-2.11.2.tar.gz", hash = "sha256:2138628e050bd7a1e70b91d4bf4a91167f4ad76fdb83209b107c8d84b854917e", size = 784742 } +sdist = { url = "https://files.pythonhosted.org/packages/10/2e/ca897f093ee6c5f3b0bee123ee4465c50e75431c3d5b6a3b44a47134e891/pydantic-2.11.3.tar.gz", hash = "sha256:7471657138c16adad9322fe3070c0116dd6c3ad8d649300e3cbdfe91f4db4ec3", size = 785513 } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/c2/0f3baea344d0b15e35cb3e04ad5b953fa05106b76efbf4c782a3f47f22f5/pydantic-2.11.2-py3-none-any.whl", hash = "sha256:7f17d25846bcdf89b670a86cdfe7b29a9f1c9ca23dee154221c9aa81845cfca7", size = 443295 }, + { url = "https://files.pythonhosted.org/packages/b0/1d/407b29780a289868ed696d1616f4aad49d6388e5a77f567dcd2629dcd7b8/pydantic-2.11.3-py3-none-any.whl", hash = "sha256:a082753436a07f9ba1289c6ffa01cd93db3548776088aa917cc43b63f68fa60f", size = 443591 }, ] [[package]] @@ -2876,6 +3389,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/6f/5596dc418f2e292ffc661d21931ab34591952e2843e7168ea5a52591f6ff/pydantic_core-2.33.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f995719707e0e29f0f41a8aa3bcea6e761a36c9136104d3189eafb83f5cec5e5", size = 2080951 }, ] +[[package]] +name = "pydantic-extra-types" +version = "2.10.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/fa/6b268a47839f8af46ffeb5bb6aee7bded44fbad54e6bf826c11f17aef91a/pydantic_extra_types-2.10.3.tar.gz", hash = "sha256:dcc0a7b90ac9ef1b58876c9b8fdede17fbdde15420de9d571a9fccde2ae175bb", size = 95128 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/0a/f6f8e5f79d188e2f3fa9ecfccfa72538b685985dd5c7c2886c67af70e685/pydantic_extra_types-2.10.3-py3-none-any.whl", hash = "sha256:e8b372752b49019cd8249cc192c62a820d8019f5382a8789d0f887338a59c0f3", size = 37175 }, +] + [[package]] name = "pydantic-settings" version = "2.8.1" @@ -2949,15 +3475,15 @@ wheels = [ [[package]] name = "pyright" -version = "1.1.398" +version = "1.1.399" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nodeenv" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/24/d6/48740f1d029e9fc4194880d1ad03dcf0ba3a8f802e0e166b8f63350b3584/pyright-1.1.398.tar.gz", hash = "sha256:357a13edd9be8082dc73be51190913e475fa41a6efb6ec0d4b7aab3bc11638d8", size = 3892675 } +sdist = { url = "https://files.pythonhosted.org/packages/db/9d/d91d5f6d26b2db95476fefc772e2b9a16d54c6bd0ea6bb5c1b6d635ab8b4/pyright-1.1.399.tar.gz", hash = "sha256:439035d707a36c3d1b443aec980bc37053fbda88158eded24b8eedcf1c7b7a1b", size = 3856954 } wheels = [ - { url = "https://files.pythonhosted.org/packages/58/e0/5283593f61b3c525d6d7e94cfb6b3ded20b3df66e953acaf7bb4f23b3f6e/pyright-1.1.398-py3-none-any.whl", hash = "sha256:0a70bfd007d9ea7de1cf9740e1ad1a40a122592cfe22a3f6791b06162ad08753", size = 5780235 }, + { url = "https://files.pythonhosted.org/packages/2f/b5/380380c9e7a534cb1783c70c3e8ac6d1193c599650a55838d0557586796e/pyright-1.1.399-py3-none-any.whl", hash = "sha256:55f9a875ddf23c9698f24208c764465ffdfd38be6265f7faf9a176e1dc549f3b", size = 5592584 }, ] [[package]] @@ -3014,15 +3540,15 @@ wheels = [ [[package]] name = "pytest-docker" -version = "3.2.0" +version = "3.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8f/05/5c25661d15d45ab0f7537545d552fc97b296215b82e1677c0a1916d48a22/pytest_docker-3.2.0.tar.gz", hash = "sha256:3d6537564e1582cab39e6cc3d6f3d931e92398af62f8313fc826e436f8233e21", size = 13461 } +sdist = { url = "https://files.pythonhosted.org/packages/dd/38/ba9344240455a09195863f2c4466468b41a08be0dff8c5611f7ec63f260d/pytest_docker-3.2.1.tar.gz", hash = "sha256:fc2cd9d1d317ac0854c140738182a60331fbcee8c0ef655b790e8f40a96e226f", size = 13499 } wheels = [ - { url = "https://files.pythonhosted.org/packages/66/70/d0148590517cd275bc6fa1fddd836fa787b77092ec3e9d3218466bd492aa/pytest_docker-3.2.0-py3-none-any.whl", hash = "sha256:3e266db66887aa3611b2dfd86fb2a3b42f25f3a29d3f14b6e57a831e93a64f60", size = 8545 }, + { url = "https://files.pythonhosted.org/packages/d5/22/8495ea7fbb9685efccb969e5139d564cbc5a8645b86278b28cbaa21bce0d/pytest_docker-3.2.1-py3-none-any.whl", hash = "sha256:ad1be411336959bee768b965c1c4949657e743eec9cf9e7a921fadf83ad97526", size = 8584 }, ] [[package]] @@ -3123,6 +3649,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/08/20/0f2523b9e50a8052bc6a8b732dfc8568abbdc42010aef03a2d750bdab3b2/python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7", size = 15163 }, ] +[[package]] +name = "python-multipart" +version = "0.0.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 }, +] + [[package]] name = "pytz" version = "2025.2" @@ -3363,6 +3898,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/69/963f0bf44a654f6465bdb66fb5a91051b0d7af9f742b5bd7202607165036/rich_click-1.8.8-py3-none-any.whl", hash = "sha256:205aabd5a98e64ab2c105dee9e368be27480ba004c7dfa2accd0ed44f9f1550e", size = 35747 }, ] +[[package]] +name = "rich-toolkit" +version = "0.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/ea/13945d58d556a28dfb0f774ad5c8af759527390e59505a40d164bf8ce1ce/rich_toolkit-0.14.1.tar.gz", hash = "sha256:9248e2d087bfc01f3e4c5c8987e05f7fa744d00dd22fa2be3aa6e50255790b3f", size = 104416 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/e8/61c5b12d1567fdba41a6775db12a090d88b8305424ee7c47259c70d33cb4/rich_toolkit-0.14.1-py3-none-any.whl", hash = "sha256:dc92c0117d752446d04fdc828dbca5873bcded213a091a5d3742a2beec2e6559", size = 24177 }, +] + [[package]] name = "roman-numerals-py" version = "3.1.0" @@ -3513,27 +4062,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.11.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/5b/3ae20f89777115944e89c2d8c2e795dcc5b9e04052f76d5347e35e0da66e/ruff-0.11.4.tar.gz", hash = "sha256:f45bd2fb1a56a5a85fae3b95add03fb185a0b30cf47f5edc92aa0355ca1d7407", size = 3933063 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/db/baee59ac88f57527fcbaad3a7b309994e42329c6bc4d4d2b681a3d7b5426/ruff-0.11.4-py3-none-linux_armv6l.whl", hash = "sha256:d9f4a761ecbde448a2d3e12fb398647c7f0bf526dbc354a643ec505965824ed2", size = 10106493 }, - { url = "https://files.pythonhosted.org/packages/c1/d6/9a0962cbb347f4ff98b33d699bf1193ff04ca93bed4b4222fd881b502154/ruff-0.11.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8c1747d903447d45ca3d40c794d1a56458c51e5cc1bc77b7b64bd2cf0b1626cc", size = 10876382 }, - { url = "https://files.pythonhosted.org/packages/3a/8f/62bab0c7d7e1ae3707b69b157701b41c1ccab8f83e8501734d12ea8a839f/ruff-0.11.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:51a6494209cacca79e121e9b244dc30d3414dac8cc5afb93f852173a2ecfc906", size = 10237050 }, - { url = "https://files.pythonhosted.org/packages/09/96/e296965ae9705af19c265d4d441958ed65c0c58fc4ec340c27cc9d2a1f5b/ruff-0.11.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f171605f65f4fc49c87f41b456e882cd0c89e4ac9d58e149a2b07930e1d466f", size = 10424984 }, - { url = "https://files.pythonhosted.org/packages/e5/56/644595eb57d855afed6e54b852e2df8cd5ca94c78043b2f29bdfb29882d5/ruff-0.11.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ebf99ea9af918878e6ce42098981fc8c1db3850fef2f1ada69fb1dcdb0f8e79e", size = 9957438 }, - { url = "https://files.pythonhosted.org/packages/86/83/9d3f3bed0118aef3e871ded9e5687fb8c5776bde233427fd9ce0a45db2d4/ruff-0.11.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edad2eac42279df12e176564a23fc6f4aaeeb09abba840627780b1bb11a9d223", size = 11547282 }, - { url = "https://files.pythonhosted.org/packages/40/e6/0c6e4f5ae72fac5ccb44d72c0111f294a5c2c8cc5024afcb38e6bda5f4b3/ruff-0.11.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f103a848be9ff379fc19b5d656c1f911d0a0b4e3e0424f9532ececf319a4296e", size = 12182020 }, - { url = "https://files.pythonhosted.org/packages/b5/92/4aed0e460aeb1df5ea0c2fbe8d04f9725cccdb25d8da09a0d3f5b8764bf8/ruff-0.11.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:193e6fac6eb60cc97b9f728e953c21cc38a20077ed64f912e9d62b97487f3f2d", size = 11679154 }, - { url = "https://files.pythonhosted.org/packages/1b/d3/7316aa2609f2c592038e2543483eafbc62a0e1a6a6965178e284808c095c/ruff-0.11.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7af4e5f69b7c138be8dcffa5b4a061bf6ba6a3301f632a6bce25d45daff9bc99", size = 13905985 }, - { url = "https://files.pythonhosted.org/packages/63/80/734d3d17546e47ff99871f44ea7540ad2bbd7a480ed197fe8a1c8a261075/ruff-0.11.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:126b1bf13154aa18ae2d6c3c5efe144ec14b97c60844cfa6eb960c2a05188222", size = 11348343 }, - { url = "https://files.pythonhosted.org/packages/04/7b/70fc7f09a0161dce9613a4671d198f609e653d6f4ff9eee14d64c4c240fb/ruff-0.11.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8806daaf9dfa881a0ed603f8a0e364e4f11b6ed461b56cae2b1c0cab0645304", size = 10308487 }, - { url = "https://files.pythonhosted.org/packages/1a/22/1cdd62dabd678d75842bf4944fd889cf794dc9e58c18cc547f9eb28f95ed/ruff-0.11.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5d94bb1cc2fc94a769b0eb975344f1b1f3d294da1da9ddbb5a77665feb3a3019", size = 9929091 }, - { url = "https://files.pythonhosted.org/packages/9f/20/40e0563506332313148e783bbc1e4276d657962cc370657b2fff20e6e058/ruff-0.11.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:995071203d0fe2183fc7a268766fd7603afb9996785f086b0d76edee8755c896", size = 10924659 }, - { url = "https://files.pythonhosted.org/packages/b5/41/eef9b7aac8819d9e942f617f9db296f13d2c4576806d604aba8db5a753f1/ruff-0.11.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7a37ca937e307ea18156e775a6ac6e02f34b99e8c23fe63c1996185a4efe0751", size = 11428160 }, - { url = "https://files.pythonhosted.org/packages/ff/61/c488943414fb2b8754c02f3879de003e26efdd20f38167ded3fb3fc1cda3/ruff-0.11.4-py3-none-win32.whl", hash = "sha256:0e9365a7dff9b93af933dab8aebce53b72d8f815e131796268709890b4a83270", size = 10311496 }, - { url = "https://files.pythonhosted.org/packages/b6/2b/2a1c8deb5f5dfa3871eb7daa41492c4d2b2824a74d2b38e788617612a66d/ruff-0.11.4-py3-none-win_amd64.whl", hash = "sha256:5a9fa1c69c7815e39fcfb3646bbfd7f528fa8e2d4bebdcf4c2bd0fa037a255fb", size = 11399146 }, - { url = "https://files.pythonhosted.org/packages/4f/03/3aec4846226d54a37822e4c7ea39489e4abd6f88388fba74e3d4abe77300/ruff-0.11.4-py3-none-win_arm64.whl", hash = "sha256:d435db6b9b93d02934cf61ef332e66af82da6d8c69aefdea5994c89997c7a0fc", size = 10450306 }, +version = "0.11.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/71/5759b2a6b2279bb77fe15b1435b89473631c2cd6374d45ccdb6b785810be/ruff-0.11.5.tar.gz", hash = "sha256:cae2e2439cb88853e421901ec040a758960b576126dab520fa08e9de431d1bef", size = 3976488 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/db/6efda6381778eec7f35875b5cbefd194904832a1153d68d36d6b269d81a8/ruff-0.11.5-py3-none-linux_armv6l.whl", hash = "sha256:2561294e108eb648e50f210671cc56aee590fb6167b594144401532138c66c7b", size = 10103150 }, + { url = "https://files.pythonhosted.org/packages/44/f2/06cd9006077a8db61956768bc200a8e52515bf33a8f9b671ee527bb10d77/ruff-0.11.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac12884b9e005c12d0bd121f56ccf8033e1614f736f766c118ad60780882a077", size = 10898637 }, + { url = "https://files.pythonhosted.org/packages/18/f5/af390a013c56022fe6f72b95c86eb7b2585c89cc25d63882d3bfe411ecf1/ruff-0.11.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4bfd80a6ec559a5eeb96c33f832418bf0fb96752de0539905cf7b0cc1d31d779", size = 10236012 }, + { url = "https://files.pythonhosted.org/packages/b8/ca/b9bf954cfed165e1a0c24b86305d5c8ea75def256707f2448439ac5e0d8b/ruff-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0947c0a1afa75dcb5db4b34b070ec2bccee869d40e6cc8ab25aca11a7d527794", size = 10415338 }, + { url = "https://files.pythonhosted.org/packages/d9/4d/2522dde4e790f1b59885283f8786ab0046958dfd39959c81acc75d347467/ruff-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad871ff74b5ec9caa66cb725b85d4ef89b53f8170f47c3406e32ef040400b038", size = 9965277 }, + { url = "https://files.pythonhosted.org/packages/e5/7a/749f56f150eef71ce2f626a2f6988446c620af2f9ba2a7804295ca450397/ruff-0.11.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6cf918390cfe46d240732d4d72fa6e18e528ca1f60e318a10835cf2fa3dc19f", size = 11541614 }, + { url = "https://files.pythonhosted.org/packages/89/b2/7d9b8435222485b6aac627d9c29793ba89be40b5de11584ca604b829e960/ruff-0.11.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56145ee1478582f61c08f21076dc59153310d606ad663acc00ea3ab5b2125f82", size = 12198873 }, + { url = "https://files.pythonhosted.org/packages/00/e0/a1a69ef5ffb5c5f9c31554b27e030a9c468fc6f57055886d27d316dfbabd/ruff-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5f66f8f1e8c9fc594cbd66fbc5f246a8d91f916cb9667e80208663ec3728304", size = 11670190 }, + { url = "https://files.pythonhosted.org/packages/05/61/c1c16df6e92975072c07f8b20dad35cd858e8462b8865bc856fe5d6ccb63/ruff-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80b4df4d335a80315ab9afc81ed1cff62be112bd165e162b5eed8ac55bfc8470", size = 13902301 }, + { url = "https://files.pythonhosted.org/packages/79/89/0af10c8af4363304fd8cb833bd407a2850c760b71edf742c18d5a87bb3ad/ruff-0.11.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3068befab73620b8a0cc2431bd46b3cd619bc17d6f7695a3e1bb166b652c382a", size = 11350132 }, + { url = "https://files.pythonhosted.org/packages/b9/e1/ecb4c687cbf15164dd00e38cf62cbab238cad05dd8b6b0fc68b0c2785e15/ruff-0.11.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5da2e710a9641828e09aa98b92c9ebbc60518fdf3921241326ca3e8f8e55b8b", size = 10312937 }, + { url = "https://files.pythonhosted.org/packages/cf/4f/0e53fe5e500b65934500949361e3cd290c5ba60f0324ed59d15f46479c06/ruff-0.11.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef39f19cb8ec98cbc762344921e216f3857a06c47412030374fffd413fb8fd3a", size = 9936683 }, + { url = "https://files.pythonhosted.org/packages/04/a8/8183c4da6d35794ae7f76f96261ef5960853cd3f899c2671961f97a27d8e/ruff-0.11.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b2a7cedf47244f431fd11aa5a7e2806dda2e0c365873bda7834e8f7d785ae159", size = 10950217 }, + { url = "https://files.pythonhosted.org/packages/26/88/9b85a5a8af21e46a0639b107fcf9bfc31da4f1d263f2fc7fbe7199b47f0a/ruff-0.11.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:81be52e7519f3d1a0beadcf8e974715b2dfc808ae8ec729ecfc79bddf8dbb783", size = 11404521 }, + { url = "https://files.pythonhosted.org/packages/fc/52/047f35d3b20fd1ae9ccfe28791ef0f3ca0ef0b3e6c1a58badd97d450131b/ruff-0.11.5-py3-none-win32.whl", hash = "sha256:e268da7b40f56e3eca571508a7e567e794f9bfcc0f412c4b607931d3af9c4afe", size = 10320697 }, + { url = "https://files.pythonhosted.org/packages/b9/fe/00c78010e3332a6e92762424cf4c1919065707e962232797d0b57fd8267e/ruff-0.11.5-py3-none-win_amd64.whl", hash = "sha256:6c6dc38af3cfe2863213ea25b6dc616d679205732dc0fb673356c2d69608f800", size = 11378665 }, + { url = "https://files.pythonhosted.org/packages/43/7c/c83fe5cbb70ff017612ff36654edfebec4b1ef79b558b8e5fd933bab836b/ruff-0.11.5-py3-none-win_arm64.whl", hash = "sha256:67e241b4314f4eacf14a601d586026a962f4002a475aa702c69980a38087aa4e", size = 10460287 }, ] [[package]] @@ -3557,6 +4106,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/40/b0/4562db6223154aa4e22f939003cb92514c79f3d4dccca3444253fd17f902/Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9", size = 18072 }, ] +[[package]] +name = "sentry-sdk" +version = "2.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/2f/a0f732270cc7c1834f5ec45539aec87c360d5483a8bd788217a9102ccfbd/sentry_sdk-2.25.1.tar.gz", hash = "sha256:f9041b7054a7cf12d41eadabe6458ce7c6d6eea7a97cfe1b760b6692e9562cf0", size = 322190 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/b6/84049ab0967affbc7cc7590d86ae0170c1b494edb69df8786707100420e5/sentry_sdk-2.25.1-py2.py3-none-any.whl", hash = "sha256:60b016d0772789454dc55a284a6a44212044d4a16d9f8448725effee97aaf7f6", size = 339851 }, +] + [[package]] name = "setuptools" version = "78.1.0" @@ -4218,6 +4780,50 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 }, ] +[[package]] +name = "ujson" +version = "5.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/00/3110fd566786bfa542adb7932d62035e0c0ef662a8ff6544b6643b3d6fd7/ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", size = 7154885 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/ec/3c551ecfe048bcb3948725251fb0214b5844a12aa60bee08d78315bb1c39/ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00", size = 55353 }, + { url = "https://files.pythonhosted.org/packages/8d/9f/4731ef0671a0653e9f5ba18db7c4596d8ecbf80c7922dd5fe4150f1aea76/ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126", size = 51813 }, + { url = "https://files.pythonhosted.org/packages/1f/2b/44d6b9c1688330bf011f9abfdb08911a9dc74f76926dde74e718d87600da/ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8", size = 51988 }, + { url = "https://files.pythonhosted.org/packages/29/45/f5f5667427c1ec3383478092a414063ddd0dfbebbcc533538fe37068a0a3/ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b", size = 53561 }, + { url = "https://files.pythonhosted.org/packages/26/21/a0c265cda4dd225ec1be595f844661732c13560ad06378760036fc622587/ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9", size = 58497 }, + { url = "https://files.pythonhosted.org/packages/28/36/8fde862094fd2342ccc427a6a8584fed294055fdee341661c78660f7aef3/ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f", size = 997877 }, + { url = "https://files.pythonhosted.org/packages/90/37/9208e40d53baa6da9b6a1c719e0670c3f474c8fc7cc2f1e939ec21c1bc93/ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4", size = 1140632 }, + { url = "https://files.pythonhosted.org/packages/89/d5/2626c87c59802863d44d19e35ad16b7e658e4ac190b0dead17ff25460b4c/ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1", size = 1043513 }, + { url = "https://files.pythonhosted.org/packages/2f/ee/03662ce9b3f16855770f0d70f10f0978ba6210805aa310c4eebe66d36476/ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f", size = 38616 }, + { url = "https://files.pythonhosted.org/packages/3e/20/952dbed5895835ea0b82e81a7be4ebb83f93b079d4d1ead93fcddb3075af/ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720", size = 42071 }, + { url = "https://files.pythonhosted.org/packages/e8/a6/fd3f8bbd80842267e2d06c3583279555e8354c5986c952385199d57a5b6c/ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5", size = 55642 }, + { url = "https://files.pythonhosted.org/packages/a8/47/dd03fd2b5ae727e16d5d18919b383959c6d269c7b948a380fdd879518640/ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e", size = 51807 }, + { url = "https://files.pythonhosted.org/packages/25/23/079a4cc6fd7e2655a473ed9e776ddbb7144e27f04e8fc484a0fb45fe6f71/ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043", size = 51972 }, + { url = "https://files.pythonhosted.org/packages/04/81/668707e5f2177791869b624be4c06fb2473bf97ee33296b18d1cf3092af7/ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1", size = 53686 }, + { url = "https://files.pythonhosted.org/packages/bd/50/056d518a386d80aaf4505ccf3cee1c40d312a46901ed494d5711dd939bc3/ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3", size = 58591 }, + { url = "https://files.pythonhosted.org/packages/fc/d6/aeaf3e2d6fb1f4cfb6bf25f454d60490ed8146ddc0600fae44bfe7eb5a72/ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21", size = 997853 }, + { url = "https://files.pythonhosted.org/packages/f8/d5/1f2a5d2699f447f7d990334ca96e90065ea7f99b142ce96e85f26d7e78e2/ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2", size = 1140689 }, + { url = "https://files.pythonhosted.org/packages/f2/2c/6990f4ccb41ed93744aaaa3786394bca0875503f97690622f3cafc0adfde/ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e", size = 1043576 }, + { url = "https://files.pythonhosted.org/packages/14/f5/a2368463dbb09fbdbf6a696062d0c0f62e4ae6fa65f38f829611da2e8fdd/ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e", size = 38764 }, + { url = "https://files.pythonhosted.org/packages/59/2d/691f741ffd72b6c84438a93749ac57bf1a3f217ac4b0ea4fd0e96119e118/ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc", size = 42211 }, + { url = "https://files.pythonhosted.org/packages/0d/69/b3e3f924bb0e8820bb46671979770c5be6a7d51c77a66324cdb09f1acddb/ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287", size = 55646 }, + { url = "https://files.pythonhosted.org/packages/32/8a/9b748eb543c6cabc54ebeaa1f28035b1bd09c0800235b08e85990734c41e/ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e", size = 51806 }, + { url = "https://files.pythonhosted.org/packages/39/50/4b53ea234413b710a18b305f465b328e306ba9592e13a791a6a6b378869b/ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557", size = 51975 }, + { url = "https://files.pythonhosted.org/packages/b4/9d/8061934f960cdb6dd55f0b3ceeff207fcc48c64f58b43403777ad5623d9e/ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988", size = 53693 }, + { url = "https://files.pythonhosted.org/packages/f5/be/7bfa84b28519ddbb67efc8410765ca7da55e6b93aba84d97764cd5794dbc/ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816", size = 58594 }, + { url = "https://files.pythonhosted.org/packages/48/eb/85d465abafb2c69d9699cfa5520e6e96561db787d36c677370e066c7e2e7/ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20", size = 997853 }, + { url = "https://files.pythonhosted.org/packages/9f/76/2a63409fc05d34dd7d929357b7a45e3a2c96f22b4225cd74becd2ba6c4cb/ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0", size = 1140694 }, + { url = "https://files.pythonhosted.org/packages/45/ed/582c4daba0f3e1688d923b5cb914ada1f9defa702df38a1916c899f7c4d1/ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f", size = 1043580 }, + { url = "https://files.pythonhosted.org/packages/d7/0c/9837fece153051e19c7bade9f88f9b409e026b9525927824cdf16293b43b/ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165", size = 38766 }, + { url = "https://files.pythonhosted.org/packages/d7/72/6cb6728e2738c05bbe9bd522d6fc79f86b9a28402f38663e85a28fddd4a0/ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539", size = 42212 }, +] + +[[package]] +name = "uptime" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/53/6c420ddf6949097d6f9406358951c9322505849bea9cb79efe3acc0bb55d/uptime-3.0.1.tar.gz", hash = "sha256:7c300254775b807ce46e3dcbcda30aa3b9a204b9c57a7ac1e79ee6dbe3942973", size = 6630 } + [[package]] name = "uri-template" version = "1.3.0" @@ -4274,6 +4880,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, ] +[package.optional-dependencies] +standard = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "uvloop" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/a7/4cf0334105c1160dd6819f3297f8700fda7fc30ab4f61fbf3e725acbc7cc/uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8", size = 1447410 }, + { url = "https://files.pythonhosted.org/packages/8c/7c/1517b0bbc2dbe784b563d6ab54f2ef88c890fdad77232c98ed490aa07132/uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0", size = 805476 }, + { url = "https://files.pythonhosted.org/packages/ee/ea/0bfae1aceb82a503f358d8d2fa126ca9dbdb2ba9c7866974faec1cb5875c/uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e", size = 3960855 }, + { url = "https://files.pythonhosted.org/packages/8a/ca/0864176a649838b838f36d44bf31c451597ab363b60dc9e09c9630619d41/uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb", size = 3973185 }, + { url = "https://files.pythonhosted.org/packages/30/bf/08ad29979a936d63787ba47a540de2132169f140d54aa25bc8c3df3e67f4/uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6", size = 3820256 }, + { url = "https://files.pythonhosted.org/packages/da/e2/5cf6ef37e3daf2f06e651aae5ea108ad30df3cb269102678b61ebf1fdf42/uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d", size = 3937323 }, + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284 }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349 }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089 }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770 }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321 }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022 }, + { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123 }, + { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325 }, + { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806 }, + { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068 }, + { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428 }, + { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018 }, +] + [[package]] name = "virtualenv" version = "20.30.0" @@ -4515,3 +5158,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750 }, { url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594 }, ] + +[[package]] +name = "zipp" +version = "3.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630 }, +] From 3059bcc2c3f56ce61a62a1641709f5e0b3ff037f Mon Sep 17 00:00:00 2001 From: Helmut Hoffer von Ankershoffen Date: Mon, 14 Apr 2025 10:28:11 +0200 Subject: [PATCH 2/5] chore: gcp for scheduled --- .github/workflows/test-scheduled.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test-scheduled.yml b/.github/workflows/test-scheduled.yml index 3cf39d44..ed5e31c7 100644 --- a/.github/workflows/test-scheduled.yml +++ b/.github/workflows/test-scheduled.yml @@ -40,5 +40,13 @@ jobs: envkey_AIGNOSTICS_REFRESH_TOKEN: ${{ secrets.AIGNOSTICS_REFRESH_TOKEN }} fail_on_empty: false + - name: Set up cloud credentials + env: + AIGNOSTICS_API_ROOT: https://platform.aignostics.com + CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} + run: | + echo "$CREDENTIALS" | base64 -d > credentials.json + echo "GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/credentials.json" >> $GITHUB_ENV + - name: Run scheduled tests run: make test_scheduled From cb88faf5555a457d1e4f16b23c4f8c11265a95ed Mon Sep 17 00:00:00 2001 From: Helmut Hoffer von Ankershoffen Date: Mon, 14 Apr 2025 12:32:35 +0200 Subject: [PATCH 3/5] merge: polish --- API_REFERENCE_v1.md | 3562 ++++++++++++++++----- README.md | 124 +- docs/partials/README_footer.md | 28 +- docs/partials/README_main.md | 96 +- docs/source/_static/openapi_v1.json | 5 - docs/source/_static/openapi_v1.yaml | 6 - src/aignostics/client/_authentication.py | 2 + src/aignostics/client/_constants.py | 5 +- src/aignostics/client/resources/runs.py | 1 - tests/aignostics/client/scheduled_test.py | 3 +- 10 files changed, 2890 insertions(+), 942 deletions(-) diff --git a/API_REFERENCE_v1.md b/API_REFERENCE_v1.md index 3f318ffb..42cc5470 100644 --- a/API_REFERENCE_v1.md +++ b/API_REFERENCE_v1.md @@ -1,843 +1,2723 @@ # API v1 Reference +## PAPI API Reference v1.0.0 ---- -title: - url: '' -language_tabs: -toc_footers: [] -includes: [] -search: true -highlight_theme: darkula ---- - - - Aignostics H&E TME application - title: Description - type: string - name: - examples: - - HETA - title: Name - type: string - regulatory_classes: - examples: - - - RuO - items: - type: string - title: Regulatory Classes - type: array - slug: - examples: - - heta - title: Slug - type: string - required: - - application_id - - name - - slug - - regulatory_classes - - description - title: ApplicationReadResponse - type: object - ApplicationRunStatus: - enum: - - canceled_system - - canceled_user - - completed - - completed_with_error - - received - - rejected - - running - - scheduled - title: ApplicationRunStatus - type: string - ApplicationVersionReadResponse: - properties: - application_id: - format: uuid - title: Application Id - type: string - application_version_id: - format: uuid - title: Application Version Id - type: string - application_version_slug: - examples: - - tissue-segmentation-qc:v0.0.1 - pattern: ^(?:|-)*:v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ - title: Application Version Slug - type: string - changelog: - title: Changelog - type: string - flow_id: - anyOf: - - format: uuid - type: string - - type: 'null' - title: Flow Id - input_artifacts: - items: - $ref: '#/components/schemas/InputArtifactReadResponse' - title: Input Artifacts - type: array - output_artifacts: - items: - $ref: '#/components/schemas/OutputArtifactReadResponse' - title: Output Artifacts - type: array - version: - title: Version - type: string - required: - - application_version_id - - application_version_slug - - version - - application_id - - changelog - - input_artifacts - - output_artifacts - title: ApplicationVersionReadResponse - type: object - HTTPValidationError: - properties: - detail: - items: - $ref: '#/components/schemas/ValidationError' - title: Detail - type: array - title: HTTPValidationError - type: object - InputArtifact: - properties: - metadata_schema: - title: Metadata Schema - type: object - mime_type: - examples: - - image/tiff - pattern: ^{0,126}/{0,126}$ - title: Mime Type - type: string - name: - title: Name - type: string - required: - - name - - mime_type - - metadata_schema - title: InputArtifact - type: object - InputArtifactCreationRequest: - properties: - download_url: - examples: - - https://example.com/case-no-1-slide.tiff - format: uri - maxLength: 2083 - minLength: 1 - title: Download Url - type: string - metadata: - examples: - - checksum_crc32c: 752f9554 - height: 2000 - height_mpp: 0.5 - width: 10000 - width_mpp: 0.5 - title: Metadata - type: object - name: - examples: - - slide - title: Name - type: string - required: - - name - - download_url - - metadata - title: InputArtifactCreationRequest - type: object - InputArtifactReadResponse: - properties: - metadata_schema: - title: Metadata Schema - type: object - mime_type: - examples: - - image/tiff - pattern: ^{0,126}/{0,126}$ - title: Mime Type - type: string - name: - title: Name - type: string - required: - - name - - mime_type - - metadata_schema - title: InputArtifactReadResponse - type: object - InputArtifactSchemaCreationRequest: - properties: - metadata_schema: - title: Metadata Schema - type: object - mime_type: - examples: - - application/vnd.apache.parquet - title: Mime Type - type: string - name: - title: Name - type: string - required: - - name - - mime_type - - metadata_schema - title: InputArtifactSchemaCreationRequest - type: object - ItemCreationRequest: - properties: - input_artifacts: - items: - $ref: '#/components/schemas/InputArtifactCreationRequest' - title: Input Artifacts - type: array - reference: - examples: - - case-no-1 - title: Reference - type: string - required: - - reference - - input_artifacts - title: ItemCreationRequest - type: object - ItemResultReadResponse: - properties: - application_run_id: - format: uuid - title: Application Run Id - type: string - error: - anyOf: - - type: string - - type: 'null' - title: Error - item_id: - format: uuid - title: Item Id - type: string - output_artifacts: - items: - $ref: '#/components/schemas/OutputArtifactResultReadResponse' - title: Output Artifacts - type: array - reference: - title: Reference - type: string - status: - $ref: '#/components/schemas/ItemStatus' - required: - - item_id - - application_run_id - - reference - - status - - error - - output_artifacts - title: ItemResultReadResponse - type: object - ItemStatus: - enum: - - pending - - canceled_user - - canceled_system - - error_user - - error_system - - succeeded - title: ItemStatus - type: string - OutputArtifact: - properties: - metadata_schema: - title: Metadata Schema - type: object - mime_type: - examples: - - application/vnd.apache.parquet - pattern: ^{0,126}/{0,126}$ - title: Mime Type - type: string - name: - title: Name - type: string - scope: - $ref: '#/components/schemas/OutputArtifactScope' - visibility: - $ref: '#/components/schemas/OutputArtifactVisibility' - required: - - name - - mime_type - - metadata_schema - - scope - - visibility - title: OutputArtifact - type: object - OutputArtifactReadResponse: - properties: - metadata_schema: - title: Metadata Schema - type: object - mime_type: - examples: - - application/vnd.apache.parquet - pattern: ^{0,126}/{0,126}$ - title: Mime Type - type: string - name: - title: Name - type: string - scope: - $ref: '#/components/schemas/OutputArtifactScope' - required: - - name - - mime_type - - metadata_schema - - scope - title: OutputArtifactReadResponse - type: object - OutputArtifactResultReadResponse: - properties: - download_url: - anyOf: - - format: uri - maxLength: 2083 - minLength: 1 - type: string - - type: 'null' - title: Download Url - metadata: - title: Metadata - type: object - mime_type: - examples: - - application/vnd.apache.parquet - pattern: ^{0,126}/{0,126}$ - title: Mime Type - type: string - name: - title: Name - type: string - output_artifact_id: - format: uuid - title: Output Artifact Id - type: string - required: - - output_artifact_id - - name - - mime_type - - metadata - - download_url - title: OutputArtifactResultReadResponse - type: object - OutputArtifactSchemaCreationRequest: - properties: - metadata_schema: - title: Metadata Schema - type: object - mime_type: - examples: - - application/vnd.apache.parquet - title: Mime Type - type: string - name: - title: Name - type: string - scope: - $ref: '#/components/schemas/OutputArtifactScope' - visibility: - $ref: '#/components/schemas/OutputArtifactVisibility' - required: - - name - - mime_type - - scope - - visibility - - metadata_schema - title: OutputArtifactSchemaCreationRequest - type: object - OutputArtifactScope: - enum: - - item - - global - title: OutputArtifactScope - type: string - OutputArtifactVisibility: - enum: - - internal - - external - title: OutputArtifactVisibility - type: string - PayloadInputArtifact: - properties: - download_url: - format: uri - minLength: 1 - title: Download Url - type: string - input_artifact_id: - format: uuid - title: Input Artifact Id - type: string - metadata: - title: Metadata - type: object - required: - - metadata - - download_url - title: PayloadInputArtifact - type: object - PayloadItem: - properties: - input_artifacts: - additionalProperties: - $ref: '#/components/schemas/PayloadInputArtifact' - title: Input Artifacts - type: object - item_id: - format: uuid - title: Item Id - type: string - output_artifacts: - additionalProperties: - $ref: '#/components/schemas/PayloadOutputArtifact' - title: Output Artifacts - type: object - required: - - item_id - - input_artifacts - - output_artifacts - title: PayloadItem - type: object - PayloadOutputArtifact: - properties: - data: - $ref: '#/components/schemas/TransferUrls' - metadata: - $ref: '#/components/schemas/TransferUrls' - output_artifact_id: - format: uuid - title: Output Artifact Id - type: string - required: - - output_artifact_id - - data - - metadata - title: PayloadOutputArtifact - type: object - RunCreationRequest: - properties: - application_version: - anyOf: - - format: uuid - type: string - - $ref: '#/components/schemas/SlugVersionRequest' - examples: - - efbf9822-a1e5-4045-a283-dbf26e8064a9 - title: Application Version - items: - items: - $ref: '#/components/schemas/ItemCreationRequest' - title: Items - type: array - required: - - application_version - - items - title: RunCreationRequest - type: object - RunCreationResponse: - properties: - application_run_id: - format: uuid - title: Application Run Id - type: string - required: - - application_run_id - title: RunCreationResponse - type: object - RunReadResponse: - properties: - application_run_id: - format: uuid - title: Application Run Id - type: string - application_version_id: - format: uuid - title: Application Version Id - type: string - organization_id: - title: Organization Id - type: string - status: - $ref: '#/components/schemas/ApplicationRunStatus' - triggered_at: - format: date-time - title: Triggered At - type: string - triggered_by: - title: Triggered By - type: string - user_payload: - anyOf: - - $ref: '#/components/schemas/UserPayload' - - type: 'null' - required: - - application_run_id - - application_version_id - - organization_id - - status - - triggered_at - - triggered_by - title: RunReadResponse - type: object - SlugVersionRequest: - properties: - application_slug: - pattern: ^(-?)*$ - title: Application Slug - type: string - version: - title: Version - type: string - required: - - application_slug - - version - title: SlugVersionRequest - type: object - TransferUrls: - properties: - download_url: - format: uri - minLength: 1 - title: Download Url - type: string - upload_url: - format: uri - minLength: 1 - title: Upload Url - type: string - required: - - upload_url - - download_url - title: TransferUrls - type: object - UserPayload: - properties: - application_id: - format: uuid - title: Application Id - type: string - application_run_id: - format: uuid - title: Application Run Id - type: string - global_output_artifacts: - anyOf: - - additionalProperties: - $ref: '#/components/schemas/PayloadOutputArtifact' - type: object - - type: 'null' - title: Global Output Artifacts - items: - items: - $ref: '#/components/schemas/PayloadItem' - title: Items - type: array - required: - - application_id - - application_run_id - - global_output_artifacts - - items - title: UserPayload - type: object - ValidationError: - properties: - loc: - items: - anyOf: - - type: string - - type: integer - title: Location - type: array - msg: - title: Message - type: string - type: - title: Error Type - type: string - required: - - loc - - msg - - type - title: ValidationError - type: object - VersionCreationRequest: - properties: - application_id: - format: uuid - title: Application Id - type: string - changelog: - title: Changelog - type: string - flow_id: - format: uuid - title: Flow Id - type: string - input_artifacts: - items: - $ref: '#/components/schemas/InputArtifactSchemaCreationRequest' - title: Input Artifacts - type: array - output_artifacts: - items: - $ref: '#/components/schemas/OutputArtifactSchemaCreationRequest' - title: Output Artifacts - type: array - version: - title: Version - type: string - required: - - version - - application_id - - flow_id - - changelog - - input_artifacts - - output_artifacts - title: VersionCreationRequest - type: object - VersionCreationResponse: - properties: - application_version_id: - format: uuid - title: Application Version Id - type: string - required: - - application_version_id - title: VersionCreationResponse - type: object - VersionReadResponse: - properties: - application_id: - format: uuid - title: Application Id - type: string - application_version_id: - format: uuid - title: Application Version Id - type: string - changelog: - title: Changelog - type: string - created_at: - format: date-time - title: Created At - type: string - flow_id: - anyOf: - - format: uuid - type: string - - type: 'null' - title: Flow Id - input_artifacts: - items: - $ref: '#/components/schemas/InputArtifact' - title: Input Artifacts - type: array - output_artifacts: - items: - $ref: '#/components/schemas/OutputArtifact' - title: Output Artifacts - type: array - version: - title: Version - type: string - required: - - application_version_id - - version - - application_id - - changelog - - input_artifacts - - output_artifacts - - created_at - title: VersionReadResponse - type: object - -info: title: PAPI API Reference version: 1.0.0 openapi: 3.1.0 paths: -/v1/applications: get: operationId: list_applications_v1_applications_get -parameters: - in: query name: page required: false schema: default: 1 minimum: 1 -title: Page type: integer - in: query name: page_size required: false schema: -default: 50 maximum: 100 minimum: 5 title: Page Size type: integer - in: query -name: sort required: false schema: anyOf: - items: type: string type: array - -type: 'null' title: Sort responses: '200': content: application/json: schema: -items: $ref: '#/components/schemas/ApplicationReadResponse' title: Response List -Applications V1 Applications Get type: array description: Successful Response -'422': content: application/json: schema: $ref: -'#/components/schemas/HTTPValidationError' description: Validation Error -summary: List Applications tags: - Externals -/v1/applications/{application_id}/versions: get: operationId: -list_versions_by_application_id_v1_applications__application_id__versions_get -parameters: - in: path name: application_id required: true schema: format: uuid -title: Application Id type: string - in: query name: page required: false -schema: default: 1 minimum: 1 title: Page type: integer - in: query name: -page_size required: false schema: default: 50 maximum: 100 minimum: 5 title: -Page Size type: integer - in: query name: version required: false schema: anyOf: -- type: string - type: 'null' title: Version - in: query name: include required: -false schema: anyOf: - maxItems: 1 minItems: 1 prefixItems: - type: string type: -array - type: 'null' title: Include - in: query name: sort required: false -schema: anyOf: - items: type: string type: array - type: 'null' title: Sort -responses: '200': content: application/json: schema: items: $ref: -'#/components/schemas/ApplicationVersionReadResponse' title: Response List -Versions By Application Id V1 Applications Application Id Versions Get type: -array description: Successful Response '422': content: application/json: schema: -$ref: '#/components/schemas/HTTPValidationError' description: Validation Error -summary: List Versions By Application Id tags: - Externals -/v1/applications/{application_slug}: get: operationId: -read_application_by_slug_v1_applications__application_slug__get parameters: - -in: path name: application_slug required: true schema: title: Application Slug -type: string responses: '200': content: application/json: schema: $ref: -'#/components/schemas/ApplicationReadResponse' description: Successful Response -'422': content: application/json: schema: -$ref: '#/components/schemas/HTTPValidationError' - description: Validation Error - summary: Read Application By Slug - tags: - - Externals - /v1/applications/{application_slug}/versions: - get: - operationId: -list_versions_by_application_slug_v1_applications__application_slug__versions_ge -t - parameters: - - in: path - name: application_slug - required: true - schema: - pattern: ^(-?)*$ title: Application Slug type: string - in: query -name: page required: false schema: default: 1 minimum: 1 title: Page type: -integer - in: query name: page_size required: false schema: default: 50 maximum: -100 minimum: 5 title: Page Size type: integer - in: query name: version -required: false schema: anyOf: - type: string - type: 'null' title: Version - -in: query name: include required: false schema: anyOf: - maxItems: 1 minItems: 1 -prefixItems: - type: string type: array - type: 'null' title: Include - in: -query name: sort required: false schema: anyOf: - items: type: string type: -array - type: 'null' title: Sort responses: '200': content: application/json: -schema: items: $ref: '#/components/schemas/ApplicationVersionReadResponse' -title: Response List Versions By Application Slug V1 Applications Application -Slug Versions Get type: array description: Successful Response '422': content: -application/json: schema: $ref: '#/components/schemas/HTTPValidationError' -description: Validation Error summary: List Versions By Application Slug tags: - -Externals /v1/runs: get: operationId: list_application_runs_v1_runs_get -parameters: - in: query name: application_id required: false schema: anyOf: - -format: uuid type: string - type: 'null' title: Application Id - in: query name: -application_version_id required: false schema: anyOf: - format: uuid type: -string - type: 'null' title: Application Version Id - in: query name: include -required: false schema: anyOf: - maxItems: 1 minItems: 1 prefixItems: - type: -string type: array - type: 'null' title: Include - in: query name: page -required: false schema: default: 1 minimum: 1 title: Page type: integer - in: -query name: page_size required: false schema: default: 50 maximum: 100 minimum: -5 title: Page Size type: integer - in: query name: sort required: false schema: -anyOf: - items: type: string type: array - type: 'null' title: Sort responses: -'200': content: application/json: schema: items: $ref: -'#/components/schemas/RunReadResponse' title: Response List Application Runs V1 -Runs Get type: array description: Successful Response '404': description: -Application run not found '422': content: application/json: schema: $ref: -'#/components/schemas/HTTPValidationError' description: Validation Error -summary: List Application Runs tags: - Externals post: operationId: -create_application_run_v1_runs_post requestBody: content: application/json: -schema: $ref: '#/components/schemas/RunCreationRequest' required: true -responses: '201': content: application/json: schema: $ref: -'#/components/schemas/RunCreationResponse' description: Successful Response -'404': description: Application run not found '422': content: application/json: -schema: $ref: '#/components/schemas/HTTPValidationError' description: Validation -Error summary: Create Application Run tags: - Externals -/v1/runs/{application_run_id}: get: operationId: -get_run_v1_runs__application_run_id__get parameters: - in: path name: -application_run_id required: true schema: format: uuid title: Application Run Id -type: string - in: query name: include required: false schema: anyOf: - -maxItems: 1 minItems: 1 prefixItems: - type: string type: array - type: 'null' -title: Include responses: '200': content: application/json: schema: $ref: -'#/components/schemas/RunReadResponse' description: Successful Response '404': -description: Application run not found '422': content: application/json: schema: -$ref: '#/components/schemas/HTTPValidationError' description: Validation Error -summary: Get Run tags: - Externals /v1/runs/{application_run_id}/cancel: post: -operationId: cancel_run_v1_runs__application_run_id__cancel_post parameters: - -in: path name: application_run_id required: true schema: format: uuid title: -Application Run Id type: string responses: '202': content: application/json: -schema: {} description: Successful Response '404': description: Application run -not found '422': content: application/json: schema: $ref: -'#/components/schemas/HTTPValidationError' description: Validation Error -summary: Cancel Run tags: - Externals /v1/runs/{application_run_id}/results: -delete: operationId: -delete_run_results_v1_runs__application_run_id__results_delete parameters: - in: -path name: application_run_id required: true schema: format: uuid title: -Application Run Id type: string responses: '204': description: Successful -Response '404': description: Application run not found '422': content: -application/json: schema: $ref: '#/components/schemas/HTTPValidationError' -description: Validation Error summary: Delete Run Results tags: - Externals get: -operationId: list_run_results_v1_runs__application_run_id__results_get -parameters: - in: path name: application_run_id required: true schema: format: -uuid title: Application Run Id type: string - in: query name: item_id__in -required: false schema: anyOf: - items: format: uuid type: string type: array - -type: 'null' title: Item Id In - in: query name: page required: false schema: -default: 1 minimum: 1 title: Page type: integer - in: query name: page_size -required: false schema: default: 50 maximum: 100 minimum: 5 title: Page Size -type: integer - in: query name: reference__in required: false schema: anyOf: - -items: type: string type: array - type: 'null' title: Reference In - in: query -name: status__in required: false schema: anyOf: - items: $ref: -'#/components/schemas/ItemStatus' type: array - type: 'null' title: Status In - -in: query name: sort required: false schema: anyOf: - items: type: string type: -array - type: 'null' title: Sort responses: '200': content: application/json: -schema: items: $ref: '#/components/schemas/ItemResultReadResponse' title: -Response List Run Results V1 Runs Application Run Id\ -Results Get type: array description: Successful Response '404': description: -Application run not found '422': content: application/json: schema: $ref: -'#/components/schemas/HTTPValidationError' description: Validation Error -summary: List Run Results tags: - Externals /v1/versions: post: operationId: -register_version_v1_versions_post requestBody: content: application/json: -schema: $ref: '#/components/schemas/VersionCreationRequest' required: true -responses: '201': content: application/json: schema: $ref: -'#/components/schemas/VersionCreationResponse' description: Successful Response -'422': content: application/json: schema: $ref: -'#/components/schemas/HTTPValidationError' description: Validation Error -summary: Register Version tags: - Externals -/v1/versions/{application_version_id}: get: operationId: -get_version_v1_versions__application_version_id__get parameters: - in: path -name: application_version_id required: true schema: format: uuid title: -Application Version Id type: string - in: query name: include required: false -schema: anyOf: - maxItems: 1 minItems: 1 prefixItems: - type: string type: array -- type: 'null' title: Include responses: '200': content: application/json: -schema: $ref: '#/components/schemas/VersionReadResponse' description: Successful -Response '422': content: application/json: schema: $ref: -'#/components/schemas/HTTPValidationError' description: Validation Error -summary: Get Version tags: - Externals servers: - -- url: '' - -> components: - -> schemas: - -> ApplicationReadResponse: - -> properties: - -> application_id: - -> format: uuid - -> title: Application Id - -> type: string - -> description: - -> examples: +> Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu. + +Base URLs: + +* + +## Externals + +### list_applications_v1_applications_get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/applications', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/applications', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/applications` + +*List Applications* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|page|query|integer|false|none| +|page_size|query|integer|false|none| +|sort|query|any|false|none| + +> Example responses + +> 200 Response + +```json +[ + { + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "description": "Aignostics H&E TME application", + "name": "HETA", + "regulatory_classes": [ + "RuO" + ], + "slug": "heta" + } +] +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|Inline| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + +#### Response Schema + +Status Code **200** + +*Response List Applications V1 Applications Get* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|Response List Applications V1 Applications Get|[[ApplicationReadResponse](#schemaapplicationreadresponse)]|false|none|none| +|» ApplicationReadResponse|[ApplicationReadResponse](#schemaapplicationreadresponse)|false|none|none| +|»» application_id|string(uuid)|true|none|none| +|»» description|string|true|none|none| +|»» name|string|true|none|none| +|»» regulatory_classes|[string]|true|none|none| +|»» slug|string|true|none|none| + + +This operation does not require authentication + + +### list_versions_by_application_id_v1_applications__application_id__versions_get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/applications/{application_id}/versions', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/applications/{application_id}/versions', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/applications/{application_id}/versions` + +*List Versions By Application Id* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_id|path|string(uuid)|true|none| +|page|query|integer|false|none| +|page_size|query|integer|false|none| +|version|query|any|false|none| +|include|query|any|false|none| +|sort|query|any|false|none| + +> Example responses + +> 200 Response + +```json +[ + { + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "application_version_slug": "tissue-segmentation-qc:v0.0.1", + "changelog": "string", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "image/tiff", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item" + } + ], + "version": "string" + } +] +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|Inline| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + +#### Response Schema + +Status Code **200** + +*Response List Versions By Application Id V1 Applications Application Id Versions Get* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|Response List Versions By Application Id V1 Applications Application Id Versions Get|[[ApplicationVersionReadResponse](#schemaapplicationversionreadresponse)]|false|none|none| +|» ApplicationVersionReadResponse|[ApplicationVersionReadResponse](#schemaapplicationversionreadresponse)|false|none|none| +|»» application_id|string(uuid)|true|none|none| +|»» application_version_id|string(uuid)|true|none|none| +|»» application_version_slug|string|true|none|none| +|»» changelog|string|true|none|none| +|»» flow_id|any|false|none|none| + +*anyOf* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|string(uuid)|false|none|none| + +*or* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|null|false|none|none| + +*continued* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»» input_artifacts|[[InputArtifactReadResponse](#schemainputartifactreadresponse)]|true|none|none| +|»»» InputArtifactReadResponse|[InputArtifactReadResponse](#schemainputartifactreadresponse)|false|none|none| +|»»»» metadata_schema|object|true|none|none| +|»»»» mime_type|string|true|none|none| +|»»»» name|string|true|none|none| +|»» output_artifacts|[[OutputArtifactReadResponse](#schemaoutputartifactreadresponse)]|true|none|none| +|»»» OutputArtifactReadResponse|[OutputArtifactReadResponse](#schemaoutputartifactreadresponse)|false|none|none| +|»»»» metadata_schema|object|true|none|none| +|»»»» mime_type|string|true|none|none| +|»»»» name|string|true|none|none| +|»»»» scope|[OutputArtifactScope](#schemaoutputartifactscope)|true|none|none| +|»» version|string|true|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|scope|item| +|scope|global| + + +This operation does not require authentication + + +### read_application_by_slug_v1_applications__application_slug__get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/applications/{application_slug}', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/applications/{application_slug}', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/applications/{application_slug}` + +*Read Application By Slug* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_slug|path|string|true|none| + +> Example responses + +> 200 Response + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "description": "Aignostics H&E TME application", + "name": "HETA", + "regulatory_classes": [ + "RuO" + ], + "slug": "heta" +} +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|[ApplicationReadResponse](#schemaapplicationreadresponse)| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + + +This operation does not require authentication + + +### list_versions_by_application_slug_v1_applications__application_slug__versions_get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/applications/{application_slug}/versions', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/applications/{application_slug}/versions', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/applications/{application_slug}/versions` + +*List Versions By Application Slug* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_slug|path|string|true|none| +|page|query|integer|false|none| +|page_size|query|integer|false|none| +|version|query|any|false|none| +|include|query|any|false|none| +|sort|query|any|false|none| + +> Example responses + +> 200 Response + +```json +[ + { + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "application_version_slug": "tissue-segmentation-qc:v0.0.1", + "changelog": "string", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "image/tiff", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item" + } + ], + "version": "string" + } +] +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|Inline| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + +#### Response Schema + +Status Code **200** + +*Response List Versions By Application Slug V1 Applications Application Slug Versions Get* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|Response List Versions By Application Slug V1 Applications Application Slug Versions Get|[[ApplicationVersionReadResponse](#schemaapplicationversionreadresponse)]|false|none|none| +|» ApplicationVersionReadResponse|[ApplicationVersionReadResponse](#schemaapplicationversionreadresponse)|false|none|none| +|»» application_id|string(uuid)|true|none|none| +|»» application_version_id|string(uuid)|true|none|none| +|»» application_version_slug|string|true|none|none| +|»» changelog|string|true|none|none| +|»» flow_id|any|false|none|none| + +*anyOf* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|string(uuid)|false|none|none| + +*or* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|null|false|none|none| + +*continued* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»» input_artifacts|[[InputArtifactReadResponse](#schemainputartifactreadresponse)]|true|none|none| +|»»» InputArtifactReadResponse|[InputArtifactReadResponse](#schemainputartifactreadresponse)|false|none|none| +|»»»» metadata_schema|object|true|none|none| +|»»»» mime_type|string|true|none|none| +|»»»» name|string|true|none|none| +|»» output_artifacts|[[OutputArtifactReadResponse](#schemaoutputartifactreadresponse)]|true|none|none| +|»»» OutputArtifactReadResponse|[OutputArtifactReadResponse](#schemaoutputartifactreadresponse)|false|none|none| +|»»»» metadata_schema|object|true|none|none| +|»»»» mime_type|string|true|none|none| +|»»»» name|string|true|none|none| +|»»»» scope|[OutputArtifactScope](#schemaoutputartifactscope)|true|none|none| +|»» version|string|true|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|scope|item| +|scope|global| + + +This operation does not require authentication + + +### list_application_runs_v1_runs_get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/runs', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/runs', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/runs` + +*List Application Runs* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_id|query|any|false|none| +|application_version_id|query|any|false|none| +|include|query|any|false|none| +|page|query|integer|false|none| +|page_size|query|integer|false|none| +|sort|query|any|false|none| + +> Example responses + +> 200 Response + +```json +[ + { + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "organization_id": "string", + "status": "canceled_system", + "triggered_at": "2019-08-24T14:15:22Z", + "triggered_by": "string", + "user_payload": { + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "global_output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + }, + "items": [ + { + "input_artifacts": { + "property1": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + }, + "property2": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + } + }, + "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c", + "output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + } + } + ] + } + } +] +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|Inline| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|Application run not found|None| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + +#### Response Schema + +Status Code **200** + +*Response List Application Runs V1 Runs Get* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|Response List Application Runs V1 Runs Get|[[RunReadResponse](#schemarunreadresponse)]|false|none|none| +|» RunReadResponse|[RunReadResponse](#schemarunreadresponse)|false|none|none| +|»» application_run_id|string(uuid)|true|none|none| +|»» application_version_id|string(uuid)|true|none|none| +|»» organization_id|string|true|none|none| +|»» status|[ApplicationRunStatus](#schemaapplicationrunstatus)|true|none|none| +|»» triggered_at|string(date-time)|true|none|none| +|»» triggered_by|string|true|none|none| +|»» user_payload|any|false|none|none| + +*anyOf* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|[UserPayload](#schemauserpayload)|false|none|none| +|»»»» application_id|string(uuid)|true|none|none| +|»»»» application_run_id|string(uuid)|true|none|none| +|»»»» global_output_artifacts|any|true|none|none| + +*anyOf* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»»»» *anonymous*|object|false|none|none| +|»»»»»» PayloadOutputArtifact|[PayloadOutputArtifact](#schemapayloadoutputartifact)|false|none|none| +|»»»»»»» data|[TransferUrls](#schematransferurls)|true|none|none| +|»»»»»»»» download_url|string(uri)|true|none|none| +|»»»»»»»» upload_url|string(uri)|true|none|none| +|»»»»»»» metadata|[TransferUrls](#schematransferurls)|true|none|none| +|»»»»»»» output_artifact_id|string(uuid)|true|none|none| + +*or* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»»»» *anonymous*|null|false|none|none| + +*continued* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»»» items|[[PayloadItem](#schemapayloaditem)]|true|none|none| +|»»»»» PayloadItem|[PayloadItem](#schemapayloaditem)|false|none|none| +|»»»»»» input_artifacts|object|true|none|none| +|»»»»»»» PayloadInputArtifact|[PayloadInputArtifact](#schemapayloadinputartifact)|false|none|none| +|»»»»»»»» download_url|string(uri)|true|none|none| +|»»»»»»»» input_artifact_id|string(uuid)|false|none|none| +|»»»»»»»» metadata|object|true|none|none| +|»»»»»» item_id|string(uuid)|true|none|none| +|»»»»»» output_artifacts|object|true|none|none| +|»»»»»»» PayloadOutputArtifact|[PayloadOutputArtifact](#schemapayloadoutputartifact)|false|none|none| + +*or* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|null|false|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|status|canceled_system| +|status|canceled_user| +|status|completed| +|status|completed_with_error| +|status|received| +|status|rejected| +|status|running| +|status|scheduled| + + +This operation does not require authentication + + +### create_application_run_v1_runs_post + + + +> Code samples + +```python +import requests +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' +} + +r = requests.post('/v1/runs', headers = headers) + +print(r.json()) + +``` + +```javascript +const inputBody = '{ + "application_version": "efbf9822-a1e5-4045-a283-dbf26e8064a9", + "items": [ + { + "input_artifacts": [ + { + "download_url": "https://example.com/case-no-1-slide.tiff", + "metadata": { + "checksum_crc32c": "752f9554", + "height": 2000, + "height_mpp": 0.5, + "width": 10000, + "width_mpp": 0.5 + }, + "name": "slide" + } + ], + "reference": "case-no-1" + } + ] +}'; +const headers = { + 'Content-Type':'application/json', + 'Accept':'application/json' +}; + +fetch('/v1/runs', +{ + method: 'POST', + body: inputBody, + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`POST /v1/runs` + +*Create Application Run* + +> Body parameter + +```json +{ + "application_version": "efbf9822-a1e5-4045-a283-dbf26e8064a9", + "items": [ + { + "input_artifacts": [ + { + "download_url": "https://example.com/case-no-1-slide.tiff", + "metadata": { + "checksum_crc32c": "752f9554", + "height": 2000, + "height_mpp": 0.5, + "width": 10000, + "width_mpp": 0.5 + }, + "name": "slide" + } + ], + "reference": "case-no-1" + } + ] +} +``` + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|body|body|[RunCreationRequest](#schemaruncreationrequest)|true|none| + +> Example responses + +> 201 Response + +```json +{ + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe" +} +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|201|[Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)|Successful Response|[RunCreationResponse](#schemaruncreationresponse)| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|Application run not found|None| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + + +This operation does not require authentication + + +### get_run_v1_runs__application_run_id__get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/runs/{application_run_id}', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/runs/{application_run_id}', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/runs/{application_run_id}` + +*Get Run* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_run_id|path|string(uuid)|true|none| +|include|query|any|false|none| + +> Example responses + +> 200 Response + +```json +{ + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "organization_id": "string", + "status": "canceled_system", + "triggered_at": "2019-08-24T14:15:22Z", + "triggered_by": "string", + "user_payload": { + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "global_output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + }, + "items": [ + { + "input_artifacts": { + "property1": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + }, + "property2": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + } + }, + "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c", + "output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + } + } + ] + } +} +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|[RunReadResponse](#schemarunreadresponse)| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|Application run not found|None| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + + +This operation does not require authentication + + +### cancel_run_v1_runs__application_run_id__cancel_post + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.post('/v1/runs/{application_run_id}/cancel', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/runs/{application_run_id}/cancel', +{ + method: 'POST', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`POST /v1/runs/{application_run_id}/cancel` + +*Cancel Run* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_run_id|path|string(uuid)|true|none| + +> Example responses + +> 202 Response + +```json +null +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|202|[Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3)|Successful Response|Inline| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|Application run not found|None| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + +#### Response Schema + + +This operation does not require authentication + + +### delete_run_results_v1_runs__application_run_id__results_delete + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.delete('/v1/runs/{application_run_id}/results', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/runs/{application_run_id}/results', +{ + method: 'DELETE', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`DELETE /v1/runs/{application_run_id}/results` + +*Delete Run Results* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_run_id|path|string(uuid)|true|none| + +> Example responses + +> 422 Response + +```json +{ + "detail": [ + { + "loc": [ + "string" + ], + "msg": "string", + "type": "string" + } + ] +} +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|204|[No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5)|Successful Response|None| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|Application run not found|None| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + + +This operation does not require authentication + + +### list_run_results_v1_runs__application_run_id__results_get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/runs/{application_run_id}/results', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/runs/{application_run_id}/results', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/runs/{application_run_id}/results` + +*List Run Results* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_run_id|path|string(uuid)|true|none| +|item_id__in|query|any|false|none| +|page|query|integer|false|none| +|page_size|query|integer|false|none| +|reference__in|query|any|false|none| +|status__in|query|any|false|none| +|sort|query|any|false|none| + +> Example responses + +> 200 Response + +```json +[ + { + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "error": "string", + "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c", + "output_artifacts": [ + { + "download_url": "http://example.com", + "metadata": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + ], + "reference": "string", + "status": "pending" + } +] +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|Inline| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|Application run not found|None| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + +#### Response Schema + +Status Code **200** + +*Response List Run Results V1 Runs Application Run Id Results Get* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|Response List Run Results V1 Runs Application Run Id Results Get|[[ItemResultReadResponse](#schemaitemresultreadresponse)]|false|none|none| +|» ItemResultReadResponse|[ItemResultReadResponse](#schemaitemresultreadresponse)|false|none|none| +|»» application_run_id|string(uuid)|true|none|none| +|»» error|any|true|none|none| + +*anyOf* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|string|false|none|none| + +*or* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»» *anonymous*|null|false|none|none| + +*continued* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»» item_id|string(uuid)|true|none|none| +|»» output_artifacts|[[OutputArtifactResultReadResponse](#schemaoutputartifactresultreadresponse)]|true|none|none| +|»»» OutputArtifactResultReadResponse|[OutputArtifactResultReadResponse](#schemaoutputartifactresultreadresponse)|false|none|none| +|»»»» download_url|any|true|none|none| + +*anyOf* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»»»» *anonymous*|string(uri)|false|none|none| + +*or* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»»»» *anonymous*|null|false|none|none| + +*continued* + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|»»»» metadata|object|true|none|none| +|»»»» mime_type|string|true|none|none| +|»»»» name|string|true|none|none| +|»»»» output_artifact_id|string(uuid)|true|none|none| +|»» reference|string|true|none|none| +|»» status|[ItemStatus](#schemaitemstatus)|true|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|status|pending| +|status|canceled_user| +|status|canceled_system| +|status|error_user| +|status|error_system| +|status|succeeded| + + +This operation does not require authentication + + +### register_version_v1_versions_post + + + +> Code samples + +```python +import requests +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' +} + +r = requests.post('/v1/versions', headers = headers) + +print(r.json()) + +``` + +```javascript +const inputBody = '{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "changelog": "string", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item", + "visibility": "internal" + } + ], + "version": "string" +}'; +const headers = { + 'Content-Type':'application/json', + 'Accept':'application/json' +}; + +fetch('/v1/versions', +{ + method: 'POST', + body: inputBody, + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`POST /v1/versions` + +*Register Version* + +> Body parameter + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "changelog": "string", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item", + "visibility": "internal" + } + ], + "version": "string" +} +``` + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|body|body|[VersionCreationRequest](#schemaversioncreationrequest)|true|none| + +> Example responses + +> 201 Response + +```json +{ + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c" +} +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|201|[Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)|Successful Response|[VersionCreationResponse](#schemaversioncreationresponse)| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + + +This operation does not require authentication + + +### get_version_v1_versions__application_version_id__get + + + +> Code samples + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/versions/{application_version_id}', headers = headers) + +print(r.json()) + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/versions/{application_version_id}', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +`GET /v1/versions/{application_version_id}` + +*Get Version* + +#### Parameters + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|application_version_id|path|string(uuid)|true|none| +|include|query|any|false|none| + +> Example responses + +> 200 Response + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "changelog": "string", + "created_at": "2019-08-24T14:15:22Z", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "image/tiff", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item", + "visibility": "internal" + } + ], + "version": "string" +} +``` + +#### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful Response|[VersionReadResponse](#schemaversionreadresponse)| +|422|[Unprocessable Entity](https://tools.ietf.org/html/rfc2518#section-10.3)|Validation Error|[HTTPValidationError](#schemahttpvalidationerror)| + + +This operation does not require authentication + + +## Schemas + +### ApplicationReadResponse + + + + + + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "description": "Aignostics H&E TME application", + "name": "HETA", + "regulatory_classes": [ + "RuO" + ], + "slug": "heta" +} + +``` + +ApplicationReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_id|string(uuid)|true|none|none| +|description|string|true|none|none| +|name|string|true|none|none| +|regulatory_classes|[string]|true|none|none| +|slug|string|true|none|none| + +### ApplicationRunStatus + + + + + + +```json +"canceled_system" + +``` + +ApplicationRunStatus + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|ApplicationRunStatus|string|false|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|ApplicationRunStatus|canceled_system| +|ApplicationRunStatus|canceled_user| +|ApplicationRunStatus|completed| +|ApplicationRunStatus|completed_with_error| +|ApplicationRunStatus|received| +|ApplicationRunStatus|rejected| +|ApplicationRunStatus|running| +|ApplicationRunStatus|scheduled| + +### ApplicationVersionReadResponse + + + + + + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "application_version_slug": "tissue-segmentation-qc:v0.0.1", + "changelog": "string", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "image/tiff", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item" + } + ], + "version": "string" +} + +``` + +ApplicationVersionReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_id|string(uuid)|true|none|none| +|application_version_id|string(uuid)|true|none|none| +|application_version_slug|string|true|none|none| +|changelog|string|true|none|none| +|flow_id|any|false|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|string(uuid)|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|null|false|none|none| + +continued + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|input_artifacts|[[InputArtifactReadResponse](#schemainputartifactreadresponse)]|true|none|none| +|output_artifacts|[[OutputArtifactReadResponse](#schemaoutputartifactreadresponse)]|true|none|none| +|version|string|true|none|none| + +### HTTPValidationError + + + + + + +```json +{ + "detail": [ + { + "loc": [ + "string" + ], + "msg": "string", + "type": "string" + } + ] +} + +``` + +HTTPValidationError + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|detail|[[ValidationError](#schemavalidationerror)]|false|none|none| + +### InputArtifact + + + + + + +```json +{ + "metadata_schema": {}, + "mime_type": "image/tiff", + "name": "string" +} + +``` + +InputArtifact + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|metadata_schema|object|true|none|none| +|mime_type|string|true|none|none| +|name|string|true|none|none| + +### InputArtifactCreationRequest + + + + + + +```json +{ + "download_url": "https://example.com/case-no-1-slide.tiff", + "metadata": { + "checksum_crc32c": "752f9554", + "height": 2000, + "height_mpp": 0.5, + "width": 10000, + "width_mpp": 0.5 + }, + "name": "slide" +} + +``` + +InputArtifactCreationRequest + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|download_url|string(uri)|true|none|none| +|metadata|object|true|none|none| +|name|string|true|none|none| + +### InputArtifactReadResponse + + + + + + +```json +{ + "metadata_schema": {}, + "mime_type": "image/tiff", + "name": "string" +} + +``` + +InputArtifactReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|metadata_schema|object|true|none|none| +|mime_type|string|true|none|none| +|name|string|true|none|none| + +### InputArtifactSchemaCreationRequest + + + + + + +```json +{ + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string" +} + +``` + +InputArtifactSchemaCreationRequest + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|metadata_schema|object|true|none|none| +|mime_type|string|true|none|none| +|name|string|true|none|none| + +### ItemCreationRequest + + + + + + +```json +{ + "input_artifacts": [ + { + "download_url": "https://example.com/case-no-1-slide.tiff", + "metadata": { + "checksum_crc32c": "752f9554", + "height": 2000, + "height_mpp": 0.5, + "width": 10000, + "width_mpp": 0.5 + }, + "name": "slide" + } + ], + "reference": "case-no-1" +} + +``` + +ItemCreationRequest + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|input_artifacts|[[InputArtifactCreationRequest](#schemainputartifactcreationrequest)]|true|none|none| +|reference|string|true|none|none| + +### ItemResultReadResponse + + + + + + +```json +{ + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "error": "string", + "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c", + "output_artifacts": [ + { + "download_url": "http://example.com", + "metadata": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + ], + "reference": "string", + "status": "pending" +} + +``` + +ItemResultReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_run_id|string(uuid)|true|none|none| +|error|any|true|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|string|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|null|false|none|none| + +continued + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|item_id|string(uuid)|true|none|none| +|output_artifacts|[[OutputArtifactResultReadResponse](#schemaoutputartifactresultreadresponse)]|true|none|none| +|reference|string|true|none|none| +|status|[ItemStatus](#schemaitemstatus)|true|none|none| + +### ItemStatus + + + + + + +```json +"pending" + +``` + +ItemStatus + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|ItemStatus|string|false|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|ItemStatus|pending| +|ItemStatus|canceled_user| +|ItemStatus|canceled_system| +|ItemStatus|error_user| +|ItemStatus|error_system| +|ItemStatus|succeeded| + +### OutputArtifact + + + + + + +```json +{ + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item", + "visibility": "internal" +} + +``` + +OutputArtifact + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|metadata_schema|object|true|none|none| +|mime_type|string|true|none|none| +|name|string|true|none|none| +|scope|[OutputArtifactScope](#schemaoutputartifactscope)|true|none|none| +|visibility|[OutputArtifactVisibility](#schemaoutputartifactvisibility)|true|none|none| + +### OutputArtifactReadResponse + + + + + + +```json +{ + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item" +} + +``` + +OutputArtifactReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|metadata_schema|object|true|none|none| +|mime_type|string|true|none|none| +|name|string|true|none|none| +|scope|[OutputArtifactScope](#schemaoutputartifactscope)|true|none|none| + +### OutputArtifactResultReadResponse + + + + + + +```json +{ + "download_url": "http://example.com", + "metadata": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" +} + +``` + +OutputArtifactResultReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|download_url|any|true|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|string(uri)|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|null|false|none|none| + +continued + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|metadata|object|true|none|none| +|mime_type|string|true|none|none| +|name|string|true|none|none| +|output_artifact_id|string(uuid)|true|none|none| + +### OutputArtifactSchemaCreationRequest + + + + + + +```json +{ + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item", + "visibility": "internal" +} + +``` + +OutputArtifactSchemaCreationRequest + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|metadata_schema|object|true|none|none| +|mime_type|string|true|none|none| +|name|string|true|none|none| +|scope|[OutputArtifactScope](#schemaoutputartifactscope)|true|none|none| +|visibility|[OutputArtifactVisibility](#schemaoutputartifactvisibility)|true|none|none| + +### OutputArtifactScope + + + + + + +```json +"item" + +``` + +OutputArtifactScope + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|OutputArtifactScope|string|false|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|OutputArtifactScope|item| +|OutputArtifactScope|global| + +### OutputArtifactVisibility + + + + + + +```json +"internal" + +``` + +OutputArtifactVisibility + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|OutputArtifactVisibility|string|false|none|none| + +##### Enumerated Values + +|Property|Value| +|---|---| +|OutputArtifactVisibility|internal| +|OutputArtifactVisibility|external| + +### PayloadInputArtifact + + + + + + +```json +{ + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} +} + +``` + +PayloadInputArtifact + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|download_url|string(uri)|true|none|none| +|input_artifact_id|string(uuid)|false|none|none| +|metadata|object|true|none|none| + +### PayloadItem + + + + + + +```json +{ + "input_artifacts": { + "property1": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + }, + "property2": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + } + }, + "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c", + "output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + } +} + +``` + +PayloadItem + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|input_artifacts|object|true|none|none| +|» **additionalProperties**|[PayloadInputArtifact](#schemapayloadinputartifact)|false|none|none| +|item_id|string(uuid)|true|none|none| +|output_artifacts|object|true|none|none| +|» **additionalProperties**|[PayloadOutputArtifact](#schemapayloadoutputartifact)|false|none|none| + +### PayloadOutputArtifact + + + + + + +```json +{ + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" +} + +``` + +PayloadOutputArtifact + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|data|[TransferUrls](#schematransferurls)|true|none|none| +|metadata|[TransferUrls](#schematransferurls)|true|none|none| +|output_artifact_id|string(uuid)|true|none|none| + +### RunCreationRequest + + + + + + +```json +{ + "application_version": "efbf9822-a1e5-4045-a283-dbf26e8064a9", + "items": [ + { + "input_artifacts": [ + { + "download_url": "https://example.com/case-no-1-slide.tiff", + "metadata": { + "checksum_crc32c": "752f9554", + "height": 2000, + "height_mpp": 0.5, + "width": 10000, + "width_mpp": 0.5 + }, + "name": "slide" + } + ], + "reference": "case-no-1" + } + ] +} + +``` + +RunCreationRequest + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_version|any|true|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|string(uuid)|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|[SlugVersionRequest](#schemaslugversionrequest)|false|none|none| + +continued + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|items|[[ItemCreationRequest](#schemaitemcreationrequest)]|true|none|none| + +### RunCreationResponse + + + + + + +```json +{ + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe" +} + +``` + +RunCreationResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_run_id|string(uuid)|true|none|none| + +### RunReadResponse + + + + + + +```json +{ + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "organization_id": "string", + "status": "canceled_system", + "triggered_at": "2019-08-24T14:15:22Z", + "triggered_by": "string", + "user_payload": { + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "global_output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + }, + "items": [ + { + "input_artifacts": { + "property1": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + }, + "property2": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + } + }, + "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c", + "output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + } + } + ] + } +} + +``` + +RunReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_run_id|string(uuid)|true|none|none| +|application_version_id|string(uuid)|true|none|none| +|organization_id|string|true|none|none| +|status|[ApplicationRunStatus](#schemaapplicationrunstatus)|true|none|none| +|triggered_at|string(date-time)|true|none|none| +|triggered_by|string|true|none|none| +|user_payload|any|false|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|[UserPayload](#schemauserpayload)|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|null|false|none|none| + +### SlugVersionRequest + + + + + + +```json +{ + "application_slug": "string", + "version": "string" +} + +``` + +SlugVersionRequest + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_slug|string|true|none|none| +|version|string|true|none|none| + +### TransferUrls + + + + + + +```json +{ + "download_url": "http://example.com", + "upload_url": "http://example.com" +} + +``` + +TransferUrls + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|download_url|string(uri)|true|none|none| +|upload_url|string(uri)|true|none|none| + +### UserPayload + + + + + + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_run_id": "53c0c6ed-e767-49c4-ad7c-b1a749bf7dfe", + "global_output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + }, + "items": [ + { + "input_artifacts": { + "property1": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + }, + "property2": { + "download_url": "http://example.com", + "input_artifact_id": "a4134709-460b-44b6-99b2-2d637f889159", + "metadata": {} + } + }, + "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c", + "output_artifacts": { + "property1": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + }, + "property2": { + "data": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "metadata": { + "download_url": "http://example.com", + "upload_url": "http://example.com" + }, + "output_artifact_id": "3f78e99c-5d35-4282-9e82-63c422f3af1b" + } + } + } + ] +} + +``` + +UserPayload + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_id|string(uuid)|true|none|none| +|application_run_id|string(uuid)|true|none|none| +|global_output_artifacts|any|true|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|object|false|none|none| +|»» **additionalProperties**|[PayloadOutputArtifact](#schemapayloadoutputartifact)|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|null|false|none|none| + +continued + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|items|[[PayloadItem](#schemapayloaditem)]|true|none|none| + +### ValidationError + + + + + + +```json +{ + "loc": [ + "string" + ], + "msg": "string", + "type": "string" +} + +``` + +ValidationError + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|loc|[anyOf]|true|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|string|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|integer|false|none|none| + +continued + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|msg|string|true|none|none| +|type|string|true|none|none| + +### VersionCreationRequest + + + + + + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "changelog": "string", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item", + "visibility": "internal" + } + ], + "version": "string" +} + +``` + +VersionCreationRequest + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_id|string(uuid)|true|none|none| +|changelog|string|true|none|none| +|flow_id|string(uuid)|true|none|none| +|input_artifacts|[[InputArtifactSchemaCreationRequest](#schemainputartifactschemacreationrequest)]|true|none|none| +|output_artifacts|[[OutputArtifactSchemaCreationRequest](#schemaoutputartifactschemacreationrequest)]|true|none|none| +|version|string|true|none|none| + +### VersionCreationResponse + + + + + + +```json +{ + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c" +} + +``` + +VersionCreationResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_version_id|string(uuid)|true|none|none| + +### VersionReadResponse + + + + + + +```json +{ + "application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c", + "application_version_id": "4108b546-90d4-4689-8b58-78cd9ef4691c", + "changelog": "string", + "created_at": "2019-08-24T14:15:22Z", + "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2", + "input_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "image/tiff", + "name": "string" + } + ], + "output_artifacts": [ + { + "metadata_schema": {}, + "mime_type": "application/vnd.apache.parquet", + "name": "string", + "scope": "item", + "visibility": "internal" + } + ], + "version": "string" +} + +``` + +VersionReadResponse + +#### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|application_id|string(uuid)|true|none|none| +|application_version_id|string(uuid)|true|none|none| +|changelog|string|true|none|none| +|created_at|string(date-time)|true|none|none| +|flow_id|any|false|none|none| + +anyOf + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|string(uuid)|false|none|none| + +or + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|» *anonymous*|null|false|none|none| + +continued + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|input_artifacts|[[InputArtifact](#schemainputartifact)]|true|none|none| +|output_artifacts|[[OutputArtifact](#schemaoutputartifact)]|true|none|none| +|version|string|true|none|none| diff --git a/README.md b/README.md index 1ea3098f..aba96a5a 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,8 @@ --- -from aignx.codegen.models import ItemCreationRequestfrom aignx.codegen.models import ItemCreationRequestfrom aignx.codegen.models import RunCreationRequest +from aignx.codegen.models import ItemCreationRequestfrom aignx.codegen.models +import ItemCreationRequestfrom aignx.codegen.models import RunCreationRequest ## Introduction @@ -113,19 +114,19 @@ The CLI is installed as part of the SDK. You can run it from your terminal using the `uvx` command. See as follows for the primary commands: ```shell -uvx aignostics platform health # checks if CLI and Platform are health -uvx aignostics platform info # shows information about the platform -uvx aignostics application list # lists AI applications available for the user +uvx aignostics system health # checks if the Python SDK and the aignostics platform are healthy +uvx aignostics system info # shows information about the configuration and runtime of the system +uvx aignostics application list # lists AI applications available for you # TODO (Helmut): Explain a bit more. ``` The CLI provides extensive help: ```shell -uvx aignostics --help # all CLI commands -uvx aignostics application --help # help for specific topic -uvx aignostics application list --help # help for specific topic -uvx aignostics serve --help +uvx aignostics --help # all subcommands +uvx aignostics application --help # list subcommands in the application space +uvx aignostics application list --help # help for specific command +uvx aignostics application run --help. # list subcommands in the application run space ``` Check out our @@ -134,32 +135,41 @@ to learn about all commands and options available. ## Using the Python SDK in your Codebase -The following sections showcase how you can integrate the Python SDK in your codebase. +The following sections showcase how you can integrate the Python SDK in your +codebase. ### Installation -Adding Aignostics Python SDK to your codebase as a dependency is easy. -You can directly import add the dependency via your favourite package manager, -e.g., [pip](https://pip.pypa.io/en/stable/) or [uv](https://docs.astral.sh/uv/). +Adding Aignostics Python SDK to your codebase as a dependency is easy. You can +directly import add the dependency via your favourite package manager, e.g., +[pip](https://pip.pypa.io/en/stable/) or [uv](https://docs.astral.sh/uv/). + +**Install with uv** -- If you don't have uv installed follow +[these instructions](https://docs.astral.sh/uv/getting-started/installation/). -**Install with uv** -- If you don't have uv installed follow [these instructions](https://docs.astral.sh/uv/getting-started/installation/). ```shell uv add aignostics # add SDK as dependency to your project ``` **Install with pip** + ```shell pip install aignostics # add SDK as dependency to your project ``` ### Usage -Read the [client reference documentation](https://aignostics.readthedocs.io/en/latest/lib_reference.html) to learn about all classes and methods. +Read the +[client reference documentation](https://aignostics.readthedocs.io/en/latest/lib_reference.html) +to learn about all classes and methods. -The following snippets showcase the basic code to run an application with the Python SDK. -A more detailed example - including comments - is available in the `examples` folder as Python notebooks: -[examples/notebook.ipynb](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.ipynb) (IPython) -[examples/notebook.py](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.py) (Marimo). +The following snippets showcase the basic code to run an application with the +Python SDK. A more detailed example - including comments - is available in the +`examples` folder as Python notebooks: +[examples/notebook.ipynb](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.ipynb) +(IPython) +[examples/notebook.py](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.py) +(Marimo). ```python import aignostics.client @@ -185,13 +195,18 @@ application_run.download_to_folder("path/to/download/folder") ``` ### Authentication Setup -The SDK uses the [OAuth2](https://oauth.net/2/) protocol for authentication. -Please visit [your personal dashboard on the aignostics platform](https://platform.aignostics.com) and scroll to the "Python SDK" section -to find your personalized setup instructions. + +The SDK uses the [OAuth2](https://oauth.net/2/) protocol for authentication. +Please visit +[your personal dashboard on the aignostics platform](https://platform.aignostics.com) +and scroll to the "Python SDK" section to find your personalized setup +instructions. ### Application Run Payloads -The payload expected to trigger an application run is specified by the `RunCreationRequest` pydantic model: +The payload expected to trigger an application run is specified by the +`RunCreationRequest` pydantic model: + ```python RunCreationRequest( application_version=..., @@ -201,8 +216,10 @@ RunCreationRequest( ] ) ``` -Next to the application version of the application you want to run, -it defines the items you want to be processed as `ItemCreationRequest` objects: + +Next to the application version of the application you want to run, it defines +the items you want to be processed as `ItemCreationRequest` objects: + ```python ItemCreationRequest( reference="1", @@ -220,20 +237,29 @@ ItemCreationRequest( ], ), ``` -For each item you want to process, you need to provide a unique `reference` string. -This is used to identify the item in the results later on. -The `input_artifacts` field is a list of `InputArtifactCreationRequest` objects, which defines what data & metadata you need to provide for each item. -The required artifacts depend on the application version you want to run - in the case of test application, there is only one artifact required, which is the image to process on. -The artifact name is defined as `user_slide`. -The `download_url` is a signed URL that allows the Aignostics Platform to download the image data later during processing. +For each item you want to process, you need to provide a unique `reference` +string. This is used to identify the item in the results later on. The +`input_artifacts` field is a list of `InputArtifactCreationRequest` objects, +which defines what data & metadata you need to provide for each item. The +required artifacts depend on the application version you want to run - in the +case of test application, there is only one artifact required, which is the +image to process on. The artifact name is defined as `user_slide`. + +The `download_url` is a signed URL that allows the Aignostics Platform to +download the image data later during processing. #### Self-signed URLs for large files -To make the images you want to process available to the Aignostics Platform, you need to provide a signed URL that allows the platform to download the data. -Self-signed URLs for files in google storage buckets can be generated using the `generate_signed_url` ([code](https://github.com/aignostics/python-sdk/blob/407e74f7ae89289b70efd86cbda59ec7414050d5/src/aignostics/client/utils.py#L85)). +To make the images you want to process available to the Aignostics Platform, you +need to provide a signed URL that allows the platform to download the data. +Self-signed URLs for files in google storage buckets can be generated using the +`generate_signed_url` +([code](https://github.com/aignostics/python-sdk/blob/407e74f7ae89289b70efd86cbda59ec7414050d5/src/aignostics/client/utils.py#L85)). -**We expect that you provide the [required credentials](https://cloud.google.com/docs/authentication/application-default-credentials) for the Google Storage Bucket** +**We expect that you provide the +[required credentials](https://cloud.google.com/docs/authentication/application-default-credentials) +for the Google Storage Bucket** ## Run with Docker @@ -243,7 +269,7 @@ required you can run the CLI as a Docker container: ```shell # TODO (Helmut): Explain about the environment docker run helmuthva/aignostics-python-sdk --help -docker run helmuthva/aignostics-python-sdk platform health +docker run helmuthva/aignostics-python-sdk system health ``` Running via docker compose is supported as well. The .env is passed through from @@ -251,7 +277,7 @@ the host to the Docker container automatically. ```shell docker compose run aignostics --help -docker compose run aignostics platform health +docker compose run aignostics system health ``` @@ -350,13 +376,27 @@ When the application run is cancelled, either by the system or by the user, only ## Further Reading -* Inspect our [security policy](https://aignostics.readthedocs.io/en/latest/security.html) with detailed documentation of checks, tools and principles. -* Check out the [CLI Reference](https://aignostics.readthedocs.io/en/latest/cli_reference.html) with detailed documentation of all CLI commands and options. -* Check out the [Library Reference](https://aignostics.readthedocs.io/en/latest/lib_reference.html) with detailed documentation of public classes and functions. -* Check out the [API Reference](https://aignostics.readthedocs.io/en/latest/api_reference_v1.html) with detailed documentation of all API operations and parameters. -* Our [release notes](https://aignostics.readthedocs.io/en/latest/release-notes.html) provide a complete log of recent improvements and changes. -* In case you want to help us improve 🔬 Aignostics Python SDK: The [contribution guidelines](https://aignostics.readthedocs.io/en/latest/contributing.html) explain how to setup your development environment and create pull requests. -* We gratefully acknowledge the [open source projects](https://aignostics.readthedocs.io/en/latest/attributions.html) that this project builds upon. Thank you to all these wonderful contributors! +- Inspect our + [security policy](https://aignostics.readthedocs.io/en/latest/security.html) + with detailed documentation of checks, tools and principles. +- Check out the + [CLI reference](https://aignostics.readthedocs.io/en/latest/cli_reference.html) + with detailed documentation of all CLI commands and options. +- Check out the + [library reference](https://aignostics.readthedocs.io/en/latest/lib_reference.html) + with detailed documentation of public classes and functions. +- Check out the + [API reference](https://aignostics.readthedocs.io/en/latest/api_reference_v1.html) + with detailed documentation of all API operations and parameters. +- Our + [release notes](https://aignostics.readthedocs.io/en/latest/release-notes.html) + provide a complete log of recent improvements and changes. +- In case you want to help us improve 🔬 Aignostics Python SDK: The + [contribution guidelines](https://aignostics.readthedocs.io/en/latest/contributing.html) + explain how to setup your development environment and create pull requests. +- We gratefully acknowledge the + [open source projects](https://aignostics.readthedocs.io/en/latest/attributions.html) + that this project builds upon. Thank you to all these wonderful contributors! ## Star History diff --git a/docs/partials/README_footer.md b/docs/partials/README_footer.md index 5fed0be7..98e6a62d 100644 --- a/docs/partials/README_footer.md +++ b/docs/partials/README_footer.md @@ -1,12 +1,26 @@ ## Further Reading -* Inspect our [security policy](https://aignostics.readthedocs.io/en/latest/security.html) with detailed documentation of checks, tools and principles. -* Check out the [CLI Reference](https://aignostics.readthedocs.io/en/latest/cli_reference.html) with detailed documentation of all CLI commands and options. -* Check out the [Library Reference](https://aignostics.readthedocs.io/en/latest/lib_reference.html) with detailed documentation of public classes and functions. -* Check out the [API Reference](https://aignostics.readthedocs.io/en/latest/api_reference_v1.html) with detailed documentation of all API operations and parameters. -* Our [release notes](https://aignostics.readthedocs.io/en/latest/release-notes.html) provide a complete log of recent improvements and changes. -* In case you want to help us improve 🔬 Aignostics Python SDK: The [contribution guidelines](https://aignostics.readthedocs.io/en/latest/contributing.html) explain how to setup your development environment and create pull requests. -* We gratefully acknowledge the [open source projects](https://aignostics.readthedocs.io/en/latest/attributions.html) that this project builds upon. Thank you to all these wonderful contributors! +- Inspect our + [security policy](https://aignostics.readthedocs.io/en/latest/security.html) + with detailed documentation of checks, tools and principles. +- Check out the + [CLI reference](https://aignostics.readthedocs.io/en/latest/cli_reference.html) + with detailed documentation of all CLI commands and options. +- Check out the + [library reference](https://aignostics.readthedocs.io/en/latest/lib_reference.html) + with detailed documentation of public classes and functions. +- Check out the + [API reference](https://aignostics.readthedocs.io/en/latest/api_reference_v1.html) + with detailed documentation of all API operations and parameters. +- Our + [release notes](https://aignostics.readthedocs.io/en/latest/release-notes.html) + provide a complete log of recent improvements and changes. +- In case you want to help us improve 🔬 Aignostics Python SDK: The + [contribution guidelines](https://aignostics.readthedocs.io/en/latest/contributing.html) + explain how to setup your development environment and create pull requests. +- We gratefully acknowledge the + [open source projects](https://aignostics.readthedocs.io/en/latest/attributions.html) + that this project builds upon. Thank you to all these wonderful contributors! ## Star History diff --git a/docs/partials/README_main.md b/docs/partials/README_main.md index 6872c866..1e420b88 100644 --- a/docs/partials/README_main.md +++ b/docs/partials/README_main.md @@ -1,4 +1,5 @@ -from aignx.codegen.models import ItemCreationRequestfrom aignx.codegen.models import ItemCreationRequestfrom aignx.codegen.models import RunCreationRequest +from aignx.codegen.models import ItemCreationRequestfrom aignx.codegen.models +import ItemCreationRequestfrom aignx.codegen.models import RunCreationRequest ## Introduction @@ -66,19 +67,19 @@ The CLI is installed as part of the SDK. You can run it from your terminal using the `uvx` command. See as follows for the primary commands: ```shell -uvx aignostics platform health # checks if CLI and Platform are health -uvx aignostics platform info # shows information about the platform -uvx aignostics application list # lists AI applications available for the user +uvx aignostics system health # checks if the Python SDK and the aignostics platform are healthy +uvx aignostics system info # shows information about the configuration and runtime of the system +uvx aignostics application list # lists AI applications available for you # TODO (Helmut): Explain a bit more. ``` The CLI provides extensive help: ```shell -uvx aignostics --help # all CLI commands -uvx aignostics application --help # help for specific topic -uvx aignostics application list --help # help for specific topic -uvx aignostics serve --help +uvx aignostics --help # all subcommands +uvx aignostics application --help # list subcommands in the application space +uvx aignostics application list --help # help for specific command +uvx aignostics application run --help. # list subcommands in the application run space ``` Check out our @@ -87,32 +88,41 @@ to learn about all commands and options available. ## Using the Python SDK in your Codebase -The following sections showcase how you can integrate the Python SDK in your codebase. +The following sections showcase how you can integrate the Python SDK in your +codebase. ### Installation -Adding Aignostics Python SDK to your codebase as a dependency is easy. -You can directly import add the dependency via your favourite package manager, -e.g., [pip](https://pip.pypa.io/en/stable/) or [uv](https://docs.astral.sh/uv/). +Adding Aignostics Python SDK to your codebase as a dependency is easy. You can +directly import add the dependency via your favourite package manager, e.g., +[pip](https://pip.pypa.io/en/stable/) or [uv](https://docs.astral.sh/uv/). + +**Install with uv** -- If you don't have uv installed follow +[these instructions](https://docs.astral.sh/uv/getting-started/installation/). -**Install with uv** -- If you don't have uv installed follow [these instructions](https://docs.astral.sh/uv/getting-started/installation/). ```shell uv add aignostics # add SDK as dependency to your project ``` **Install with pip** + ```shell pip install aignostics # add SDK as dependency to your project ``` ### Usage -Read the [client reference documentation](https://aignostics.readthedocs.io/en/latest/lib_reference.html) to learn about all classes and methods. +Read the +[client reference documentation](https://aignostics.readthedocs.io/en/latest/lib_reference.html) +to learn about all classes and methods. -The following snippets showcase the basic code to run an application with the Python SDK. -A more detailed example - including comments - is available in the `examples` folder as Python notebooks: -[examples/notebook.ipynb](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.ipynb) (IPython) -[examples/notebook.py](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.py) (Marimo). +The following snippets showcase the basic code to run an application with the +Python SDK. A more detailed example - including comments - is available in the +`examples` folder as Python notebooks: +[examples/notebook.ipynb](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.ipynb) +(IPython) +[examples/notebook.py](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.py) +(Marimo). ```python import aignostics.client @@ -138,13 +148,18 @@ application_run.download_to_folder("path/to/download/folder") ``` ### Authentication Setup -The SDK uses the [OAuth2](https://oauth.net/2/) protocol for authentication. -Please visit [your personal dashboard on the aignostics platform](https://platform.aignostics.com) and scroll to the "Python SDK" section -to find your personalized setup instructions. + +The SDK uses the [OAuth2](https://oauth.net/2/) protocol for authentication. +Please visit +[your personal dashboard on the aignostics platform](https://platform.aignostics.com) +and scroll to the "Python SDK" section to find your personalized setup +instructions. ### Application Run Payloads -The payload expected to trigger an application run is specified by the `RunCreationRequest` pydantic model: +The payload expected to trigger an application run is specified by the +`RunCreationRequest` pydantic model: + ```python RunCreationRequest( application_version=..., @@ -154,8 +169,10 @@ RunCreationRequest( ] ) ``` -Next to the application version of the application you want to run, -it defines the items you want to be processed as `ItemCreationRequest` objects: + +Next to the application version of the application you want to run, it defines +the items you want to be processed as `ItemCreationRequest` objects: + ```python ItemCreationRequest( reference="1", @@ -173,20 +190,29 @@ ItemCreationRequest( ], ), ``` -For each item you want to process, you need to provide a unique `reference` string. -This is used to identify the item in the results later on. -The `input_artifacts` field is a list of `InputArtifactCreationRequest` objects, which defines what data & metadata you need to provide for each item. -The required artifacts depend on the application version you want to run - in the case of test application, there is only one artifact required, which is the image to process on. -The artifact name is defined as `user_slide`. -The `download_url` is a signed URL that allows the Aignostics Platform to download the image data later during processing. +For each item you want to process, you need to provide a unique `reference` +string. This is used to identify the item in the results later on. The +`input_artifacts` field is a list of `InputArtifactCreationRequest` objects, +which defines what data & metadata you need to provide for each item. The +required artifacts depend on the application version you want to run - in the +case of test application, there is only one artifact required, which is the +image to process on. The artifact name is defined as `user_slide`. + +The `download_url` is a signed URL that allows the Aignostics Platform to +download the image data later during processing. #### Self-signed URLs for large files -To make the images you want to process available to the Aignostics Platform, you need to provide a signed URL that allows the platform to download the data. -Self-signed URLs for files in google storage buckets can be generated using the `generate_signed_url` ([code](https://github.com/aignostics/python-sdk/blob/407e74f7ae89289b70efd86cbda59ec7414050d5/src/aignostics/client/utils.py#L85)). +To make the images you want to process available to the Aignostics Platform, you +need to provide a signed URL that allows the platform to download the data. +Self-signed URLs for files in google storage buckets can be generated using the +`generate_signed_url` +([code](https://github.com/aignostics/python-sdk/blob/407e74f7ae89289b70efd86cbda59ec7414050d5/src/aignostics/client/utils.py#L85)). -**We expect that you provide the [required credentials](https://cloud.google.com/docs/authentication/application-default-credentials) for the Google Storage Bucket** +**We expect that you provide the +[required credentials](https://cloud.google.com/docs/authentication/application-default-credentials) +for the Google Storage Bucket** ## Run with Docker @@ -196,7 +222,7 @@ required you can run the CLI as a Docker container: ```shell # TODO (Helmut): Explain about the environment docker run helmuthva/aignostics-python-sdk --help -docker run helmuthva/aignostics-python-sdk platform health +docker run helmuthva/aignostics-python-sdk system health ``` Running via docker compose is supported as well. The .env is passed through from @@ -204,5 +230,5 @@ the host to the Docker container automatically. ```shell docker compose run aignostics --help -docker compose run aignostics platform health +docker compose run aignostics system health ``` diff --git a/docs/source/_static/openapi_v1.json b/docs/source/_static/openapi_v1.json index 03345399..5c30db4f 100644 --- a/docs/source/_static/openapi_v1.json +++ b/docs/source/_static/openapi_v1.json @@ -1,5 +1,3 @@ -Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 -https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 { "openapi": "3.1.0", "info": { @@ -1912,6 +1910,3 @@ https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 } } } -Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 -https://logfire-eu.pydantic.dev:443 "POST /v1/metrics HTTP/1.1" 200 2 -https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 diff --git a/docs/source/_static/openapi_v1.yaml b/docs/source/_static/openapi_v1.yaml index 55c430ff..470f21a5 100644 --- a/docs/source/_static/openapi_v1.yaml +++ b/docs/source/_static/openapi_v1.yaml @@ -1,5 +1,3 @@ -Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 -https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 components: schemas: ApplicationReadResponse: @@ -1266,7 +1264,3 @@ paths: - Externals servers: - url: '' -Starting new HTTPS connection (1): logfire-eu.pydantic.dev:443 -Starting new HTTPS connection (2): logfire-eu.pydantic.dev:443 -https://logfire-eu.pydantic.dev:443 "POST /v1/traces HTTP/1.1" 200 0 -https://logfire-eu.pydantic.dev:443 "POST /v1/metrics HTTP/1.1" 200 2 diff --git a/src/aignostics/client/_authentication.py b/src/aignostics/client/_authentication.py index 49ca2944..cf5957f6 100644 --- a/src/aignostics/client/_authentication.py +++ b/src/aignostics/client/_authentication.py @@ -16,6 +16,8 @@ from ._messages import AUTHENTICATION_FAILED, INVALID_REDIRECT_URI from ._settings import settings +CALLBACK_PORT_RETRY_COUNT = 5 + class AuthenticationResult(BaseModel): """Represents the result of an OAuth authentication flow.""" diff --git a/src/aignostics/client/_constants.py b/src/aignostics/client/_constants.py index ab2c9143..1386f268 100644 --- a/src/aignostics/client/_constants.py +++ b/src/aignostics/client/_constants.py @@ -5,11 +5,10 @@ AUDIENCE_PRODUCTION = "https://aignostics-platform-samia" AUTHORIZATION_BASE_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/authorize" TOKEN_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/oauth/token" # noqa: S105 -REDIRECT_URI_PRODUCTION = "http://localhost:8080/" +REDIRECT_URI_PRODUCTION = "http://localhost:8989/" DEVICE_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/oauth/device/code" JWS_JSON_URL_PRODUCTION = "https://aignostics-platform.eu.auth0.com/.well-known/jwks.json" - API_ROOT_STAGING = "https://platform-staging.aignostics.com" # TODO (Andreas): hhva: please fill in AUDIENCE_STAGING = TODO_URL @@ -23,6 +22,6 @@ AUDIENCE_DEV = "https://dev-8ouohmmrbuh2h4vu-samia" AUTHORIZATION_BASE_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/authorize" TOKEN_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/oauth/token" # noqa: S105 -REDIRECT_URI_DEV = "http://localhost:8080/" +REDIRECT_URI_DEV = "http://localhost:8989/" DEVICE_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/oauth/device/code" JWS_JSON_URL_DEV = "https://dev-8ouohmmrbuh2h4vu.eu.auth0.com/.well-known/jwks.json" diff --git a/src/aignostics/client/resources/runs.py b/src/aignostics/client/resources/runs.py index 7e6dee64..85eb31cb 100644 --- a/src/aignostics/client/resources/runs.py +++ b/src/aignostics/client/resources/runs.py @@ -25,7 +25,6 @@ from aignostics.client._utils import calculate_file_crc32c, download_file, mime_type_to_file_ending from aignostics.client.resources.applications import Versions from aignostics.client.resources.utils import paginate -from aignostics.client.utils import calculate_file_crc32c, download_file, mime_type_to_file_ending class ApplicationRun: diff --git a/tests/aignostics/client/scheduled_test.py b/tests/aignostics/client/scheduled_test.py index 93b3d890..a32dfbe3 100644 --- a/tests/aignostics/client/scheduled_test.py +++ b/tests/aignostics/client/scheduled_test.py @@ -19,8 +19,7 @@ ) import aignostics.client -from aignostics.client._utils import calculate_file_crc32c, mime_type_to_file_ending -from aignostics.client.utils import calculate_file_crc32c, generate_signed_url, mime_type_to_file_ending +from aignostics.client._utils import calculate_file_crc32c, generate_signed_url, mime_type_to_file_ending def three_spots_payload() -> list[ItemCreationRequest]: From e3dd95900623eaa5bdab842dd4587139d714ae65 Mon Sep 17 00:00:00 2001 From: Helmut Hoffer von Ankershoffen Date: Mon, 14 Apr 2025 12:40:41 +0200 Subject: [PATCH 4/5] chore(workflow): simplify GCP credentials injection --- .github/workflows/test-and-report.yml | 7 ++----- .github/workflows/test-scheduled.yml | 12 ++---------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test-and-report.yml b/.github/workflows/test-and-report.yml index ae1388ed..c5a2fe98 100644 --- a/.github/workflows/test-and-report.yml +++ b/.github/workflows/test-and-report.yml @@ -73,12 +73,9 @@ jobs: exit 1 fi - - name: Set up cloud credentials - env: - AIGNOSTICS_API_ROOT: https://platform.aignostics.com - CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} + - name: Set up GCP credentials for bucket access run: | - echo "$CREDENTIALS" | base64 -d > credentials.json + echo "${{ secrets.GCP_CREDENTIALS }}" | base64 -d > credentials.json echo "GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/credentials.json" >> $GITHUB_ENV - name: Smoke tests diff --git a/.github/workflows/test-scheduled.yml b/.github/workflows/test-scheduled.yml index bee81a55..098291ce 100644 --- a/.github/workflows/test-scheduled.yml +++ b/.github/workflows/test-scheduled.yml @@ -40,18 +40,10 @@ jobs: envkey_AIGNOSTICS_REFRESH_TOKEN: ${{ secrets.AIGNOSTICS_REFRESH_TOKEN }} fail_on_empty: false - - name: Set up cloud credentials - env: - AIGNOSTICS_API_ROOT: https://platform.aignostics.com - CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} + - name: Set up GCP credentials for bucket access run: | - echo "$CREDENTIALS" | base64 -d > credentials.json + echo "${{ secrets.GCP_CREDENTIALS }}" | base64 -d > credentials.json echo "GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/credentials.json" >> $GITHUB_ENV - name: Run scheduled tests - env: - AIGNOSTICS_API_ROOT: https://platform.aignostics.com - AIGNOSTICS_CLIENT_ID_DEVICE: ${{ secrets.AIGNOSTICS_CLIENT_DEVICE_ID }} - AIGNOSTICS_CLIENT_ID_INTERACTIVE: ${{ secrets.AIGNOSTICS_CLIENT_ID_INTERACTIVE }} - AIGNOSTICS_REFRESH_TOKEN: ${{ secrets.AIGNOSTICS_REFRESH_TOKEN }} run: make test_scheduled From 86ac8abca372c880b0aa6e9b9f22fcb4843f35d1 Mon Sep 17 00:00:00 2001 From: Helmut Hoffer von Ankershoffen Date: Mon, 14 Apr 2025 12:52:58 +0200 Subject: [PATCH 5/5] chore: env --- .env.example | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index fecd62ee..fdb19557 100644 --- a/.env.example +++ b/.env.example @@ -4,12 +4,16 @@ AIGNOSTICS_LOG_LEVEL=INFO AIGNOSTICS_LOG_FILE_ENABLED=false AIGNOSTICS_LOG_FILE_NAME=aignostics.log AIGNOSTICS_LOG_CONSOLE_ENABLED=false -AIGNOSTICS_LOGFIRE_TOKEN=pylf_v1_eu_CwtB1kc64d42qClGkVHLgZ65X4yFCSwPS6lv8ydw35Wm +AIGNOSTICS_LOGFIRE_TOKEN=YOUR_LOGFIRE_TOKEN AIGNOSTICS_LOGFIRE_INSTRUMENT_SYSTEM_METRICS=true -AIGNOSTICS_SENTRY_DSN=https://5e2b6e59746a3cb502589d8c2f0e3b64@o443095.ingest.us.sentry.io/4509130454466560 +AIGNOSTICS_SENTRY_DSN=YOUR_SENTRY_DSN AIGNOSTICS_SENTRY_DEBUG=false AIGNOSTICS_SENTRY_SEND_DEFAULT_PII=false AIGNOSTICS_SENTRY_MAX_BREADCRUMBS=5 AIGNOSTICS_SENTRY_SAMPLE_RATE=1.0 AIGNOSTICS_SENTRY_TRACES_SAMPLE_RATE=1.0 AIGNOSTICS_SENTRY_PROFILES_SAMPLE_RATE=1.0 +AIGNOSTICS_API_ROOT=https://platform.aignostics.com +AIGNOSTICS_CLIENT_ID_DEVICE=YOUR_CLIENT_ID_DEVICE_RETRIEVED_FROM_DASHBOARD +AIGNOSTICS_CLIENT_ID_INTERACTIVE=YOUR_CLIENT_ID_INTERACTIVE_RETRIEVED_FROM_DASHBOARD +GOOGLE_APPLICATION_CREDENTIALS=..../gcp-credentials.json \ No newline at end of file