From 2a8eb899c32132fd04097d2acf86c2107fe48d36 Mon Sep 17 00:00:00 2001 From: Francesco Faraone Date: Thu, 23 Apr 2026 19:01:05 +0200 Subject: [PATCH] MPT-20538 move backend files to backend folder --- .github/workflows/pr-build-merge.yaml | 25 +- .pre-commit-config.yaml | 6 +- LICENSE.txt => LICENSE | 2 +- .python-version => backend/.python-version | 0 alembic.ini => backend/alembic.ini | 0 {app => backend/app}/__init__.py | 0 {app => backend/app}/__main__.py | 0 {app => backend/app}/api_clients/__init__.py | 0 .../app}/api_clients/api_modifier.py | 0 {app => backend/app}/api_clients/base.py | 0 .../app}/api_clients/exchage_rates.py | 0 {app => backend/app}/api_clients/mpt.py | 0 {app => backend/app}/api_clients/optscale.py | 0 {app => backend/app}/auth/__init__.py | 0 {app => backend/app}/auth/auth.py | 0 {app => backend/app}/auth/constants.py | 0 {app => backend/app}/auth/context.py | 0 {app => backend/app}/billing/__init__.py | 0 {app => backend/app}/billing/constants.py | 0 {app => backend/app}/billing/dataclasses.py | 0 {app => backend/app}/billing/enum.py | 0 {app => backend/app}/billing/exceptions.py | 0 .../app}/billing/notification_helper.py | 0 .../app}/billing/process_billing.py | 0 {app => backend/app}/bootstrap.py | 0 {app => backend/app}/cli.py | 0 {app => backend/app}/commands/__init__.py | 0 .../app}/commands/calculate_accounts_stats.py | 0 .../cleanup_obsolete_datasource_expenses.py | 0 .../app}/commands/create_admin_account.py | 0 .../commands/fetch_datasource_expenses.py | 0 {app => backend/app}/commands/openapi.py | 0 .../app}/commands/process_billing.py | 0 .../app}/commands/redeem_entitlements.py | 0 {app => backend/app}/commands/serve.py | 0 {app => backend/app}/commands/shell.py | 0 {app => backend/app}/conf.py | 0 {app => backend/app}/db/__init__.py | 0 {app => backend/app}/db/base.py | 0 {app => backend/app}/db/handlers.py | 0 {app => backend/app}/db/human_readable_pk.py | 0 {app => backend/app}/db/models.py | 0 {app => backend/app}/dependencies/__init__.py | 0 .../app}/dependencies/api_clients.py | 0 {app => backend/app}/dependencies/auth.py | 0 {app => backend/app}/dependencies/core.py | 0 {app => backend/app}/dependencies/db.py | 0 {app => backend/app}/dependencies/path.py | 0 {app => backend/app}/enums.py | 0 {app => backend/app}/logging.py | 0 {app => backend/app}/main.py | 0 {app => backend/app}/notifications.py | 0 {app => backend/app}/openapi/__init__.py | 0 {app => backend/app}/openapi/base.py | 0 {app => backend/app}/openapi/examples.py | 0 {app => backend/app}/pagination.py | 0 {app => backend/app}/parameters.py | 0 {app => backend/app}/routers/__init__.py | 0 {app => backend/app}/routers/accounts.py | 0 {app => backend/app}/routers/employees.py | 0 {app => backend/app}/routers/entitlements.py | 0 {app => backend/app}/routers/expenses.py | 0 {app => backend/app}/routers/organizations.py | 0 {app => backend/app}/rql.py | 0 {app => backend/app}/schemas/__init__.py | 0 {app => backend/app}/schemas/accounts.py | 0 {app => backend/app}/schemas/auth.py | 0 {app => backend/app}/schemas/core.py | 0 {app => backend/app}/schemas/employees.py | 0 {app => backend/app}/schemas/entitlements.py | 0 {app => backend/app}/schemas/expenses.py | 0 {app => backend/app}/schemas/organizations.py | 0 {app => backend/app}/schemas/systems.py | 0 {app => backend/app}/schemas/users.py | 0 {app => backend/app}/telemetry.py | 0 .../app}/templates/emails/invitation.html.j2 | 0 {app => backend/app}/utils.py | 0 {migrations => backend/migrations}/README | 0 {migrations => backend/migrations}/env.py | 0 .../migrations}/script.py.mako | 0 .../versions/085245566812_phase_2_models.py | 0 ...emove_unneeded_audit_fields_from_models.py | 0 ...3_make_expenses_datasourceexpenses_not_.py | 0 ...move_name_from_system_and_user_to_actor.py | 0 .../1ba8d43509b6_migrate_account_type.py | 0 ...85887_create_datasources_expenses_table.py | 0 ...create_unique_constraint_on_datasource_.py | 0 ...7dabef_create_datasourceexpense_linked_.py | 0 ...a_remove_unused_fields_for_system_user_.py | 0 .../51d41f5610bd_add_additional_admin.py | 0 ...faa_merge_d144491ac1b6_and_f4b7143100d4.py | 0 ...df34b13b5_organization_billing_currency.py | 0 ...289e6c92_add_datasource_name_column_to_.py | 0 ...0617026_make_entitlement_owner_required.py | 0 ..._swith_to_daily_and_total_expenses_for_.py | 0 ...84694384_fix_chargesfiles_name_and_enum.py | 0 ...ba90d_add_entitilement_ds_type_and_name.py | 0 ...cdb363_add_entitlement_stats_to_account.py | 0 ...make_total_expenses_datasourceexpenses_.py | 0 ...6d8b9091ed_add_redeem_at_to_entitlement.py | 0 .../8fdb9f36e41c_add_external_id_to_actor.py | 0 ...e8ec11a3_system_change_unique_index_to_.py | 0 ...07_organization_operations_external_id_.py | 0 ...3c4_merge_70fa90617026_and_deded05b7d54.py | 0 .../versions/b55c60f80419_add_chargesfile.py | 0 .../c16f32ef558c_rename_external_ids.py | 0 ...144491ac1b6_create_exchange_rates_model.py | 0 ...0dd09ae4ba_add_day_to_datasourceexpense.py | 0 ...deded05b7d54_add_external_id_to_account.py | 0 ...315a_drop_exchangerates_and_chargesfile.py | 0 .../f4b7143100d4_increase_amount_fields.py | 0 pyproject.toml => backend/pyproject.toml | 17 +- {tests => backend/tests}/__init__.py | 0 {tests => backend/tests}/api/__init__.py | 0 .../tests}/api/test_accounts_api.py | 12 +- .../tests}/api/test_additional_admin_api.py | 6 +- .../tests}/api/test_datasources_api.py | 6 +- .../tests}/api/test_employees_api.py | 4 +- .../tests}/api/test_entitlements_api.py | 6 +- .../tests}/api/test_expenses_api.py | 4 +- .../tests}/api/test_organizations_api.py | 6 +- {tests => backend/tests}/commands/__init__.py | 0 {tests => backend/tests}/commands/conftest.py | 3 +- .../commands/test_calculate_accounts_stats.py | 3 +- ...st_cleanup_obsolete_datasource_expenses.py | 8 +- .../commands/test_create_admin_account.py | 7 +- .../test_fetch_datasource_expenses.py | 12 +- .../tests}/commands/test_openapi.py | 3 +- .../commands/test_redeem_entitlements.py | 11 +- .../tests}/commands/test_serve.py | 3 +- .../tests}/commands/test_shell.py | 3 +- {tests => backend/tests}/conftest.py | 21 +- {tests => backend/tests}/db/__init__.py | 0 {tests => backend/tests}/db/models.py | 5 +- {tests => backend/tests}/db/test_handlers.py | 8 +- {tests => backend/tests}/db/test_models.py | 7 +- {tests => backend/tests}/fixtures/__init__.py | 0 .../tests}/fixtures/mock_api_clients.py | 7 +- {tests => backend/tests}/test_auth.py | 0 .../tests}/test_exchange_rates_client.py | 1 - {tests => backend/tests}/test_logging.py | 1 - .../tests}/test_notifications.py | 5 +- {tests => backend/tests}/test_openapi.py | 3 +- .../tests}/test_process_billing.py | 3 +- {tests => backend/tests}/test_schemas.py | 3 +- {tests => backend/tests}/test_telemetry.py | 3 +- {tests => backend/tests}/test_utils.py | 3 +- {tests => backend/tests}/types.py | 0 uv.lock => backend/uv.lock | 266 +++++++++--------- dev.Dockerfile | 13 +- prod.Dockerfile | 10 +- sonar-project.properties | 4 +- 152 files changed, 249 insertions(+), 261 deletions(-) rename LICENSE.txt => LICENSE (99%) rename .python-version => backend/.python-version (100%) rename alembic.ini => backend/alembic.ini (100%) rename {app => backend/app}/__init__.py (100%) rename {app => backend/app}/__main__.py (100%) rename {app => backend/app}/api_clients/__init__.py (100%) rename {app => backend/app}/api_clients/api_modifier.py (100%) rename {app => backend/app}/api_clients/base.py (100%) rename {app => backend/app}/api_clients/exchage_rates.py (100%) rename {app => backend/app}/api_clients/mpt.py (100%) rename {app => backend/app}/api_clients/optscale.py (100%) rename {app => backend/app}/auth/__init__.py (100%) rename {app => backend/app}/auth/auth.py (100%) rename {app => backend/app}/auth/constants.py (100%) rename {app => backend/app}/auth/context.py (100%) rename {app => backend/app}/billing/__init__.py (100%) rename {app => backend/app}/billing/constants.py (100%) rename {app => backend/app}/billing/dataclasses.py (100%) rename {app => backend/app}/billing/enum.py (100%) rename {app => backend/app}/billing/exceptions.py (100%) rename {app => backend/app}/billing/notification_helper.py (100%) rename {app => backend/app}/billing/process_billing.py (100%) rename {app => backend/app}/bootstrap.py (100%) rename {app => backend/app}/cli.py (100%) rename {app => backend/app}/commands/__init__.py (100%) rename {app => backend/app}/commands/calculate_accounts_stats.py (100%) rename {app => backend/app}/commands/cleanup_obsolete_datasource_expenses.py (100%) rename {app => backend/app}/commands/create_admin_account.py (100%) rename {app => backend/app}/commands/fetch_datasource_expenses.py (100%) rename {app => backend/app}/commands/openapi.py (100%) rename {app => backend/app}/commands/process_billing.py (100%) rename {app => backend/app}/commands/redeem_entitlements.py (100%) rename {app => backend/app}/commands/serve.py (100%) rename {app => backend/app}/commands/shell.py (100%) rename {app => backend/app}/conf.py (100%) rename {app => backend/app}/db/__init__.py (100%) rename {app => backend/app}/db/base.py (100%) rename {app => backend/app}/db/handlers.py (100%) rename {app => backend/app}/db/human_readable_pk.py (100%) rename {app => backend/app}/db/models.py (100%) rename {app => backend/app}/dependencies/__init__.py (100%) rename {app => backend/app}/dependencies/api_clients.py (100%) rename {app => backend/app}/dependencies/auth.py (100%) rename {app => backend/app}/dependencies/core.py (100%) rename {app => backend/app}/dependencies/db.py (100%) rename {app => backend/app}/dependencies/path.py (100%) rename {app => backend/app}/enums.py (100%) rename {app => backend/app}/logging.py (100%) rename {app => backend/app}/main.py (100%) rename {app => backend/app}/notifications.py (100%) rename {app => backend/app}/openapi/__init__.py (100%) rename {app => backend/app}/openapi/base.py (100%) rename {app => backend/app}/openapi/examples.py (100%) rename {app => backend/app}/pagination.py (100%) rename {app => backend/app}/parameters.py (100%) rename {app => backend/app}/routers/__init__.py (100%) rename {app => backend/app}/routers/accounts.py (100%) rename {app => backend/app}/routers/employees.py (100%) rename {app => backend/app}/routers/entitlements.py (100%) rename {app => backend/app}/routers/expenses.py (100%) rename {app => backend/app}/routers/organizations.py (100%) rename {app => backend/app}/rql.py (100%) rename {app => backend/app}/schemas/__init__.py (100%) rename {app => backend/app}/schemas/accounts.py (100%) rename {app => backend/app}/schemas/auth.py (100%) rename {app => backend/app}/schemas/core.py (100%) rename {app => backend/app}/schemas/employees.py (100%) rename {app => backend/app}/schemas/entitlements.py (100%) rename {app => backend/app}/schemas/expenses.py (100%) rename {app => backend/app}/schemas/organizations.py (100%) rename {app => backend/app}/schemas/systems.py (100%) rename {app => backend/app}/schemas/users.py (100%) rename {app => backend/app}/telemetry.py (100%) rename {app => backend/app}/templates/emails/invitation.html.j2 (100%) rename {app => backend/app}/utils.py (100%) rename {migrations => backend/migrations}/README (100%) rename {migrations => backend/migrations}/env.py (100%) rename {migrations => backend/migrations}/script.py.mako (100%) rename {migrations => backend/migrations}/versions/085245566812_phase_2_models.py (100%) rename {migrations => backend/migrations}/versions/09b830373981_remove_unneeded_audit_fields_from_models.py (100%) rename {migrations => backend/migrations}/versions/105fa6bcbc13_make_expenses_datasourceexpenses_not_.py (100%) rename {migrations => backend/migrations}/versions/196f292f2ea2_move_name_from_system_and_user_to_actor.py (100%) rename {migrations => backend/migrations}/versions/1ba8d43509b6_migrate_account_type.py (100%) rename {migrations => backend/migrations}/versions/2f61b7c85887_create_datasources_expenses_table.py (100%) rename {migrations => backend/migrations}/versions/3679d9919a68_create_unique_constraint_on_datasource_.py (100%) rename {migrations => backend/migrations}/versions/46d8a57dabef_create_datasourceexpense_linked_.py (100%) rename {migrations => backend/migrations}/versions/4e8e385293da_remove_unused_fields_for_system_user_.py (100%) rename {migrations => backend/migrations}/versions/51d41f5610bd_add_additional_admin.py (100%) rename {migrations => backend/migrations}/versions/5da9a1a6efaa_merge_d144491ac1b6_and_f4b7143100d4.py (100%) rename {migrations => backend/migrations}/versions/660df34b13b5_organization_billing_currency.py (100%) rename {migrations => backend/migrations}/versions/6d2b289e6c92_add_datasource_name_column_to_.py (100%) rename {migrations => backend/migrations}/versions/70fa90617026_make_entitlement_owner_required.py (100%) rename {migrations => backend/migrations}/versions/75971b70c7de_swith_to_daily_and_total_expenses_for_.py (100%) rename {migrations => backend/migrations}/versions/7cd884694384_fix_chargesfiles_name_and_enum.py (100%) rename {migrations => backend/migrations}/versions/7fcf1b0ba90d_add_entitilement_ds_type_and_name.py (100%) rename {migrations => backend/migrations}/versions/80ece7cdb363_add_entitlement_stats_to_account.py (100%) rename {migrations => backend/migrations}/versions/84791d4463e8_make_total_expenses_datasourceexpenses_.py (100%) rename {migrations => backend/migrations}/versions/8e6d8b9091ed_add_redeem_at_to_entitlement.py (100%) rename {migrations => backend/migrations}/versions/8fdb9f36e41c_add_external_id_to_actor.py (100%) rename {migrations => backend/migrations}/versions/9736e8ec11a3_system_change_unique_index_to_.py (100%) rename {migrations => backend/migrations}/versions/a7badd09ba07_organization_operations_external_id_.py (100%) rename {migrations => backend/migrations}/versions/b34e156283c4_merge_70fa90617026_and_deded05b7d54.py (100%) rename {migrations => backend/migrations}/versions/b55c60f80419_add_chargesfile.py (100%) rename {migrations => backend/migrations}/versions/c16f32ef558c_rename_external_ids.py (100%) rename {migrations => backend/migrations}/versions/d144491ac1b6_create_exchange_rates_model.py (100%) rename {migrations => backend/migrations}/versions/d90dd09ae4ba_add_day_to_datasourceexpense.py (100%) rename {migrations => backend/migrations}/versions/deded05b7d54_add_external_id_to_account.py (100%) rename {migrations => backend/migrations}/versions/e2964d52315a_drop_exchangerates_and_chargesfile.py (100%) rename {migrations => backend/migrations}/versions/f4b7143100d4_increase_amount_fields.py (100%) rename pyproject.toml => backend/pyproject.toml (94%) rename {tests => backend/tests}/__init__.py (100%) rename {tests => backend/tests}/api/__init__.py (100%) rename {tests => backend/tests}/api/test_accounts_api.py (100%) rename {tests => backend/tests}/api/test_additional_admin_api.py (100%) rename {tests => backend/tests}/api/test_datasources_api.py (100%) rename {tests => backend/tests}/api/test_employees_api.py (100%) rename {tests => backend/tests}/api/test_entitlements_api.py (100%) rename {tests => backend/tests}/api/test_expenses_api.py (100%) rename {tests => backend/tests}/api/test_organizations_api.py (100%) rename {tests => backend/tests}/commands/__init__.py (100%) rename {tests => backend/tests}/commands/conftest.py (99%) rename {tests => backend/tests}/commands/test_calculate_accounts_stats.py (99%) rename {tests => backend/tests}/commands/test_cleanup_obsolete_datasource_expenses.py (100%) rename {tests => backend/tests}/commands/test_create_admin_account.py (99%) rename {tests => backend/tests}/commands/test_fetch_datasource_expenses.py (100%) rename {tests => backend/tests}/commands/test_openapi.py (99%) rename {tests => backend/tests}/commands/test_redeem_entitlements.py (99%) rename {tests => backend/tests}/commands/test_serve.py (99%) rename {tests => backend/tests}/commands/test_shell.py (99%) rename {tests => backend/tests}/conftest.py (99%) rename {tests => backend/tests}/db/__init__.py (100%) rename {tests => backend/tests}/db/models.py (99%) rename {tests => backend/tests}/db/test_handlers.py (100%) rename {tests => backend/tests}/db/test_models.py (99%) rename {tests => backend/tests}/fixtures/__init__.py (100%) rename {tests => backend/tests}/fixtures/mock_api_clients.py (99%) rename {tests => backend/tests}/test_auth.py (100%) rename {tests => backend/tests}/test_exchange_rates_client.py (99%) rename {tests => backend/tests}/test_logging.py (99%) rename {tests => backend/tests}/test_notifications.py (99%) rename {tests => backend/tests}/test_openapi.py (99%) rename {tests => backend/tests}/test_process_billing.py (99%) rename {tests => backend/tests}/test_schemas.py (99%) rename {tests => backend/tests}/test_telemetry.py (99%) rename {tests => backend/tests}/test_utils.py (99%) rename {tests => backend/tests}/types.py (100%) rename uv.lock => backend/uv.lock (94%) diff --git a/.github/workflows/pr-build-merge.yaml b/.github/workflows/pr-build-merge.yaml index a184321..a04186a 100644 --- a/.github/workflows/pr-build-merge.yaml +++ b/.github/workflows/pr-build-merge.yaml @@ -38,30 +38,30 @@ jobs: uses: astral-sh/setup-uv@v4 with: enable-cache: true - cache-dependency-glob: "uv.lock" + cache-dependency-glob: "backend/uv.lock" - name: Install Python uses: actions/setup-python@v5 with: - python-version-file: ".python-version" + python-version-file: "backend/.python-version" - name: Install the project dependancies - run: uv sync --all-extras --dev + run: uv --project backend sync --all-extras --dev - name: Create the .env file run: cp env.example .env - name: Run formatting checks - run: uv run ruff format --check --diff . + run: uv --project backend run ruff --config backend/pyproject.toml format --check --diff backend - name: Run linting - run: uv run ruff check . + run: uv --project backend run ruff --config backend/pyproject.toml check backend - name: Run security checks - run: uv run bandit -c pyproject.toml -r . -f json -o bandit.json + run: uv --project backend run bandit -c backend/pyproject.toml -r backend -f json -o bandit.json - name: Run tests - run: uv run pytest + run: uv --project backend run pytest --rootdir=backend -c backend/pyproject.toml backend env: FFC_EXT_POSTGRES_HOST: localhost FFC_EXT_POSTGRES_PORT: 5432 @@ -122,14 +122,3 @@ jobs: name: coverage-report path: htmlcov retention-days: 10 - - - name: Generate openapi.json - run: uv run ffcops openapi -f json -o openapi.json - - - name: Save openapi.json the artefacts - uses: actions/upload-artifact@v4 - if: ${{ !env.ACT }} - with: - name: openapi-spec - path: openapi.json - retention-days: 10 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ca6c6c8..ae1e38b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,6 +16,8 @@ repos: hooks: - id: ruff args: + - --config + - backend/pyproject.toml - --fix - id: ruff-format - repo: https://github.com/PyCQA/bandit @@ -24,6 +26,6 @@ repos: - id: bandit args: - -c - - pyproject.toml + - backend/pyproject.toml - -r - - . + - backend/ diff --git a/LICENSE.txt b/LICENSE similarity index 99% rename from LICENSE.txt rename to LICENSE index 5e85470..54fae84 100644 --- a/LICENSE.txt +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2024 - SoftwareOne AG + Copyright 2026 - SoftwareOne AG Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/.python-version b/backend/.python-version similarity index 100% rename from .python-version rename to backend/.python-version diff --git a/alembic.ini b/backend/alembic.ini similarity index 100% rename from alembic.ini rename to backend/alembic.ini diff --git a/app/__init__.py b/backend/app/__init__.py similarity index 100% rename from app/__init__.py rename to backend/app/__init__.py diff --git a/app/__main__.py b/backend/app/__main__.py similarity index 100% rename from app/__main__.py rename to backend/app/__main__.py diff --git a/app/api_clients/__init__.py b/backend/app/api_clients/__init__.py similarity index 100% rename from app/api_clients/__init__.py rename to backend/app/api_clients/__init__.py diff --git a/app/api_clients/api_modifier.py b/backend/app/api_clients/api_modifier.py similarity index 100% rename from app/api_clients/api_modifier.py rename to backend/app/api_clients/api_modifier.py diff --git a/app/api_clients/base.py b/backend/app/api_clients/base.py similarity index 100% rename from app/api_clients/base.py rename to backend/app/api_clients/base.py diff --git a/app/api_clients/exchage_rates.py b/backend/app/api_clients/exchage_rates.py similarity index 100% rename from app/api_clients/exchage_rates.py rename to backend/app/api_clients/exchage_rates.py diff --git a/app/api_clients/mpt.py b/backend/app/api_clients/mpt.py similarity index 100% rename from app/api_clients/mpt.py rename to backend/app/api_clients/mpt.py diff --git a/app/api_clients/optscale.py b/backend/app/api_clients/optscale.py similarity index 100% rename from app/api_clients/optscale.py rename to backend/app/api_clients/optscale.py diff --git a/app/auth/__init__.py b/backend/app/auth/__init__.py similarity index 100% rename from app/auth/__init__.py rename to backend/app/auth/__init__.py diff --git a/app/auth/auth.py b/backend/app/auth/auth.py similarity index 100% rename from app/auth/auth.py rename to backend/app/auth/auth.py diff --git a/app/auth/constants.py b/backend/app/auth/constants.py similarity index 100% rename from app/auth/constants.py rename to backend/app/auth/constants.py diff --git a/app/auth/context.py b/backend/app/auth/context.py similarity index 100% rename from app/auth/context.py rename to backend/app/auth/context.py diff --git a/app/billing/__init__.py b/backend/app/billing/__init__.py similarity index 100% rename from app/billing/__init__.py rename to backend/app/billing/__init__.py diff --git a/app/billing/constants.py b/backend/app/billing/constants.py similarity index 100% rename from app/billing/constants.py rename to backend/app/billing/constants.py diff --git a/app/billing/dataclasses.py b/backend/app/billing/dataclasses.py similarity index 100% rename from app/billing/dataclasses.py rename to backend/app/billing/dataclasses.py diff --git a/app/billing/enum.py b/backend/app/billing/enum.py similarity index 100% rename from app/billing/enum.py rename to backend/app/billing/enum.py diff --git a/app/billing/exceptions.py b/backend/app/billing/exceptions.py similarity index 100% rename from app/billing/exceptions.py rename to backend/app/billing/exceptions.py diff --git a/app/billing/notification_helper.py b/backend/app/billing/notification_helper.py similarity index 100% rename from app/billing/notification_helper.py rename to backend/app/billing/notification_helper.py diff --git a/app/billing/process_billing.py b/backend/app/billing/process_billing.py similarity index 100% rename from app/billing/process_billing.py rename to backend/app/billing/process_billing.py diff --git a/app/bootstrap.py b/backend/app/bootstrap.py similarity index 100% rename from app/bootstrap.py rename to backend/app/bootstrap.py diff --git a/app/cli.py b/backend/app/cli.py similarity index 100% rename from app/cli.py rename to backend/app/cli.py diff --git a/app/commands/__init__.py b/backend/app/commands/__init__.py similarity index 100% rename from app/commands/__init__.py rename to backend/app/commands/__init__.py diff --git a/app/commands/calculate_accounts_stats.py b/backend/app/commands/calculate_accounts_stats.py similarity index 100% rename from app/commands/calculate_accounts_stats.py rename to backend/app/commands/calculate_accounts_stats.py diff --git a/app/commands/cleanup_obsolete_datasource_expenses.py b/backend/app/commands/cleanup_obsolete_datasource_expenses.py similarity index 100% rename from app/commands/cleanup_obsolete_datasource_expenses.py rename to backend/app/commands/cleanup_obsolete_datasource_expenses.py diff --git a/app/commands/create_admin_account.py b/backend/app/commands/create_admin_account.py similarity index 100% rename from app/commands/create_admin_account.py rename to backend/app/commands/create_admin_account.py diff --git a/app/commands/fetch_datasource_expenses.py b/backend/app/commands/fetch_datasource_expenses.py similarity index 100% rename from app/commands/fetch_datasource_expenses.py rename to backend/app/commands/fetch_datasource_expenses.py diff --git a/app/commands/openapi.py b/backend/app/commands/openapi.py similarity index 100% rename from app/commands/openapi.py rename to backend/app/commands/openapi.py diff --git a/app/commands/process_billing.py b/backend/app/commands/process_billing.py similarity index 100% rename from app/commands/process_billing.py rename to backend/app/commands/process_billing.py diff --git a/app/commands/redeem_entitlements.py b/backend/app/commands/redeem_entitlements.py similarity index 100% rename from app/commands/redeem_entitlements.py rename to backend/app/commands/redeem_entitlements.py diff --git a/app/commands/serve.py b/backend/app/commands/serve.py similarity index 100% rename from app/commands/serve.py rename to backend/app/commands/serve.py diff --git a/app/commands/shell.py b/backend/app/commands/shell.py similarity index 100% rename from app/commands/shell.py rename to backend/app/commands/shell.py diff --git a/app/conf.py b/backend/app/conf.py similarity index 100% rename from app/conf.py rename to backend/app/conf.py diff --git a/app/db/__init__.py b/backend/app/db/__init__.py similarity index 100% rename from app/db/__init__.py rename to backend/app/db/__init__.py diff --git a/app/db/base.py b/backend/app/db/base.py similarity index 100% rename from app/db/base.py rename to backend/app/db/base.py diff --git a/app/db/handlers.py b/backend/app/db/handlers.py similarity index 100% rename from app/db/handlers.py rename to backend/app/db/handlers.py diff --git a/app/db/human_readable_pk.py b/backend/app/db/human_readable_pk.py similarity index 100% rename from app/db/human_readable_pk.py rename to backend/app/db/human_readable_pk.py diff --git a/app/db/models.py b/backend/app/db/models.py similarity index 100% rename from app/db/models.py rename to backend/app/db/models.py diff --git a/app/dependencies/__init__.py b/backend/app/dependencies/__init__.py similarity index 100% rename from app/dependencies/__init__.py rename to backend/app/dependencies/__init__.py diff --git a/app/dependencies/api_clients.py b/backend/app/dependencies/api_clients.py similarity index 100% rename from app/dependencies/api_clients.py rename to backend/app/dependencies/api_clients.py diff --git a/app/dependencies/auth.py b/backend/app/dependencies/auth.py similarity index 100% rename from app/dependencies/auth.py rename to backend/app/dependencies/auth.py diff --git a/app/dependencies/core.py b/backend/app/dependencies/core.py similarity index 100% rename from app/dependencies/core.py rename to backend/app/dependencies/core.py diff --git a/app/dependencies/db.py b/backend/app/dependencies/db.py similarity index 100% rename from app/dependencies/db.py rename to backend/app/dependencies/db.py diff --git a/app/dependencies/path.py b/backend/app/dependencies/path.py similarity index 100% rename from app/dependencies/path.py rename to backend/app/dependencies/path.py diff --git a/app/enums.py b/backend/app/enums.py similarity index 100% rename from app/enums.py rename to backend/app/enums.py diff --git a/app/logging.py b/backend/app/logging.py similarity index 100% rename from app/logging.py rename to backend/app/logging.py diff --git a/app/main.py b/backend/app/main.py similarity index 100% rename from app/main.py rename to backend/app/main.py diff --git a/app/notifications.py b/backend/app/notifications.py similarity index 100% rename from app/notifications.py rename to backend/app/notifications.py diff --git a/app/openapi/__init__.py b/backend/app/openapi/__init__.py similarity index 100% rename from app/openapi/__init__.py rename to backend/app/openapi/__init__.py diff --git a/app/openapi/base.py b/backend/app/openapi/base.py similarity index 100% rename from app/openapi/base.py rename to backend/app/openapi/base.py diff --git a/app/openapi/examples.py b/backend/app/openapi/examples.py similarity index 100% rename from app/openapi/examples.py rename to backend/app/openapi/examples.py diff --git a/app/pagination.py b/backend/app/pagination.py similarity index 100% rename from app/pagination.py rename to backend/app/pagination.py diff --git a/app/parameters.py b/backend/app/parameters.py similarity index 100% rename from app/parameters.py rename to backend/app/parameters.py diff --git a/app/routers/__init__.py b/backend/app/routers/__init__.py similarity index 100% rename from app/routers/__init__.py rename to backend/app/routers/__init__.py diff --git a/app/routers/accounts.py b/backend/app/routers/accounts.py similarity index 100% rename from app/routers/accounts.py rename to backend/app/routers/accounts.py diff --git a/app/routers/employees.py b/backend/app/routers/employees.py similarity index 100% rename from app/routers/employees.py rename to backend/app/routers/employees.py diff --git a/app/routers/entitlements.py b/backend/app/routers/entitlements.py similarity index 100% rename from app/routers/entitlements.py rename to backend/app/routers/entitlements.py diff --git a/app/routers/expenses.py b/backend/app/routers/expenses.py similarity index 100% rename from app/routers/expenses.py rename to backend/app/routers/expenses.py diff --git a/app/routers/organizations.py b/backend/app/routers/organizations.py similarity index 100% rename from app/routers/organizations.py rename to backend/app/routers/organizations.py diff --git a/app/rql.py b/backend/app/rql.py similarity index 100% rename from app/rql.py rename to backend/app/rql.py diff --git a/app/schemas/__init__.py b/backend/app/schemas/__init__.py similarity index 100% rename from app/schemas/__init__.py rename to backend/app/schemas/__init__.py diff --git a/app/schemas/accounts.py b/backend/app/schemas/accounts.py similarity index 100% rename from app/schemas/accounts.py rename to backend/app/schemas/accounts.py diff --git a/app/schemas/auth.py b/backend/app/schemas/auth.py similarity index 100% rename from app/schemas/auth.py rename to backend/app/schemas/auth.py diff --git a/app/schemas/core.py b/backend/app/schemas/core.py similarity index 100% rename from app/schemas/core.py rename to backend/app/schemas/core.py diff --git a/app/schemas/employees.py b/backend/app/schemas/employees.py similarity index 100% rename from app/schemas/employees.py rename to backend/app/schemas/employees.py diff --git a/app/schemas/entitlements.py b/backend/app/schemas/entitlements.py similarity index 100% rename from app/schemas/entitlements.py rename to backend/app/schemas/entitlements.py diff --git a/app/schemas/expenses.py b/backend/app/schemas/expenses.py similarity index 100% rename from app/schemas/expenses.py rename to backend/app/schemas/expenses.py diff --git a/app/schemas/organizations.py b/backend/app/schemas/organizations.py similarity index 100% rename from app/schemas/organizations.py rename to backend/app/schemas/organizations.py diff --git a/app/schemas/systems.py b/backend/app/schemas/systems.py similarity index 100% rename from app/schemas/systems.py rename to backend/app/schemas/systems.py diff --git a/app/schemas/users.py b/backend/app/schemas/users.py similarity index 100% rename from app/schemas/users.py rename to backend/app/schemas/users.py diff --git a/app/telemetry.py b/backend/app/telemetry.py similarity index 100% rename from app/telemetry.py rename to backend/app/telemetry.py diff --git a/app/templates/emails/invitation.html.j2 b/backend/app/templates/emails/invitation.html.j2 similarity index 100% rename from app/templates/emails/invitation.html.j2 rename to backend/app/templates/emails/invitation.html.j2 diff --git a/app/utils.py b/backend/app/utils.py similarity index 100% rename from app/utils.py rename to backend/app/utils.py diff --git a/migrations/README b/backend/migrations/README similarity index 100% rename from migrations/README rename to backend/migrations/README diff --git a/migrations/env.py b/backend/migrations/env.py similarity index 100% rename from migrations/env.py rename to backend/migrations/env.py diff --git a/migrations/script.py.mako b/backend/migrations/script.py.mako similarity index 100% rename from migrations/script.py.mako rename to backend/migrations/script.py.mako diff --git a/migrations/versions/085245566812_phase_2_models.py b/backend/migrations/versions/085245566812_phase_2_models.py similarity index 100% rename from migrations/versions/085245566812_phase_2_models.py rename to backend/migrations/versions/085245566812_phase_2_models.py diff --git a/migrations/versions/09b830373981_remove_unneeded_audit_fields_from_models.py b/backend/migrations/versions/09b830373981_remove_unneeded_audit_fields_from_models.py similarity index 100% rename from migrations/versions/09b830373981_remove_unneeded_audit_fields_from_models.py rename to backend/migrations/versions/09b830373981_remove_unneeded_audit_fields_from_models.py diff --git a/migrations/versions/105fa6bcbc13_make_expenses_datasourceexpenses_not_.py b/backend/migrations/versions/105fa6bcbc13_make_expenses_datasourceexpenses_not_.py similarity index 100% rename from migrations/versions/105fa6bcbc13_make_expenses_datasourceexpenses_not_.py rename to backend/migrations/versions/105fa6bcbc13_make_expenses_datasourceexpenses_not_.py diff --git a/migrations/versions/196f292f2ea2_move_name_from_system_and_user_to_actor.py b/backend/migrations/versions/196f292f2ea2_move_name_from_system_and_user_to_actor.py similarity index 100% rename from migrations/versions/196f292f2ea2_move_name_from_system_and_user_to_actor.py rename to backend/migrations/versions/196f292f2ea2_move_name_from_system_and_user_to_actor.py diff --git a/migrations/versions/1ba8d43509b6_migrate_account_type.py b/backend/migrations/versions/1ba8d43509b6_migrate_account_type.py similarity index 100% rename from migrations/versions/1ba8d43509b6_migrate_account_type.py rename to backend/migrations/versions/1ba8d43509b6_migrate_account_type.py diff --git a/migrations/versions/2f61b7c85887_create_datasources_expenses_table.py b/backend/migrations/versions/2f61b7c85887_create_datasources_expenses_table.py similarity index 100% rename from migrations/versions/2f61b7c85887_create_datasources_expenses_table.py rename to backend/migrations/versions/2f61b7c85887_create_datasources_expenses_table.py diff --git a/migrations/versions/3679d9919a68_create_unique_constraint_on_datasource_.py b/backend/migrations/versions/3679d9919a68_create_unique_constraint_on_datasource_.py similarity index 100% rename from migrations/versions/3679d9919a68_create_unique_constraint_on_datasource_.py rename to backend/migrations/versions/3679d9919a68_create_unique_constraint_on_datasource_.py diff --git a/migrations/versions/46d8a57dabef_create_datasourceexpense_linked_.py b/backend/migrations/versions/46d8a57dabef_create_datasourceexpense_linked_.py similarity index 100% rename from migrations/versions/46d8a57dabef_create_datasourceexpense_linked_.py rename to backend/migrations/versions/46d8a57dabef_create_datasourceexpense_linked_.py diff --git a/migrations/versions/4e8e385293da_remove_unused_fields_for_system_user_.py b/backend/migrations/versions/4e8e385293da_remove_unused_fields_for_system_user_.py similarity index 100% rename from migrations/versions/4e8e385293da_remove_unused_fields_for_system_user_.py rename to backend/migrations/versions/4e8e385293da_remove_unused_fields_for_system_user_.py diff --git a/migrations/versions/51d41f5610bd_add_additional_admin.py b/backend/migrations/versions/51d41f5610bd_add_additional_admin.py similarity index 100% rename from migrations/versions/51d41f5610bd_add_additional_admin.py rename to backend/migrations/versions/51d41f5610bd_add_additional_admin.py diff --git a/migrations/versions/5da9a1a6efaa_merge_d144491ac1b6_and_f4b7143100d4.py b/backend/migrations/versions/5da9a1a6efaa_merge_d144491ac1b6_and_f4b7143100d4.py similarity index 100% rename from migrations/versions/5da9a1a6efaa_merge_d144491ac1b6_and_f4b7143100d4.py rename to backend/migrations/versions/5da9a1a6efaa_merge_d144491ac1b6_and_f4b7143100d4.py diff --git a/migrations/versions/660df34b13b5_organization_billing_currency.py b/backend/migrations/versions/660df34b13b5_organization_billing_currency.py similarity index 100% rename from migrations/versions/660df34b13b5_organization_billing_currency.py rename to backend/migrations/versions/660df34b13b5_organization_billing_currency.py diff --git a/migrations/versions/6d2b289e6c92_add_datasource_name_column_to_.py b/backend/migrations/versions/6d2b289e6c92_add_datasource_name_column_to_.py similarity index 100% rename from migrations/versions/6d2b289e6c92_add_datasource_name_column_to_.py rename to backend/migrations/versions/6d2b289e6c92_add_datasource_name_column_to_.py diff --git a/migrations/versions/70fa90617026_make_entitlement_owner_required.py b/backend/migrations/versions/70fa90617026_make_entitlement_owner_required.py similarity index 100% rename from migrations/versions/70fa90617026_make_entitlement_owner_required.py rename to backend/migrations/versions/70fa90617026_make_entitlement_owner_required.py diff --git a/migrations/versions/75971b70c7de_swith_to_daily_and_total_expenses_for_.py b/backend/migrations/versions/75971b70c7de_swith_to_daily_and_total_expenses_for_.py similarity index 100% rename from migrations/versions/75971b70c7de_swith_to_daily_and_total_expenses_for_.py rename to backend/migrations/versions/75971b70c7de_swith_to_daily_and_total_expenses_for_.py diff --git a/migrations/versions/7cd884694384_fix_chargesfiles_name_and_enum.py b/backend/migrations/versions/7cd884694384_fix_chargesfiles_name_and_enum.py similarity index 100% rename from migrations/versions/7cd884694384_fix_chargesfiles_name_and_enum.py rename to backend/migrations/versions/7cd884694384_fix_chargesfiles_name_and_enum.py diff --git a/migrations/versions/7fcf1b0ba90d_add_entitilement_ds_type_and_name.py b/backend/migrations/versions/7fcf1b0ba90d_add_entitilement_ds_type_and_name.py similarity index 100% rename from migrations/versions/7fcf1b0ba90d_add_entitilement_ds_type_and_name.py rename to backend/migrations/versions/7fcf1b0ba90d_add_entitilement_ds_type_and_name.py diff --git a/migrations/versions/80ece7cdb363_add_entitlement_stats_to_account.py b/backend/migrations/versions/80ece7cdb363_add_entitlement_stats_to_account.py similarity index 100% rename from migrations/versions/80ece7cdb363_add_entitlement_stats_to_account.py rename to backend/migrations/versions/80ece7cdb363_add_entitlement_stats_to_account.py diff --git a/migrations/versions/84791d4463e8_make_total_expenses_datasourceexpenses_.py b/backend/migrations/versions/84791d4463e8_make_total_expenses_datasourceexpenses_.py similarity index 100% rename from migrations/versions/84791d4463e8_make_total_expenses_datasourceexpenses_.py rename to backend/migrations/versions/84791d4463e8_make_total_expenses_datasourceexpenses_.py diff --git a/migrations/versions/8e6d8b9091ed_add_redeem_at_to_entitlement.py b/backend/migrations/versions/8e6d8b9091ed_add_redeem_at_to_entitlement.py similarity index 100% rename from migrations/versions/8e6d8b9091ed_add_redeem_at_to_entitlement.py rename to backend/migrations/versions/8e6d8b9091ed_add_redeem_at_to_entitlement.py diff --git a/migrations/versions/8fdb9f36e41c_add_external_id_to_actor.py b/backend/migrations/versions/8fdb9f36e41c_add_external_id_to_actor.py similarity index 100% rename from migrations/versions/8fdb9f36e41c_add_external_id_to_actor.py rename to backend/migrations/versions/8fdb9f36e41c_add_external_id_to_actor.py diff --git a/migrations/versions/9736e8ec11a3_system_change_unique_index_to_.py b/backend/migrations/versions/9736e8ec11a3_system_change_unique_index_to_.py similarity index 100% rename from migrations/versions/9736e8ec11a3_system_change_unique_index_to_.py rename to backend/migrations/versions/9736e8ec11a3_system_change_unique_index_to_.py diff --git a/migrations/versions/a7badd09ba07_organization_operations_external_id_.py b/backend/migrations/versions/a7badd09ba07_organization_operations_external_id_.py similarity index 100% rename from migrations/versions/a7badd09ba07_organization_operations_external_id_.py rename to backend/migrations/versions/a7badd09ba07_organization_operations_external_id_.py diff --git a/migrations/versions/b34e156283c4_merge_70fa90617026_and_deded05b7d54.py b/backend/migrations/versions/b34e156283c4_merge_70fa90617026_and_deded05b7d54.py similarity index 100% rename from migrations/versions/b34e156283c4_merge_70fa90617026_and_deded05b7d54.py rename to backend/migrations/versions/b34e156283c4_merge_70fa90617026_and_deded05b7d54.py diff --git a/migrations/versions/b55c60f80419_add_chargesfile.py b/backend/migrations/versions/b55c60f80419_add_chargesfile.py similarity index 100% rename from migrations/versions/b55c60f80419_add_chargesfile.py rename to backend/migrations/versions/b55c60f80419_add_chargesfile.py diff --git a/migrations/versions/c16f32ef558c_rename_external_ids.py b/backend/migrations/versions/c16f32ef558c_rename_external_ids.py similarity index 100% rename from migrations/versions/c16f32ef558c_rename_external_ids.py rename to backend/migrations/versions/c16f32ef558c_rename_external_ids.py diff --git a/migrations/versions/d144491ac1b6_create_exchange_rates_model.py b/backend/migrations/versions/d144491ac1b6_create_exchange_rates_model.py similarity index 100% rename from migrations/versions/d144491ac1b6_create_exchange_rates_model.py rename to backend/migrations/versions/d144491ac1b6_create_exchange_rates_model.py diff --git a/migrations/versions/d90dd09ae4ba_add_day_to_datasourceexpense.py b/backend/migrations/versions/d90dd09ae4ba_add_day_to_datasourceexpense.py similarity index 100% rename from migrations/versions/d90dd09ae4ba_add_day_to_datasourceexpense.py rename to backend/migrations/versions/d90dd09ae4ba_add_day_to_datasourceexpense.py diff --git a/migrations/versions/deded05b7d54_add_external_id_to_account.py b/backend/migrations/versions/deded05b7d54_add_external_id_to_account.py similarity index 100% rename from migrations/versions/deded05b7d54_add_external_id_to_account.py rename to backend/migrations/versions/deded05b7d54_add_external_id_to_account.py diff --git a/migrations/versions/e2964d52315a_drop_exchangerates_and_chargesfile.py b/backend/migrations/versions/e2964d52315a_drop_exchangerates_and_chargesfile.py similarity index 100% rename from migrations/versions/e2964d52315a_drop_exchangerates_and_chargesfile.py rename to backend/migrations/versions/e2964d52315a_drop_exchangerates_and_chargesfile.py diff --git a/migrations/versions/f4b7143100d4_increase_amount_fields.py b/backend/migrations/versions/f4b7143100d4_increase_amount_fields.py similarity index 100% rename from migrations/versions/f4b7143100d4_increase_amount_fields.py rename to backend/migrations/versions/f4b7143100d4_increase_amount_fields.py diff --git a/pyproject.toml b/backend/pyproject.toml similarity index 94% rename from pyproject.toml rename to backend/pyproject.toml index f15ed9d..33ada45 100644 --- a/pyproject.toml +++ b/backend/pyproject.toml @@ -2,11 +2,11 @@ name = "ffc-extension" version = "0.1.0" description = "SWO FinOps For Cloud Extension API" -readme = { file = "README.md", content-type = "text/markdown" } +readme = { file = "../README.md", content-type = "text/markdown" } authors = [ { name = "SoftwareOne AG" }, ] -license = { file = "LICENSE.txt" } +license = { file = "../LICENSE" } requires-python = ">=3.12,<4" dependencies = [ "alembic>=1.14.1,<2", @@ -88,17 +88,22 @@ package = true preview = true add-bounds = "major" -[tool.setuptools] -py-modules = ["app"] +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["app"] [tool.ruff] line-length = 100 target-version = "py312" output-format = "full" extend-exclude = [ - "migrations/versions/", + "migrations", + "migrations/versions", ] -cache-dir = ".cache/ruff" +cache-dir = "../.cache/ruff" [tool.ruff.lint] preview = true # enable linting rules in preview (e.g. RUF029 as of 2025-02-20) diff --git a/tests/__init__.py b/backend/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to backend/tests/__init__.py diff --git a/tests/api/__init__.py b/backend/tests/api/__init__.py similarity index 100% rename from tests/api/__init__.py rename to backend/tests/api/__init__.py diff --git a/tests/api/test_accounts_api.py b/backend/tests/api/test_accounts_api.py similarity index 100% rename from tests/api/test_accounts_api.py rename to backend/tests/api/test_accounts_api.py index ae16784..c660da2 100644 --- a/tests/api/test_accounts_api.py +++ b/backend/tests/api/test_accounts_api.py @@ -2,12 +2,6 @@ from uuid import uuid4 import pytest -from fastapi import HTTPException, status -from httpx import AsyncClient -from pytest_mock import MockerFixture -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession - from app.db.handlers import NotFoundError from app.db.models import Account, AccountUser, System, User from app.dependencies.db import AccountRepository @@ -18,6 +12,12 @@ validate_required_conditions_before_update, ) from app.schemas.accounts import AccountCreate +from fastapi import HTTPException, status +from httpx import AsyncClient +from pytest_mock import MockerFixture +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + from tests.types import ModelFactory diff --git a/tests/api/test_additional_admin_api.py b/backend/tests/api/test_additional_admin_api.py similarity index 100% rename from tests/api/test_additional_admin_api.py rename to backend/tests/api/test_additional_admin_api.py index 965607d..b31405f 100644 --- a/tests/api/test_additional_admin_api.py +++ b/backend/tests/api/test_additional_admin_api.py @@ -1,12 +1,12 @@ import logging from _pytest.logging import LogCaptureFixture -from httpx import AsyncClient -from pytest_httpx import HTTPXMock - from app import Settings from app.db.models import Organization from app.enums import OrganizationStatus +from httpx import AsyncClient +from pytest_httpx import HTTPXMock + from tests.types import ModelFactory FAKE_USER_ID = "1bf6f063-d90b-4d45-8e7f-62fefa9f5471" diff --git a/tests/api/test_datasources_api.py b/backend/tests/api/test_datasources_api.py similarity index 100% rename from tests/api/test_datasources_api.py rename to backend/tests/api/test_datasources_api.py index a9bbf70..abeef56 100644 --- a/tests/api/test_datasources_api.py +++ b/backend/tests/api/test_datasources_api.py @@ -2,12 +2,12 @@ from typing import Any import pytest -from httpx import AsyncClient -from pytest_httpx import HTTPXMock - from app.conf import Settings from app.db.models import Organization from app.enums import DatasourceType +from httpx import AsyncClient +from pytest_httpx import HTTPXMock + from tests.types import ModelFactory # =========================== diff --git a/tests/api/test_employees_api.py b/backend/tests/api/test_employees_api.py similarity index 100% rename from tests/api/test_employees_api.py rename to backend/tests/api/test_employees_api.py index 80660a6..8fbf22a 100644 --- a/tests/api/test_employees_api.py +++ b/backend/tests/api/test_employees_api.py @@ -1,11 +1,11 @@ import uuid +from app.conf import Settings +from app.db.models import Organization from httpx import AsyncClient from pytest_httpx import HTTPXMock from pytest_mock import MockerFixture -from app.conf import Settings -from app.db.models import Organization from tests.types import ModelFactory diff --git a/tests/api/test_entitlements_api.py b/backend/tests/api/test_entitlements_api.py similarity index 100% rename from tests/api/test_entitlements_api.py rename to backend/tests/api/test_entitlements_api.py index 086ce87..2f04a2f 100644 --- a/tests/api/test_entitlements_api.py +++ b/backend/tests/api/test_entitlements_api.py @@ -1,14 +1,14 @@ from datetime import UTC, datetime import pytest +from app.conf import Settings +from app.db.models import Account, Entitlement, System +from app.enums import AccountStatus, DatasourceType, EntitlementStatus, OrganizationStatus from httpx import AsyncClient from pytest_httpx import HTTPXMock from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from app.conf import Settings -from app.db.models import Account, Entitlement, System -from app.enums import AccountStatus, DatasourceType, EntitlementStatus, OrganizationStatus from tests.types import ModelFactory # ==================== diff --git a/tests/api/test_expenses_api.py b/backend/tests/api/test_expenses_api.py similarity index 100% rename from tests/api/test_expenses_api.py rename to backend/tests/api/test_expenses_api.py index 83cee95..052e479 100644 --- a/tests/api/test_expenses_api.py +++ b/backend/tests/api/test_expenses_api.py @@ -2,12 +2,12 @@ from decimal import Decimal import pytest +from app.db.models import DatasourceExpense, Organization +from app.enums import DatasourceType, OrganizationStatus from faker import Faker from httpx import AsyncClient from sqlalchemy.ext.asyncio import AsyncSession -from app.db.models import DatasourceExpense, Organization -from app.enums import DatasourceType, OrganizationStatus from tests.types import ModelFactory diff --git a/tests/api/test_organizations_api.py b/backend/tests/api/test_organizations_api.py similarity index 100% rename from tests/api/test_organizations_api.py rename to backend/tests/api/test_organizations_api.py index 05b772a..d6c5e37 100644 --- a/tests/api/test_organizations_api.py +++ b/backend/tests/api/test_organizations_api.py @@ -1,13 +1,13 @@ import pytest +from app.conf import Settings +from app.db.models import Organization, System +from app.enums import OrganizationStatus from httpx import AsyncClient from pytest_httpx import HTTPXMock from pytest_mock import MockerFixture from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from app.conf import Settings -from app.db.models import Organization, System -from app.enums import OrganizationStatus from tests.types import ModelFactory # ================= diff --git a/tests/commands/__init__.py b/backend/tests/commands/__init__.py similarity index 100% rename from tests/commands/__init__.py rename to backend/tests/commands/__init__.py diff --git a/tests/commands/conftest.py b/backend/tests/commands/conftest.py similarity index 99% rename from tests/commands/conftest.py rename to backend/tests/commands/conftest.py index e8302b1..47b4542 100644 --- a/tests/commands/conftest.py +++ b/backend/tests/commands/conftest.py @@ -1,7 +1,6 @@ import pytest -from pytest_mock import MockerFixture - from app.conf import Settings +from pytest_mock import MockerFixture @pytest.fixture(autouse=True) diff --git a/tests/commands/test_calculate_accounts_stats.py b/backend/tests/commands/test_calculate_accounts_stats.py similarity index 99% rename from tests/commands/test_calculate_accounts_stats.py rename to backend/tests/commands/test_calculate_accounts_stats.py index 59aa174..de1a8f8 100644 --- a/tests/commands/test_calculate_accounts_stats.py +++ b/backend/tests/commands/test_calculate_accounts_stats.py @@ -1,9 +1,8 @@ import pytest -from sqlalchemy.ext.asyncio import AsyncSession - from app.commands.calculate_accounts_stats import calculate_accounts_stats from app.conf import Settings from app.enums import AccountStatus, EntitlementStatus +from sqlalchemy.ext.asyncio import AsyncSession @pytest.mark.parametrize( diff --git a/tests/commands/test_cleanup_obsolete_datasource_expenses.py b/backend/tests/commands/test_cleanup_obsolete_datasource_expenses.py similarity index 100% rename from tests/commands/test_cleanup_obsolete_datasource_expenses.py rename to backend/tests/commands/test_cleanup_obsolete_datasource_expenses.py index e109b17..7564010 100644 --- a/tests/commands/test_cleanup_obsolete_datasource_expenses.py +++ b/backend/tests/commands/test_cleanup_obsolete_datasource_expenses.py @@ -3,15 +3,15 @@ import pytest import time_machine +from app.cli import app +from app.commands import cleanup_obsolete_datasource_expenses +from app.conf import Settings +from app.db.models import DatasourceExpense, Organization from pytest_mock import MockerFixture from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from typer.testing import CliRunner -from app.cli import app -from app.commands import cleanup_obsolete_datasource_expenses -from app.conf import Settings -from app.db.models import DatasourceExpense, Organization from tests.types import ModelFactory diff --git a/tests/commands/test_create_admin_account.py b/backend/tests/commands/test_create_admin_account.py similarity index 99% rename from tests/commands/test_create_admin_account.py rename to backend/tests/commands/test_create_admin_account.py index b044aad..6a98616 100644 --- a/tests/commands/test_create_admin_account.py +++ b/backend/tests/commands/test_create_admin_account.py @@ -1,14 +1,13 @@ import pytest -from pytest_mock import MockerFixture -from sqlalchemy.ext.asyncio import AsyncSession -from typer.testing import CliRunner - from app.cli import app from app.commands.create_admin_account import create_admin_account from app.conf import Settings from app.db.handlers import AccountHandler from app.db.models import Account from app.enums import AccountStatus, AccountType +from pytest_mock import MockerFixture +from sqlalchemy.ext.asyncio import AsyncSession +from typer.testing import CliRunner async def test_create_admin_account( diff --git a/tests/commands/test_fetch_datasource_expenses.py b/backend/tests/commands/test_fetch_datasource_expenses.py similarity index 100% rename from tests/commands/test_fetch_datasource_expenses.py rename to backend/tests/commands/test_fetch_datasource_expenses.py index 81de9c4..65cd035 100644 --- a/tests/commands/test_fetch_datasource_expenses.py +++ b/backend/tests/commands/test_fetch_datasource_expenses.py @@ -5,18 +5,18 @@ import pytest import time_machine -from fastapi import status -from pytest_httpx import HTTPXMock -from pytest_mock import MockerFixture -from sqlalchemy.ext.asyncio import AsyncSession -from typer.testing import CliRunner - from app.cli import app from app.commands import fetch_datasource_expenses from app.conf import Settings from app.db.handlers import DatasourceExpenseHandler from app.db.models import DatasourceExpense, Organization from app.enums import DatasourceType, OrganizationStatus +from fastapi import status +from pytest_httpx import HTTPXMock +from pytest_mock import MockerFixture +from sqlalchemy.ext.asyncio import AsyncSession +from typer.testing import CliRunner + from tests.fixtures.mock_api_clients import MockOptscaleClient from tests.types import ModelFactory diff --git a/tests/commands/test_openapi.py b/backend/tests/commands/test_openapi.py similarity index 99% rename from tests/commands/test_openapi.py rename to backend/tests/commands/test_openapi.py index 55179c7..7b4150c 100644 --- a/tests/commands/test_openapi.py +++ b/backend/tests/commands/test_openapi.py @@ -3,11 +3,10 @@ from pathlib import Path import yaml +from app.cli import app from pytest_mock import MockerFixture from typer.testing import CliRunner -from app.cli import app - def test_openapi(mocker: MockerFixture): spec = {"test": "openapi"} diff --git a/tests/commands/test_redeem_entitlements.py b/backend/tests/commands/test_redeem_entitlements.py similarity index 99% rename from tests/commands/test_redeem_entitlements.py rename to backend/tests/commands/test_redeem_entitlements.py index 518c5d4..7c88c42 100644 --- a/tests/commands/test_redeem_entitlements.py +++ b/backend/tests/commands/test_redeem_entitlements.py @@ -2,18 +2,17 @@ import pytest import time_machine -from httpx import HTTPStatusError, ReadTimeout -from pytest_httpx import HTTPXMock -from pytest_mock import MockerFixture -from sqlalchemy.ext.asyncio import AsyncSession -from typer.testing import CliRunner - from app.cli import app from app.commands.redeem_entitlements import fetch_datasources_for_organization, redeem_entitlements from app.conf import Settings from app.db.models import Entitlement, Organization from app.enums import DatasourceType, EntitlementStatus from app.notifications import ColumnHeader +from httpx import HTTPStatusError, ReadTimeout +from pytest_httpx import HTTPXMock +from pytest_mock import MockerFixture +from sqlalchemy.ext.asyncio import AsyncSession +from typer.testing import CliRunner @time_machine.travel("2025-03-07T10:00:00Z", tick=False) diff --git a/tests/commands/test_serve.py b/backend/tests/commands/test_serve.py similarity index 99% rename from tests/commands/test_serve.py rename to backend/tests/commands/test_serve.py index ba62737..c4e4caf 100644 --- a/tests/commands/test_serve.py +++ b/backend/tests/commands/test_serve.py @@ -1,8 +1,7 @@ +from app.cli import app from pytest_mock import MockerFixture from typer.testing import CliRunner -from app.cli import app - def test_serve(mocker: MockerFixture): mocked_settings = mocker.MagicMock() diff --git a/tests/commands/test_shell.py b/backend/tests/commands/test_shell.py similarity index 99% rename from tests/commands/test_shell.py rename to backend/tests/commands/test_shell.py index 29f5abc..31d2775 100644 --- a/tests/commands/test_shell.py +++ b/backend/tests/commands/test_shell.py @@ -1,8 +1,7 @@ +from app.cli import app from pytest_mock import MockerFixture from typer.testing import CliRunner -from app.cli import app - def test_shell(mocker: MockerFixture): mocked_ishell = mocker.patch("app.commands.shell.InteractiveShellEmbed") diff --git a/tests/conftest.py b/backend/tests/conftest.py similarity index 99% rename from tests/conftest.py rename to backend/tests/conftest.py index 99d15dc..728bb0b 100644 --- a/tests/conftest.py +++ b/backend/tests/conftest.py @@ -11,16 +11,6 @@ import jwt import pytest import responses -from asgi_lifespan import LifespanManager -from faker import Faker -from fastapi import FastAPI -from httpx import ASGITransport, AsyncClient -from pytest_asyncio import is_async_test -from sqlalchemy.ext.asyncio import ( - AsyncEngine, - AsyncSession, -) - from app.api_clients.base import BaseAPIClient from app.billing.dataclasses import ProcessResultInfo from app.billing.enum import ProcessResult @@ -49,6 +39,16 @@ SystemStatus, UserStatus, ) +from asgi_lifespan import LifespanManager +from faker import Faker +from fastapi import FastAPI +from httpx import ASGITransport, AsyncClient +from pytest_asyncio import is_async_test +from sqlalchemy.ext.asyncio import ( + AsyncEngine, + AsyncSession, +) + from tests.db.models import ModelForTests, ParentModelForTests # noqa: F401 from tests.types import ModelFactory @@ -2395,7 +2395,6 @@ async def _gen(): @pytest.fixture() def patch_get_by_billing_currency(mocker, org_mock_generator): - def _factory(*_args, **_kwargs): return org_mock_generator() diff --git a/tests/db/__init__.py b/backend/tests/db/__init__.py similarity index 100% rename from tests/db/__init__.py rename to backend/tests/db/__init__.py diff --git a/tests/db/models.py b/backend/tests/db/models.py similarity index 99% rename from tests/db/models.py rename to backend/tests/db/models.py index 897e96c..c9bda51 100644 --- a/tests/db/models.py +++ b/backend/tests/db/models.py @@ -1,10 +1,9 @@ import enum -from sqlalchemy import Enum, ForeignKey, String -from sqlalchemy.orm import Mapped, mapped_column, relationship - from app.db.human_readable_pk import HumanReadablePKMixin from app.db.models import AuditableMixin, Base +from sqlalchemy import Enum, ForeignKey, String +from sqlalchemy.orm import Mapped, mapped_column, relationship class ModelForTests(Base, HumanReadablePKMixin): diff --git a/tests/db/test_handlers.py b/backend/tests/db/test_handlers.py similarity index 100% rename from tests/db/test_handlers.py rename to backend/tests/db/test_handlers.py index 6549248..ecb4f25 100644 --- a/tests/db/test_handlers.py +++ b/backend/tests/db/test_handlers.py @@ -1,8 +1,4 @@ import pytest -from pytest_mock import MockerFixture -from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.orm import joinedload - from app.auth.context import AuthenticationContext from app.db.handlers import ( AccountUserHandler, @@ -13,6 +9,10 @@ ) from app.db.models import Account, AccountUser, Base, User from app.enums import AccountStatus, AccountUserStatus, UserStatus +from pytest_mock import MockerFixture +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import joinedload + from tests.db.models import ( DeletableAuditModelForTests, DeletableModelForTests, diff --git a/tests/db/test_models.py b/backend/tests/db/test_models.py similarity index 99% rename from tests/db/test_models.py rename to backend/tests/db/test_models.py index 2892aa6..bbafae2 100644 --- a/tests/db/test_models.py +++ b/backend/tests/db/test_models.py @@ -1,15 +1,14 @@ from datetime import UTC, datetime import pytest +from app.db.human_readable_pk import HumanReadablePKMixin +from app.db.models import Account, Actor, Entitlement, Organization, System +from app.enums import ActorType, EntitlementStatus from pytest_mock import MockerFixture from sqlalchemy import select from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession -from app.db.human_readable_pk import HumanReadablePKMixin -from app.db.models import Account, Actor, Entitlement, Organization, System -from app.enums import ActorType, EntitlementStatus - async def test_actor_inheritance(db_session: AsyncSession): # Create a system which inherits from Actor diff --git a/tests/fixtures/__init__.py b/backend/tests/fixtures/__init__.py similarity index 100% rename from tests/fixtures/__init__.py rename to backend/tests/fixtures/__init__.py diff --git a/tests/fixtures/mock_api_clients.py b/backend/tests/fixtures/mock_api_clients.py similarity index 99% rename from tests/fixtures/mock_api_clients.py rename to backend/tests/fixtures/mock_api_clients.py index 25aa1e8..fc72cd4 100644 --- a/tests/fixtures/mock_api_clients.py +++ b/backend/tests/fixtures/mock_api_clients.py @@ -4,14 +4,13 @@ import httpx import pytest -from fastapi import status -from pydantic.v1.utils import deep_update -from pytest_httpx import HTTPXMock - from app.api_clients.base import BaseAPIClient from app.api_clients.optscale import OptscaleClient from app.conf import Settings from app.db.models import Organization +from fastapi import status +from pydantic.v1.utils import deep_update +from pytest_httpx import HTTPXMock C = TypeVar("C", bound=BaseAPIClient) diff --git a/tests/test_auth.py b/backend/tests/test_auth.py similarity index 100% rename from tests/test_auth.py rename to backend/tests/test_auth.py diff --git a/tests/test_exchange_rates_client.py b/backend/tests/test_exchange_rates_client.py similarity index 99% rename from tests/test_exchange_rates_client.py rename to backend/tests/test_exchange_rates_client.py index 2b80f23..94f9210 100644 --- a/tests/test_exchange_rates_client.py +++ b/backend/tests/test_exchange_rates_client.py @@ -2,7 +2,6 @@ import httpx import pytest - from app.api_clients.exchage_rates import ExchangeRatesClient from app.billing.exceptions import ExchangeRatesClientError diff --git a/tests/test_logging.py b/backend/tests/test_logging.py similarity index 99% rename from tests/test_logging.py rename to backend/tests/test_logging.py index 63ef360..960ea80 100644 --- a/tests/test_logging.py +++ b/backend/tests/test_logging.py @@ -1,6 +1,5 @@ import pytest import pytest_mock - from app.logging import get_logging_config, setup_logging diff --git a/tests/test_notifications.py b/backend/tests/test_notifications.py similarity index 99% rename from tests/test_notifications.py rename to backend/tests/test_notifications.py index 51d37e8..6d55369 100644 --- a/tests/test_notifications.py +++ b/backend/tests/test_notifications.py @@ -1,8 +1,5 @@ import pytest from adaptive_cards import card_types as ct -from pytest_httpx import HTTPXMock -from pytest_mock import MockerFixture - from app.notifications import ( NotificationDetails, send_error, @@ -11,6 +8,8 @@ send_notification, send_warning, ) +from pytest_httpx import HTTPXMock +from pytest_mock import MockerFixture @pytest.mark.parametrize( diff --git a/tests/test_openapi.py b/backend/tests/test_openapi.py similarity index 99% rename from tests/test_openapi.py rename to backend/tests/test_openapi.py index cae8464..bac8e37 100644 --- a/tests/test_openapi.py +++ b/backend/tests/test_openapi.py @@ -1,7 +1,6 @@ -from fastapi import FastAPI - from app.conf import Settings from app.openapi import generate_openapi_spec +from fastapi import FastAPI def test_gen_openapi(fastapi_app: FastAPI, test_settings: Settings): diff --git a/tests/test_process_billing.py b/backend/tests/test_process_billing.py similarity index 99% rename from tests/test_process_billing.py rename to backend/tests/test_process_billing.py index b265df2..307e32d 100644 --- a/tests/test_process_billing.py +++ b/backend/tests/test_process_billing.py @@ -9,12 +9,11 @@ import httpx import pytest import typer -from freezegun import freeze_time - from app.billing.dataclasses import CurrencyConversionInfo, ProcessResultInfo, Refund from app.billing.enum import ProcessResult from app.billing.exceptions import ExchangeRatesClientError, JournalStatusError, JournalSubmitError from app.billing.notification_helper import check_results +from freezegun import freeze_time # - test evaluate_journal_status() diff --git a/tests/test_schemas.py b/backend/tests/test_schemas.py similarity index 99% rename from tests/test_schemas.py rename to backend/tests/test_schemas.py index a18329e..a479b88 100644 --- a/tests/test_schemas.py +++ b/backend/tests/test_schemas.py @@ -1,8 +1,6 @@ from datetime import UTC, datetime import pytest -from pydantic import ValidationError - from app.db.models import Account, Actor, Entitlement, Organization, System from app.enums import AccountType, ActorType, EntitlementStatus, OrganizationStatus, SystemStatus from app.schemas.core import ActorRead, convert_model_to_schema, convert_schema_to_model @@ -14,6 +12,7 @@ OrganizationUpdate, ) from app.schemas.systems import SystemCreate, SystemRead +from pydantic import ValidationError def test_actor_read_convert_model_to_schema(): diff --git a/tests/test_telemetry.py b/backend/tests/test_telemetry.py similarity index 99% rename from tests/test_telemetry.py rename to backend/tests/test_telemetry.py index f296c80..49122ee 100644 --- a/tests/test_telemetry.py +++ b/backend/tests/test_telemetry.py @@ -1,10 +1,9 @@ -from pytest_mock import MockerFixture - from app.telemetry import ( setup_fastapi_instrumentor, setup_sqlalchemy_instrumentor, setup_telemetry, ) +from pytest_mock import MockerFixture def test_setup_telemetry(mocker: MockerFixture): diff --git a/tests/test_utils.py b/backend/tests/test_utils.py similarity index 99% rename from tests/test_utils.py rename to backend/tests/test_utils.py index d1c4b14..ea239ce 100644 --- a/tests/test_utils.py +++ b/backend/tests/test_utils.py @@ -1,7 +1,6 @@ -from pytest_mock import MockerFixture - from app.conf import Settings from app.utils import send_email +from pytest_mock import MockerFixture def test_send_email_success(test_settings: Settings, mocker: MockerFixture): diff --git a/tests/types.py b/backend/tests/types.py similarity index 100% rename from tests/types.py rename to backend/tests/types.py diff --git a/uv.lock b/backend/uv.lock similarity index 94% rename from uv.lock rename to backend/uv.lock index 8a135e9..46b112c 100644 --- a/uv.lock +++ b/backend/uv.lock @@ -348,11 +348,11 @@ wheels = [ [[package]] name = "certifi" -version = "2026.2.25" +version = "2026.4.22" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } +sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, + { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, ] [[package]] @@ -527,14 +527,14 @@ wheels = [ [[package]] name = "click" -version = "8.3.2" +version = "8.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5", size = 302856, upload-time = "2026-04-03T19:14:45.118Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/63/f9e1ea081ce35720d8b92acde70daaedace594dc93b693c869e0d5910718/click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2", size = 328061, upload-time = "2026-04-22T15:11:27.506Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/20/71885d8b97d4f3dde17b1fdb92dbd4908b00541c5a3379787137285f602e/click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d", size = 108379, upload-time = "2026-04-03T19:14:43.505Z" }, + { url = "https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613", size = 110502, upload-time = "2026-04-22T15:11:25.044Z" }, ] [[package]] @@ -804,7 +804,7 @@ standard = [ [[package]] name = "fastapi-cloud-cli" -version = "0.16.1" +version = "0.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastar" }, @@ -816,9 +816,9 @@ dependencies = [ { name = "typer" }, { name = "uvicorn", extra = ["standard"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/70/ca14fae57a221610d3e2e3dfad2b6e97ee31fcafaa36f90a2158d57e9a73/fastapi_cloud_cli-0.16.1.tar.gz", hash = "sha256:33b552c4ad46cd33823ef53f93b8b7813db2306c80c1cbcfa4d72067c99b26ab", size = 46193, upload-time = "2026-04-08T09:12:54.151Z" } +sdist = { url = "https://files.pythonhosted.org/packages/67/79/66567c39c5fab6dbebf9e40b3a3fcb0e2ec359517c87a67434c76b06e60b/fastapi_cloud_cli-0.17.0.tar.gz", hash = "sha256:2b6c241b63427023bd1e23b3251f23234aba4b05428b245a050e92db1389823c", size = 47276, upload-time = "2026-04-15T13:17:56.402Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/8b/f8c9eb116d2e89de5e0875c5fce90f23143410f41fe27725be04bdcec328/fastapi_cloud_cli-0.16.1-py3-none-any.whl", hash = "sha256:8b43bd8c7dd3710393d3be4c248c6a00807202b488a543716562529a8316cbee", size = 33212, upload-time = "2026-04-08T09:12:52.949Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/fa442466bacadffec3d6611509d6ea391b6ca01b6ee0d4af835bfdea3483/fastapi_cloud_cli-0.17.0-py3-none-any.whl", hash = "sha256:b496e6998f037f572ab06a233ce257828b4c701488ce500b5c9d725e970a7cb1", size = 33936, upload-time = "2026-04-15T13:17:55.112Z" }, ] [[package]] @@ -1058,11 +1058,11 @@ dev = [ [[package]] name = "filelock" -version = "3.25.2" +version = "3.29.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/b8/00651a0f559862f3bb7d6f7477b192afe3f583cc5e26403b44e59a55ab34/filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", size = 40480, upload-time = "2026-03-11T20:45:38.487Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" }, + { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, ] [[package]] @@ -1323,20 +1323,20 @@ wheels = [ [[package]] name = "identify" -version = "2.6.18" +version = "2.6.19" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/46/c4/7fb4db12296cdb11893d61c92048fe617ee853f8523b9b296ac03b43757e/identify-2.6.18.tar.gz", hash = "sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd", size = 99580, upload-time = "2026-03-15T18:39:50.319Z" } +sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl", hash = "sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737", size = 99394, upload-time = "2026-03-15T18:39:48.915Z" }, + { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, ] [[package]] name = "idna" -version = "3.11" +version = "3.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/cc/762dfb036166873f0059f3b7de4565e1b5bc3d6f28a414c13da27e442f99/idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242", size = 194210, upload-time = "2026-04-22T16:42:42.314Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" }, ] [[package]] @@ -1522,14 +1522,14 @@ wheels = [ [[package]] name = "mako" -version = "1.3.10" +version = "1.3.11" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9e/38/bd5b78a920a64d708fe6bc8e0a2c075e1389d53bef8413725c63ba041535/mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", size = 392474, upload-time = "2025-04-10T12:44:31.16Z" } +sdist = { url = "https://files.pythonhosted.org/packages/59/8a/805404d0c0b9f3d7a326475ca008db57aea9c5c9f2e1e39ed0faa335571c/mako-1.3.11.tar.gz", hash = "sha256:071eb4ab4c5010443152255d77db7faa6ce5916f35226eb02dc34479b6858069", size = 399811, upload-time = "2026-04-14T20:19:51.493Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59", size = 78509, upload-time = "2025-04-10T12:50:53.297Z" }, + { url = "https://files.pythonhosted.org/packages/68/a5/19d7aaa7e433713ffe881df33705925a196afb9532efc8475d26593921a6/mako-1.3.11-py3-none-any.whl", hash = "sha256:e372c6e333cf004aa736a15f425087ec977e1fcbd2966aae7f17c8dc1da27a77", size = 78503, upload-time = "2026-04-14T20:19:53.233Z" }, ] [[package]] @@ -2104,11 +2104,11 @@ sdist = { url = "https://files.pythonhosted.org/packages/40/56/265f7b6f90b61ab4a [[package]] name = "packaging" -version = "26.0" +version = "26.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } +sdist = { url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de", size = 215519, upload-time = "2026-04-14T21:12:49.362Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, + { url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" }, ] [[package]] @@ -2206,7 +2206,7 @@ wheels = [ [[package]] name = "pre-commit" -version = "4.5.1" +version = "4.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, @@ -2215,9 +2215,9 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/22/2de9408ac81acbb8a7d05d4cc064a152ccf33b3d480ebe0cd292153db239/pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9", size = 198525, upload-time = "2026-04-21T20:31:41.613Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, + { url = "https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b", size = 226472, upload-time = "2026-04-21T20:31:40.092Z" }, ] [[package]] @@ -2397,7 +2397,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.13.0" +version = "2.13.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -2405,9 +2405,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/84/6b/69fd5c7194b21ebde0f8637e2a4ddc766ada29d472bfa6a5ca533d79549a/pydantic-2.13.0.tar.gz", hash = "sha256:b89b575b6e670ebf6e7448c01b41b244f471edd276cd0b6fe02e7e7aca320070", size = 843468, upload-time = "2026-04-13T10:51:35.571Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/e4/40d09941a2cebcb20609b86a559817d5b9291c49dd6f8c87e5feffbe703a/pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d", size = 844068, upload-time = "2026-04-20T14:46:43.632Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/d7/c3a52c61f5b7be648e919005820fbac33028c6149994cd64453f49951c17/pydantic-2.13.0-py3-none-any.whl", hash = "sha256:ab0078b90da5f3e2fd2e71e3d9b457ddcb35d0350854fbda93b451e28d56baaf", size = 471872, upload-time = "2026-04-13T10:51:33.343Z" }, + { url = "https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927", size = 471981, upload-time = "2026-04-20T14:46:41.402Z" }, ] [package.optional-dependencies] @@ -2417,77 +2417,77 @@ email = [ [[package]] name = "pydantic-core" -version = "2.46.0" +version = "2.46.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6f/0a/9414cddf82eda3976b14048cc0fa8f5b5d1aecb0b22e1dcd2dbfe0e139b1/pydantic_core-2.46.0.tar.gz", hash = "sha256:82d2498c96be47b47e903e1378d1d0f770097ec56ea953322f39936a7cf34977", size = 471441, upload-time = "2026-04-13T09:06:33.813Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/d2/206c72ad47071559142a35f71efc29eb16448a4a5ae9487230ab8e4e292b/pydantic_core-2.46.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:66ccedb02c934622612448489824955838a221b3a35875458970521ef17b2f9c", size = 2117060, upload-time = "2026-04-13T09:04:47.443Z" }, - { url = "https://files.pythonhosted.org/packages/17/2c/7a53b33f91c8b77e696b1a6aa3bed609bf9374bdc0f8dcda681bc7d922b8/pydantic_core-2.46.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a44f27f4d2788ef9876ec47a43739b118c5904d74f418f53398f6ced3bbcacf2", size = 1951802, upload-time = "2026-04-13T09:05:34.591Z" }, - { url = "https://files.pythonhosted.org/packages/fc/20/90e548c1f6d38800ef11c915881525770ce270d8e5e887563ff046a08674/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26a1032bcce6ca4b4670eb3f7d8195bd0a8b8f255f1307823e217ca3cfa7c27", size = 1976621, upload-time = "2026-04-13T09:04:03.909Z" }, - { url = "https://files.pythonhosted.org/packages/20/3c/9c5810ca70b60c623488cdd80f7e9ee1a0812df81e97098b64788719860f/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b8d1412f725060527e56675904b17a2d421dddcf861eecf7c75b9dda47921a4", size = 2056721, upload-time = "2026-04-13T09:04:40.992Z" }, - { url = "https://files.pythonhosted.org/packages/1a/a3/d6e5f4cdec84278431c75540f90838c9d0a4dfe9402a8f3902073660ff28/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc3d1569edd859cabaa476cabce9eecd05049a7966af7b4a33b541bfd4ca1104", size = 2239634, upload-time = "2026-04-13T09:03:52.478Z" }, - { url = "https://files.pythonhosted.org/packages/46/42/ef58aacf330d8de6e309d62469aa1f80e945eaf665929b4037ac1bfcebc1/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:38108976f2d8afaa8f5067fd1390a8c9f5cc580175407cda636e76bc76e88054", size = 2315739, upload-time = "2026-04-13T09:05:04.971Z" }, - { url = "https://files.pythonhosted.org/packages/8b/86/c63b12fafa2d86a515bfd1840b39c23a49302f02b653161bf9c3a0566c50/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5a06d8ed01dad5575056b5187e5959b336793c6047920a3441ee5b03533836", size = 2098169, upload-time = "2026-04-13T09:07:27.151Z" }, - { url = "https://files.pythonhosted.org/packages/76/19/b5b33a2f6be4755b21a20434293c4364be255f4c1a108f125d101d4cc4ee/pydantic_core-2.46.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:04017ace142da9ce27cafd423a480872571b5c7e80382aec22f7d715ca8eb870", size = 2170830, upload-time = "2026-04-13T09:04:39.448Z" }, - { url = "https://files.pythonhosted.org/packages/99/ae/7559f99a29b7d440012ddb4da897359304988a881efaca912fd2f655652e/pydantic_core-2.46.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2629ad992ed1b1c012e6067f5ffafd3336fcb9b54569449fabb85621f1444ed3", size = 2203901, upload-time = "2026-04-13T09:04:01.048Z" }, - { url = "https://files.pythonhosted.org/packages/dd/0e/b0ef945a39aeb4ac58da316813e1106b7fbdfbf20ac141c1c27904355ac5/pydantic_core-2.46.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3068b1e7bd986aebc88f6859f8353e72072538dcf92a7fb9cf511a0f61c5e729", size = 2191789, upload-time = "2026-04-13T09:06:39.915Z" }, - { url = "https://files.pythonhosted.org/packages/90/f4/830484e07188c1236b013995818888ab93bab8fd88aa9689b1d8fd22220d/pydantic_core-2.46.0-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:1e366916ff69ff700aa9326601634e688581bc24c5b6b4f8738d809ec7d72611", size = 2344423, upload-time = "2026-04-13T09:05:12.252Z" }, - { url = "https://files.pythonhosted.org/packages/fd/ba/e455c18cbdc333177af754e740be4fe9d1de173d65bbe534daf88da02ac0/pydantic_core-2.46.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:485a23e8f4618a1b8e23ac744180acde283fffe617f96923d25507d5cade62ec", size = 2384037, upload-time = "2026-04-13T09:06:24.503Z" }, - { url = "https://files.pythonhosted.org/packages/78/1f/b35d20d73144a41e78de0ae398e60fdd8bed91667daa1a5a92ab958551ba/pydantic_core-2.46.0-cp312-cp312-win32.whl", hash = "sha256:520940e1b702fe3b33525d0351777f25e9924f1818ca7956447dabacf2d339fd", size = 1967068, upload-time = "2026-04-13T09:05:23.374Z" }, - { url = "https://files.pythonhosted.org/packages/d1/84/4b6252e9606e8295647b848233cc4137ee0a04ebba8f0f9fb2977655b38c/pydantic_core-2.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:90d2048e0339fa365e5a66aefe760ddd3b3d0a45501e088bc5bc7f4ed9ff9571", size = 2071008, upload-time = "2026-04-13T09:05:21.392Z" }, - { url = "https://files.pythonhosted.org/packages/39/95/d08eb508d4d5560ccbd226ee5971e5ef9b749aba9b413c0c4ed6e406d4f6/pydantic_core-2.46.0-cp312-cp312-win_arm64.whl", hash = "sha256:a70247649b7dffe36648e8f34be5ce8c5fa0a27ff07b071ea780c20a738c05ce", size = 2036634, upload-time = "2026-04-13T09:05:48.299Z" }, - { url = "https://files.pythonhosted.org/packages/df/05/ab3b0742bad1d51822f1af0c4232208408902bdcfc47601f3b812e09e6c2/pydantic_core-2.46.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:a05900c37264c070c683c650cbca8f83d7cbb549719e645fcd81a24592eac788", size = 2116814, upload-time = "2026-04-13T09:04:12.41Z" }, - { url = "https://files.pythonhosted.org/packages/98/08/30b43d9569d69094a0899a199711c43aa58fce6ce80f6a8f7693673eb995/pydantic_core-2.46.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de8e482fd4f1e3f36c50c6aac46d044462615d8f12cfafc6bebeaa0909eea22", size = 1951867, upload-time = "2026-04-13T09:04:02.364Z" }, - { url = "https://files.pythonhosted.org/packages/db/a0/bf9a1ba34537c2ed3872a48195291138fdec8fe26c4009776f00d63cf0c8/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c525ecf8a4cdf198327b65030a7d081867ad8e60acb01a7214fff95cf9832d47", size = 1977040, upload-time = "2026-04-13T09:06:16.088Z" }, - { url = "https://files.pythonhosted.org/packages/71/70/0ba03c20e1e118219fc18c5417b008b7e880f0e3fb38560ec4465984d471/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f14581aeb12e61542ce73b9bfef2bca5439d65d9ab3efe1a4d8e346b61838f9b", size = 2055284, upload-time = "2026-04-13T09:05:25.125Z" }, - { url = "https://files.pythonhosted.org/packages/58/cf/1e320acefbde7fb7158a9e5def55e0adf9a4634636098ce28dc6b978e0d3/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c108067f2f7e190d0dbd81247d789ec41f9ea50ccd9265a3a46710796ac60530", size = 2238896, upload-time = "2026-04-13T09:05:01.345Z" }, - { url = "https://files.pythonhosted.org/packages/df/f5/ea8ba209756abe9eba891bb0ef3772b4c59a894eb9ad86cd5bd0dd4e3e52/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ac10967e9a7bb1b96697374513f9a1a90a59e2fb41566b5e00ee45392beac59", size = 2314353, upload-time = "2026-04-13T09:06:07.942Z" }, - { url = "https://files.pythonhosted.org/packages/e8/f8/5885350203b72e96438eee7f94de0d8f0442f4627237ca8ef75de34db1cd/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7897078fe8a13b73623c0955dfb2b3d2c9acb7177aac25144758c9e5a5265aaa", size = 2098522, upload-time = "2026-04-13T09:04:23.239Z" }, - { url = "https://files.pythonhosted.org/packages/bf/88/5930b0e828e371db5a556dd3189565417ddc3d8316bb001058168aadcf5f/pydantic_core-2.46.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:e69ce405510a419a082a78faed65bb4249cfb51232293cc675645c12f7379bf7", size = 2168757, upload-time = "2026-04-13T09:07:12.46Z" }, - { url = "https://files.pythonhosted.org/packages/da/75/63d563d3035a0548e721c38b5b69fd5626fdd51da0f09ff4467503915b82/pydantic_core-2.46.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd28d13eea0d8cf351dc1fe274b5070cc8e1cca2644381dee5f99de629e77cf3", size = 2202518, upload-time = "2026-04-13T09:05:44.418Z" }, - { url = "https://files.pythonhosted.org/packages/a7/53/1958eacbfddc41aadf5ae86dd85041bf054b675f34a2fa76385935f96070/pydantic_core-2.46.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:ee1547a6b8243e73dd10f585555e5a263395e55ce6dea618a078570a1e889aef", size = 2190148, upload-time = "2026-04-13T09:06:56.151Z" }, - { url = "https://files.pythonhosted.org/packages/c7/17/098cc6d3595e4623186f2bc6604a6195eb182e126702a90517236391e9ce/pydantic_core-2.46.0-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:c3dc68dcf62db22a18ddfc3ad4960038f72b75908edc48ae014d7ac8b391d57a", size = 2342925, upload-time = "2026-04-13T09:04:17.286Z" }, - { url = "https://files.pythonhosted.org/packages/71/a7/abdb924620b1ac535c690b36ad5b8871f376104090f8842c08625cecf1d3/pydantic_core-2.46.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:004a2081c881abfcc6854a4623da6a09090a0d7c1398a6ae7133ca1256cee70b", size = 2383167, upload-time = "2026-04-13T09:04:52.643Z" }, - { url = "https://files.pythonhosted.org/packages/d7/c9/2ddd10f50e4b7350d2574629a0f53d8d4eb6573f9c19a6b43e6b1487a31d/pydantic_core-2.46.0-cp313-cp313-win32.whl", hash = "sha256:59d24ec8d5eaabad93097525a69d0f00f2667cb353eb6cda578b1cfff203ceef", size = 1965660, upload-time = "2026-04-13T09:06:05.877Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e7/1efc38ed6f2680c032bcefa0e3ebd496a8c77e92dfdb86b07d0f2fc632b1/pydantic_core-2.46.0-cp313-cp313-win_amd64.whl", hash = "sha256:71186dad5ac325c64d68fe0e654e15fd79802e7cc42bc6f0ff822d5ad8b1ab25", size = 2069563, upload-time = "2026-04-13T09:07:14.738Z" }, - { url = "https://files.pythonhosted.org/packages/c3/1e/a325b4989e742bf7e72ed35fa124bc611fd76539c9f8cd2a9a7854473533/pydantic_core-2.46.0-cp313-cp313-win_arm64.whl", hash = "sha256:8e4503f3213f723842c9a3b53955c88a9cfbd0b288cbd1c1ae933aebeec4a1b4", size = 2034966, upload-time = "2026-04-13T09:04:21.629Z" }, - { url = "https://files.pythonhosted.org/packages/36/3b/914891d384cdbf9a6f464eb13713baa22ea1e453d4da80fb7da522079370/pydantic_core-2.46.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:4fc801c290342350ffc82d77872054a934b2e24163727263362170c1db5416ca", size = 2113349, upload-time = "2026-04-13T09:04:59.407Z" }, - { url = "https://files.pythonhosted.org/packages/35/95/3a0c6f65e231709fb3463e32943c69d10285cb50203a2130a4732053a06d/pydantic_core-2.46.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0a36f2cc88170cc177930afcc633a8c15907ea68b59ac16bd180c2999d714940", size = 1949170, upload-time = "2026-04-13T09:06:09.935Z" }, - { url = "https://files.pythonhosted.org/packages/d1/63/d845c36a608469fe7bee226edeff0984c33dbfe7aecd755b0e7ab5a275c4/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a3912e0c568a1f99d4d6d3e41def40179d61424c0ca1c8c87c4877d7f6fd7fb", size = 1977914, upload-time = "2026-04-13T09:04:56.16Z" }, - { url = "https://files.pythonhosted.org/packages/08/6f/f2e7a7f85931fb31671f5378d1c7fc70606e4b36d59b1b48e1bd1ef5d916/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3534c3415ed1a19ab23096b628916a827f7858ec8db49ad5d7d1e44dc13c0d7b", size = 2050538, upload-time = "2026-04-13T09:05:06.789Z" }, - { url = "https://files.pythonhosted.org/packages/8c/97/f4aa7181dd9a16dd9059a99fc48fdab0c2aab68307283a5c04cf56de68c4/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21067396fc285609323a4db2f63a87570044abe0acddfcca8b135fc7948e3db7", size = 2236294, upload-time = "2026-04-13T09:07:03.2Z" }, - { url = "https://files.pythonhosted.org/packages/24/c1/6a5042fc32765c87101b500f394702890af04239c318b6002cfd627b710d/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2afd85b7be186e2fe7cdbb09a3d964bcc2042f65bbcc64ad800b3c7915032655", size = 2312954, upload-time = "2026-04-13T09:06:11.919Z" }, - { url = "https://files.pythonhosted.org/packages/cb/e4/566101a561492ce8454f0844ca29c3b675a6b3a7b3ff577db85ed05c8c50/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67e2c2e171b78db8154da602de72ffdc473c6ee51de8a9d80c0f1cd4051abfc7", size = 2102533, upload-time = "2026-04-13T09:06:58.664Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ac/adc11ee1646a5c4dd9abb09a00e7909e6dc25beddc0b1310ca734bb9b48e/pydantic_core-2.46.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c16ae1f3170267b1a37e16dba5c297bdf60c8b5657b147909ca8774ce7366644", size = 2169447, upload-time = "2026-04-13T09:04:11.143Z" }, - { url = "https://files.pythonhosted.org/packages/26/73/408e686b45b82d28ac19e8229e07282254dbee6a5d24c5c7cf3cf3716613/pydantic_core-2.46.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:133b69e1c1ba34d3702eed73f19f7f966928f9aa16663b55c2ebce0893cca42e", size = 2200672, upload-time = "2026-04-13T09:03:54.056Z" }, - { url = "https://files.pythonhosted.org/packages/0a/3b/807d5b035ec891b57b9079ce881f48263936c37bd0d154a056e7fd152afb/pydantic_core-2.46.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:15ed8e5bde505133d96b41702f31f06829c46b05488211a5b1c7877e11de5eb5", size = 2188293, upload-time = "2026-04-13T09:07:07.614Z" }, - { url = "https://files.pythonhosted.org/packages/f1/ed/719b307516285099d1196c52769fdbe676fd677da007b9c349ae70b7226d/pydantic_core-2.46.0-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:8cfc29a1c66a7f0fcb36262e92f353dd0b9c4061d558fceb022e698a801cb8ae", size = 2335023, upload-time = "2026-04-13T09:04:05.176Z" }, - { url = "https://files.pythonhosted.org/packages/8d/90/8718e4ae98c4e8a7325afdc079be82be1e131d7a47cb6c098844a9531ffe/pydantic_core-2.46.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e1155708540f13845bf68d5ac511a55c76cfe2e057ed12b4bf3adac1581fc5c2", size = 2377155, upload-time = "2026-04-13T09:06:18.081Z" }, - { url = "https://files.pythonhosted.org/packages/dd/dc/7172789283b963f81da2fc92b186e22de55687019079f71c4d570822502b/pydantic_core-2.46.0-cp314-cp314-win32.whl", hash = "sha256:de5635a48df6b2eef161d10ea1bc2626153197333662ba4cd700ee7ec1aba7f5", size = 1963078, upload-time = "2026-04-13T09:05:30.615Z" }, - { url = "https://files.pythonhosted.org/packages/e0/69/03a7ea4b6264def3a44eabf577528bcec2f49468c5698b2044dea54dc07e/pydantic_core-2.46.0-cp314-cp314-win_amd64.whl", hash = "sha256:f07a5af60c5e7cf53dd1ff734228bd72d0dc9938e64a75b5bb308ca350d9681e", size = 2068439, upload-time = "2026-04-13T09:04:57.729Z" }, - { url = "https://files.pythonhosted.org/packages/f5/eb/1c3afcfdee2ab6634b802ab0a0f1966df4c8b630028ec56a1cb0a710dc58/pydantic_core-2.46.0-cp314-cp314-win_arm64.whl", hash = "sha256:e7a77eca3c7d5108ff509db20aae6f80d47c7ed7516d8b96c387aacc42f3ce0f", size = 2026470, upload-time = "2026-04-13T09:05:08.654Z" }, - { url = "https://files.pythonhosted.org/packages/5c/30/1177dde61b200785c4739665e3aa03a9d4b2c25d2d0408b07d585e633965/pydantic_core-2.46.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5e7cdd4398bee1aaeafe049ac366b0f887451d9ae418fd8785219c13fea2f928", size = 2107447, upload-time = "2026-04-13T09:05:46.314Z" }, - { url = "https://files.pythonhosted.org/packages/b1/60/4e0f61f99bdabbbc309d364a2791e1ba31e778a4935bc43391a7bdec0744/pydantic_core-2.46.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5c2c92d82808e27cef3f7ab3ed63d657d0c755e0dbe5b8a58342e37bdf09bd2e", size = 1926927, upload-time = "2026-04-13T09:06:20.371Z" }, - { url = "https://files.pythonhosted.org/packages/1d/d0/67f89a8269152c1d6eaa81f04e75a507372ebd8ca7382855a065222caa80/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bab80af91cd7014b45d1089303b5f844a9d91d7da60eabf3d5f9694b32a6655", size = 1966613, upload-time = "2026-04-13T09:07:05.389Z" }, - { url = "https://files.pythonhosted.org/packages/cd/07/8dfdc3edc78f29a80fb31f366c50203ec904cff6a4c923599bf50ac0d0ff/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1e49ffdb714bc990f00b39d1ad1d683033875b5af15582f60c1f34ad3eeccfaa", size = 2032902, upload-time = "2026-04-13T09:06:42.47Z" }, - { url = "https://files.pythonhosted.org/packages/b0/2a/111c5e8fe24f99c46bcad7d3a82a8f6dbc738066e2c72c04c71f827d8c78/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca877240e8dbdeef3a66f751dc41e5a74893767d510c22a22fc5c0199844f0ce", size = 2244456, upload-time = "2026-04-13T09:05:36.484Z" }, - { url = "https://files.pythonhosted.org/packages/6b/7c/cfc5d11c15a63ece26e148572c77cfbb2c7f08d315a7b63ef0fe0711d753/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87e6843f89ecd2f596d7294e33196c61343186255b9880c4f1b725fde8b0e20d", size = 2294535, upload-time = "2026-04-13T09:06:01.689Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2c/f0d744e3dab7bd026a3f4670a97a295157cff923a2666d30a15a70a7e3d0/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e20bc5add1dd9bc3b9a3600d40632e679376569098345500799a6ad7c5d46c72", size = 2104621, upload-time = "2026-04-13T09:04:34.388Z" }, - { url = "https://files.pythonhosted.org/packages/a7/64/e7cc4698dc024264d214b51d5a47a2404221b12060dd537d76f831b2120a/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:ee6ff79a5f0289d64a9d6696a3ce1f98f925b803dd538335a118231e26d6d827", size = 2130718, upload-time = "2026-04-13T09:04:26.23Z" }, - { url = "https://files.pythonhosted.org/packages/0b/a8/224e655fec21f7d4441438ad2ecaccb33b5a3876ce7bb2098c74a49efc14/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:52d35cfb58c26323101c7065508d7bb69bb56338cda9ea47a7b32be581af055d", size = 2180738, upload-time = "2026-04-13T09:05:50.253Z" }, - { url = "https://files.pythonhosted.org/packages/32/7b/b3025618ed4c4e4cbaa9882731c19625db6669896b621760ea95bc1125ef/pydantic_core-2.46.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d14cc5a6f260fa78e124061eebc5769af6534fc837e9a62a47f09a2c341fa4ea", size = 2171222, upload-time = "2026-04-13T09:07:29.929Z" }, - { url = "https://files.pythonhosted.org/packages/7b/e3/68170aa1d891920af09c1f2f34df61dc5ff3a746400027155523e3400e89/pydantic_core-2.46.0-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:4f7ff859d663b6635f6307a10803d07f0d09487e16c3d36b1744af51dbf948b2", size = 2320040, upload-time = "2026-04-13T09:06:35.732Z" }, - { url = "https://files.pythonhosted.org/packages/67/1b/5e65807001b84972476300c1f49aea2b4971b7e9fffb5c2654877dadd274/pydantic_core-2.46.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:8ef749be6ed0d69dba31902aaa8255a9bb269ae50c93888c4df242d8bb7acd9e", size = 2377062, upload-time = "2026-04-13T09:07:39.945Z" }, - { url = "https://files.pythonhosted.org/packages/75/03/48caa9dd5f28f7662bd52bff454d9a451f6b7e5e4af95e289e5e170749c9/pydantic_core-2.46.0-cp314-cp314t-win32.whl", hash = "sha256:d93ca72870133f86360e4bb0c78cd4e6ba2a0f9f3738a6486909ffc031463b32", size = 1951028, upload-time = "2026-04-13T09:04:20.224Z" }, - { url = "https://files.pythonhosted.org/packages/87/ed/e97ff55fe28c0e6e3cba641d622b15e071370b70e5f07c496b07b65db7c9/pydantic_core-2.46.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6ebb2668afd657e2127cb40f2ceb627dd78e74e9dfde14d9bf6cdd532a29ff59", size = 2048519, upload-time = "2026-04-13T09:05:10.464Z" }, - { url = "https://files.pythonhosted.org/packages/b6/51/e0db8267a287994546925f252e329eeae4121b1e77e76353418da5a3adf0/pydantic_core-2.46.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4864f5bbb7993845baf9209bae1669a8a76769296a018cb569ebda9dcb4241f5", size = 2026791, upload-time = "2026-04-13T09:04:37.724Z" }, - { url = "https://files.pythonhosted.org/packages/74/0c/106ed5cc50393d90523f09adcc50d05e42e748eb107dc06aea971137f02d/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:bc0e2fefe384152d7da85b5c2fe8ce2bf24752f68a58e3f3ea42e28a29dfdeb2", size = 2104968, upload-time = "2026-04-13T09:06:26.967Z" }, - { url = "https://files.pythonhosted.org/packages/f5/71/b494cef3165e3413ee9bbbb5a9eedc9af0ea7b88d8638beef6c2061b110e/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:a2ab0e785548be1b4362a62c4004f9217598b7ee465f1f420fc2123e2a5b5b02", size = 1940442, upload-time = "2026-04-13T09:06:29.332Z" }, - { url = "https://files.pythonhosted.org/packages/7e/3e/a4d578c8216c443e26a1124f8c1e07c0654264ce5651143d3883d85ff140/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16d45aecb18b8cba1c68eeb17c2bb2d38627ceed04c5b30b882fc9134e01f187", size = 1999672, upload-time = "2026-04-13T09:04:42.798Z" }, - { url = "https://files.pythonhosted.org/packages/cd/c1/9114560468685525a21770138382fd0cb849aaf351ff2c7b97f760d121e0/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5078f6c377b002428e984259ac327ef8902aacae6c14b7de740dd4869a491501", size = 2154533, upload-time = "2026-04-13T09:04:50.868Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/2a/ef/f7abb56c49382a246fd2ce9c799691e3c3e7175ec74b14d99e798bcddb1a/pydantic_core-2.46.3.tar.gz", hash = "sha256:41c178f65b8c29807239d47e6050262eb6bf84eb695e41101e62e38df4a5bc2c", size = 471412, upload-time = "2026-04-20T14:40:56.672Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/cb/5b47425556ecc1f3fe18ed2a0083188aa46e1dd812b06e406475b3a5d536/pydantic_core-2.46.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b11b59b3eee90a80a36701ddb4576d9ae31f93f05cb9e277ceaa09e6bf074a67", size = 2101946, upload-time = "2026-04-20T14:40:52.581Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4f/2fb62c2267cae99b815bbf4a7b9283812c88ca3153ef29f7707200f1d4e5/pydantic_core-2.46.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af8653713055ea18a3abc1537fe2ebc42f5b0bbb768d1eb79fd74eb47c0ac089", size = 1951612, upload-time = "2026-04-20T14:42:42.996Z" }, + { url = "https://files.pythonhosted.org/packages/50/6e/b7348fd30d6556d132cddd5bd79f37f96f2601fe0608afac4f5fb01ec0b3/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75a519dab6d63c514f3a81053e5266c549679e4aa88f6ec57f2b7b854aceb1b0", size = 1977027, upload-time = "2026-04-20T14:42:02.001Z" }, + { url = "https://files.pythonhosted.org/packages/82/11/31d60ee2b45540d3fb0b29302a393dbc01cd771c473f5b5147bcd353e593/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6cd87cb1575b1ad05ba98894c5b5c96411ef678fa2f6ed2576607095b8d9789", size = 2063008, upload-time = "2026-04-20T14:44:17.952Z" }, + { url = "https://files.pythonhosted.org/packages/8a/db/3a9d1957181b59258f44a2300ab0f0be9d1e12d662a4f57bb31250455c52/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f80a55484b8d843c8ada81ebf70a682f3f00a3d40e378c06cf17ecb44d280d7d", size = 2233082, upload-time = "2026-04-20T14:40:57.934Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e1/3277c38792aeb5cfb18c2f0c5785a221d9ff4e149abbe1184d53d5f72273/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3861f1731b90c50a3266316b9044f5c9b405eecb8e299b0a7120596334e4fe9c", size = 2304615, upload-time = "2026-04-20T14:42:12.584Z" }, + { url = "https://files.pythonhosted.org/packages/5e/d5/e3d9717c9eba10855325650afd2a9cba8e607321697f18953af9d562da2f/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb528e295ed31570ac3dcc9bfdd6e0150bc11ce6168ac87a8082055cf1a67395", size = 2094380, upload-time = "2026-04-20T14:43:05.522Z" }, + { url = "https://files.pythonhosted.org/packages/a1/20/abac35dedcbfd66c6f0b03e4e3564511771d6c9b7ede10a362d03e110d9b/pydantic_core-2.46.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:367508faa4973b992b271ba1494acaab36eb7e8739d1e47be5035fb1ea225396", size = 2135429, upload-time = "2026-04-20T14:41:55.549Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a5/41bfd1df69afad71b5cf0535055bccc73022715ad362edbc124bc1e021d7/pydantic_core-2.46.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ad3c826fe523e4becf4fe39baa44286cff85ef137c729a2c5e269afbfd0905d", size = 2174582, upload-time = "2026-04-20T14:41:45.96Z" }, + { url = "https://files.pythonhosted.org/packages/79/65/38d86ea056b29b2b10734eb23329b7a7672ca604df4f2b6e9c02d4ee22fe/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ec638c5d194ef8af27db69f16c954a09797c0dc25015ad6123eb2c73a4d271ca", size = 2187533, upload-time = "2026-04-20T14:40:55.367Z" }, + { url = "https://files.pythonhosted.org/packages/b6/55/a1129141678a2026badc539ad1dee0a71d06f54c2f06a4bd68c030ac781b/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:28ed528c45446062ee66edb1d33df5d88828ae167de76e773a3c7f64bd14e976", size = 2332985, upload-time = "2026-04-20T14:44:13.05Z" }, + { url = "https://files.pythonhosted.org/packages/d7/60/cb26f4077719f709e54819f4e8e1d43f4091f94e285eb6bd21e1190a7b7c/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aed19d0c783886d5bd86d80ae5030006b45e28464218747dcf83dabfdd092c7b", size = 2373670, upload-time = "2026-04-20T14:41:53.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/7e/c3f21882bdf1d8d086876f81b5e296206c69c6082551d776895de7801fa0/pydantic_core-2.46.3-cp312-cp312-win32.whl", hash = "sha256:06d5d8820cbbdb4147578c1fe7ffcd5b83f34508cb9f9ab76e807be7db6ff0a4", size = 1966722, upload-time = "2026-04-20T14:44:30.588Z" }, + { url = "https://files.pythonhosted.org/packages/57/be/6b5e757b859013ebfbd7adba02f23b428f37c86dcbf78b5bb0b4ffd36e99/pydantic_core-2.46.3-cp312-cp312-win_amd64.whl", hash = "sha256:c3212fda0ee959c1dd04c60b601ec31097aaa893573a3a1abd0a47bcac2968c1", size = 2072970, upload-time = "2026-04-20T14:42:54.248Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f8/a989b21cc75e9a32d24192ef700eea606521221a89faa40c919ce884f2b1/pydantic_core-2.46.3-cp312-cp312-win_arm64.whl", hash = "sha256:f1f8338dd7a7f31761f1f1a3c47503a9a3b34eea3c8b01fa6ee96408affb5e72", size = 2035963, upload-time = "2026-04-20T14:44:20.4Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3c/9b5e8eb9821936d065439c3b0fb1490ffa64163bfe7e1595985a47896073/pydantic_core-2.46.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:12bc98de041458b80c86c56b24df1d23832f3e166cbaff011f25d187f5c62c37", size = 2102109, upload-time = "2026-04-20T14:41:24.219Z" }, + { url = "https://files.pythonhosted.org/packages/91/97/1c41d1f5a19f241d8069f1e249853bcce378cdb76eec8ab636d7bc426280/pydantic_core-2.46.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:85348b8f89d2c3508b65b16c3c33a4da22b8215138d8b996912bb1532868885f", size = 1951820, upload-time = "2026-04-20T14:42:14.236Z" }, + { url = "https://files.pythonhosted.org/packages/30/b4/d03a7ae14571bc2b6b3c7b122441154720619afe9a336fa3a95434df5e2f/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1105677a6df914b1fb71a81b96c8cce7726857e1717d86001f29be06a25ee6f8", size = 1977785, upload-time = "2026-04-20T14:42:31.648Z" }, + { url = "https://files.pythonhosted.org/packages/ae/0c/4086f808834b59e3c8f1aa26df8f4b6d998cdcf354a143d18ef41529d1fe/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87082cd65669a33adeba5470769e9704c7cf026cc30afb9cc77fd865578ebaad", size = 2062761, upload-time = "2026-04-20T14:40:37.093Z" }, + { url = "https://files.pythonhosted.org/packages/fa/71/a649be5a5064c2df0db06e0a512c2281134ed2fcc981f52a657936a7527c/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e5f66e12c4f5212d08522963380eaaeac5ebd795826cfd19b2dfb0c7a52b9c", size = 2232989, upload-time = "2026-04-20T14:42:59.254Z" }, + { url = "https://files.pythonhosted.org/packages/a2/84/7756e75763e810b3a710f4724441d1ecc5883b94aacb07ca71c5fb5cfb69/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6cdf19bf84128d5e7c37e8a73a0c5c10d51103a650ac585d42dd6ae233f2b7f", size = 2303975, upload-time = "2026-04-20T14:41:32.287Z" }, + { url = "https://files.pythonhosted.org/packages/6c/35/68a762e0c1e31f35fa0dac733cbd9f5b118042853698de9509c8e5bf128b/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031bb17f4885a43773c8c763089499f242aee2ea85cf17154168775dccdecf35", size = 2095325, upload-time = "2026-04-20T14:42:47.685Z" }, + { url = "https://files.pythonhosted.org/packages/77/bf/1bf8c9a8e91836c926eae5e3e51dce009bf495a60ca56060689d3df3f340/pydantic_core-2.46.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:bcf2a8b2982a6673693eae7348ef3d8cf3979c1d63b54fca7c397a635cc68687", size = 2133368, upload-time = "2026-04-20T14:41:22.766Z" }, + { url = "https://files.pythonhosted.org/packages/e5/50/87d818d6bab915984995157ceb2380f5aac4e563dddbed6b56f0ed057aba/pydantic_core-2.46.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28e8cf2f52d72ced402a137145923a762cbb5081e48b34312f7a0c8f55928ec3", size = 2173908, upload-time = "2026-04-20T14:42:52.044Z" }, + { url = "https://files.pythonhosted.org/packages/91/88/a311fb306d0bd6185db41fa14ae888fb81d0baf648a761ae760d30819d33/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:17eaface65d9fc5abb940003020309c1bf7a211f5f608d7870297c367e6f9022", size = 2186422, upload-time = "2026-04-20T14:43:29.55Z" }, + { url = "https://files.pythonhosted.org/packages/8f/79/28fd0d81508525ab2054fef7c77a638c8b5b0afcbbaeee493cf7c3fef7e1/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:93fd339f23408a07e98950a89644f92c54d8729719a40b30c0a30bb9ebc55d23", size = 2332709, upload-time = "2026-04-20T14:42:16.134Z" }, + { url = "https://files.pythonhosted.org/packages/b3/21/795bf5fe5c0f379308b8ef19c50dedab2e7711dbc8d0c2acf08f1c7daa05/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:23cbdb3aaa74dfe0837975dbf69b469753bbde8eacace524519ffdb6b6e89eb7", size = 2372428, upload-time = "2026-04-20T14:41:10.974Z" }, + { url = "https://files.pythonhosted.org/packages/45/b3/ed14c659cbe7605e3ef063077680a64680aec81eb1a04763a05190d49b7f/pydantic_core-2.46.3-cp313-cp313-win32.whl", hash = "sha256:610eda2e3838f401105e6326ca304f5da1e15393ae25dacae5c5c63f2c275b13", size = 1965601, upload-time = "2026-04-20T14:41:42.128Z" }, + { url = "https://files.pythonhosted.org/packages/ef/bb/adb70d9a762ddd002d723fbf1bd492244d37da41e3af7b74ad212609027e/pydantic_core-2.46.3-cp313-cp313-win_amd64.whl", hash = "sha256:68cc7866ed863db34351294187f9b729964c371ba33e31c26f478471c52e1ed0", size = 2071517, upload-time = "2026-04-20T14:43:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/52/eb/66faefabebfe68bd7788339c9c9127231e680b11906368c67ce112fdb47f/pydantic_core-2.46.3-cp313-cp313-win_arm64.whl", hash = "sha256:f64b5537ac62b231572879cd08ec05600308636a5d63bcbdb15063a466977bec", size = 2035802, upload-time = "2026-04-20T14:43:38.507Z" }, + { url = "https://files.pythonhosted.org/packages/7f/db/a7bcb4940183fda36022cd18ba8dd12f2dff40740ec7b58ce7457befa416/pydantic_core-2.46.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:afa3aa644f74e290cdede48a7b0bee37d1c35e71b05105f6b340d484af536d9b", size = 2097614, upload-time = "2026-04-20T14:44:38.374Z" }, + { url = "https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ced3310e51aa425f7f77da8bbbb5212616655bedbe82c70944320bc1dbe5e018", size = 1951896, upload-time = "2026-04-20T14:40:53.996Z" }, + { url = "https://files.pythonhosted.org/packages/87/92/37cf4049d1636996e4b888c05a501f40a43ff218983a551d57f9d5e14f0d/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e29908922ce9da1a30b4da490bd1d3d82c01dcfdf864d2a74aacee674d0bfa34", size = 1979314, upload-time = "2026-04-20T14:41:49.446Z" }, + { url = "https://files.pythonhosted.org/packages/d8/36/9ff4d676dfbdfb2d591cf43f3d90ded01e15b1404fd101180ed2d62a2fd3/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c9ff69140423eea8ed2d5477df3ba037f671f5e897d206d921bc9fdc39613e7", size = 2056133, upload-time = "2026-04-20T14:42:23.574Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f0/405b442a4d7ba855b06eec8b2bf9c617d43b8432d099dfdc7bf999293495/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b675ab0a0d5b1c8fdb81195dc5bcefea3f3c240871cdd7ff9a2de8aa50772eb2", size = 2228726, upload-time = "2026-04-20T14:44:22.816Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f8/65cd92dd5a0bd89ba277a98ecbfaf6fc36bbd3300973c7a4b826d6ab1391/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0087084960f209a9a4af50ecd1fb063d9ad3658c07bb81a7a53f452dacbfb2ba", size = 2301214, upload-time = "2026-04-20T14:44:48.792Z" }, + { url = "https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed42e6cc8e1b0e2b9b96e2276bad70ae625d10d6d524aed0c93de974ae029f9f", size = 2099927, upload-time = "2026-04-20T14:41:40.196Z" }, + { url = "https://files.pythonhosted.org/packages/6d/53/269caf30e0096e0a8a8f929d1982a27b3879872cca2d917d17c2f9fdf4fe/pydantic_core-2.46.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:f1771ce258afb3e4201e67d154edbbae712a76a6081079fe247c2f53c6322c22", size = 2128789, upload-time = "2026-04-20T14:41:15.868Z" }, + { url = "https://files.pythonhosted.org/packages/00/b0/1a6d9b6a587e118482910c244a1c5acf4d192604174132efd12bf0ac486f/pydantic_core-2.46.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7610b6a5242a6c736d8ad47fd5fff87fcfe8f833b281b1c409c3d6835d9227f", size = 2173815, upload-time = "2026-04-20T14:44:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/87/56/e7e00d4041a7e62b5a40815590114db3b535bf3ca0bf4dca9f16cef25246/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:ff5e7783bcc5476e1db448bf268f11cb257b1c276d3e89f00b5727be86dd0127", size = 2181608, upload-time = "2026-04-20T14:41:28.933Z" }, + { url = "https://files.pythonhosted.org/packages/e8/22/4bd23c3d41f7c185d60808a1de83c76cf5aeabf792f6c636a55c3b1ec7f9/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:9d2e32edcc143bc01e95300671915d9ca052d4f745aa0a49c48d4803f8a85f2c", size = 2326968, upload-time = "2026-04-20T14:42:03.962Z" }, + { url = "https://files.pythonhosted.org/packages/24/ac/66cd45129e3915e5ade3b292cb3bc7fd537f58f8f8dbdaba6170f7cabb74/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d83d1c6b87fa56b521479cff237e626a292f3b31b6345c15a99121b454c1", size = 2369842, upload-time = "2026-04-20T14:41:35.52Z" }, + { url = "https://files.pythonhosted.org/packages/a2/51/dd4248abb84113615473aa20d5545b7c4cd73c8644003b5259686f93996c/pydantic_core-2.46.3-cp314-cp314-win32.whl", hash = "sha256:07bc6d2a28c3adb4f7c6ae46aa4f2d2929af127f587ed44057af50bf1ce0f505", size = 1959661, upload-time = "2026-04-20T14:41:00.042Z" }, + { url = "https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl", hash = "sha256:8940562319bc621da30714617e6a7eaa6b98c84e8c685bcdc02d7ed5e7c7c44e", size = 2071686, upload-time = "2026-04-20T14:43:16.471Z" }, + { url = "https://files.pythonhosted.org/packages/8c/db/1cf77e5247047dfee34bc01fa9bca134854f528c8eb053e144298893d370/pydantic_core-2.46.3-cp314-cp314-win_arm64.whl", hash = "sha256:5dcbbcf4d22210ced8f837c96db941bdb078f419543472aca5d9a0bb7cddc7df", size = 2026907, upload-time = "2026-04-20T14:43:31.732Z" }, + { url = "https://files.pythonhosted.org/packages/57/c0/b3df9f6a543276eadba0a48487b082ca1f201745329d97dbfa287034a230/pydantic_core-2.46.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d0fe3dce1e836e418f912c1ad91c73357d03e556a4d286f441bf34fed2dbeecf", size = 2095047, upload-time = "2026-04-20T14:42:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/66/57/886a938073b97556c168fd99e1a7305bb363cd30a6d2c76086bf0587b32a/pydantic_core-2.46.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9ce92e58abc722dac1bf835a6798a60b294e48eb0e625ec9fd994b932ac5feee", size = 1934329, upload-time = "2026-04-20T14:43:49.655Z" }, + { url = "https://files.pythonhosted.org/packages/0b/7c/b42eaa5c34b13b07ecb51da21761297a9b8eb43044c864a035999998f328/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a03e6467f0f5ab796a486146d1b887b2dc5e5f9b3288898c1b1c3ad974e53e4a", size = 1974847, upload-time = "2026-04-20T14:42:10.737Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9b/92b42db6543e7de4f99ae977101a2967b63122d4b6cf7773812da2d7d5b5/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2798b6ba041b9d70acfb9071a2ea13c8456dd1e6a5555798e41ba7b0790e329c", size = 2041742, upload-time = "2026-04-20T14:40:44.262Z" }, + { url = "https://files.pythonhosted.org/packages/0f/19/46fbe1efabb5aa2834b43b9454e70f9a83ad9c338c1291e48bdc4fecf167/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9be3e221bdc6d69abf294dcf7aff6af19c31a5cdcc8f0aa3b14be29df4bd03b1", size = 2236235, upload-time = "2026-04-20T14:41:27.307Z" }, + { url = "https://files.pythonhosted.org/packages/77/da/b3f95bc009ad60ec53120f5d16c6faa8cabdbe8a20d83849a1f2b8728148/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13936129ce841f2a5ddf6f126fea3c43cd128807b5a59588c37cf10178c2e64", size = 2282633, upload-time = "2026-04-20T14:44:33.271Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6e/401336117722e28f32fb8220df676769d28ebdf08f2f4469646d404c43a3/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28b5f2ef03416facccb1c6ef744c69793175fd27e44ef15669201601cf423acb", size = 2109679, upload-time = "2026-04-20T14:44:41.065Z" }, + { url = "https://files.pythonhosted.org/packages/fc/53/b289f9bc8756a32fe718c46f55afaeaf8d489ee18d1a1e7be1db73f42cc4/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:830d1247d77ad23852314f069e9d7ddafeec5f684baf9d7e7065ed46a049c4e6", size = 2108342, upload-time = "2026-04-20T14:42:50.144Z" }, + { url = "https://files.pythonhosted.org/packages/10/5b/8292fc7c1f9111f1b2b7c1b0dcf1179edcd014fc3ea4517499f50b829d71/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0793c90c1a3c74966e7975eaef3ed30ebdff3260a0f815a62a22adc17e4c01c", size = 2157208, upload-time = "2026-04-20T14:42:08.133Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9e/f80044e9ec07580f057a89fc131f78dda7a58751ddf52bbe05eaf31db50f/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d2d0aead851b66f5245ec0c4fb2612ef457f8bbafefdf65a2bf9d6bac6140f47", size = 2167237, upload-time = "2026-04-20T14:42:25.412Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/6781a1b037f3b96be9227edbd1101f6d3946746056231bf4ac48cdff1a8d/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:2f40e4246676beb31c5ce77c38a55ca4e465c6b38d11ea1bd935420568e0b1ab", size = 2312540, upload-time = "2026-04-20T14:40:40.313Z" }, + { url = "https://files.pythonhosted.org/packages/3e/db/19c0839feeb728e7df03255581f198dfdf1c2aeb1e174a8420b63c5252e5/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:cf489cf8986c543939aeee17a09c04d6ffb43bfef8ca16fcbcc5cfdcbed24dba", size = 2369556, upload-time = "2026-04-20T14:41:09.427Z" }, + { url = "https://files.pythonhosted.org/packages/e0/15/3228774cb7cd45f5f721ddf1b2242747f4eb834d0c491f0c02d606f09fed/pydantic_core-2.46.3-cp314-cp314t-win32.whl", hash = "sha256:ffe0883b56cfc05798bf994164d2b2ff03efe2d22022a2bb080f3b626176dd56", size = 1949756, upload-time = "2026-04-20T14:41:25.717Z" }, + { url = "https://files.pythonhosted.org/packages/b8/2a/c79cf53fd91e5a87e30d481809f52f9a60dd221e39de66455cf04deaad37/pydantic_core-2.46.3-cp314-cp314t-win_amd64.whl", hash = "sha256:706d9d0ce9cf4593d07270d8e9f53b161f90c57d315aeec4fb4fd7a8b10240d8", size = 2051305, upload-time = "2026-04-20T14:43:18.627Z" }, + { url = "https://files.pythonhosted.org/packages/0b/db/d8182a7f1d9343a032265aae186eb063fe26ca4c40f256b21e8da4498e89/pydantic_core-2.46.3-cp314-cp314t-win_arm64.whl", hash = "sha256:77706aeb41df6a76568434701e0917da10692da28cb69d5fb6919ce5fdb07374", size = 2026310, upload-time = "2026-04-20T14:41:01.778Z" }, + { url = "https://files.pythonhosted.org/packages/34/42/f426db557e8ab2791bc7562052299944a118655496fbff99914e564c0a94/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:b12dd51f1187c2eb489af8e20f880362db98e954b54ab792fa5d92e8bcc6b803", size = 2091877, upload-time = "2026-04-20T14:43:27.091Z" }, + { url = "https://files.pythonhosted.org/packages/5c/4f/86a832a9d14df58e663bfdf4627dc00d3317c2bd583c4fb23390b0f04b8e/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f00a0961b125f1a47af7bcc17f00782e12f4cd056f83416006b30111d941dfa3", size = 1932428, upload-time = "2026-04-20T14:40:45.781Z" }, + { url = "https://files.pythonhosted.org/packages/11/1a/fe857968954d93fb78e0d4b6df5c988c74c4aaa67181c60be7cfe327c0ca/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57697d7c056aca4bbb680200f96563e841a6386ac1129370a0102592f4dddff5", size = 1997550, upload-time = "2026-04-20T14:44:02.425Z" }, + { url = "https://files.pythonhosted.org/packages/17/eb/9d89ad2d9b0ba8cd65393d434471621b98912abb10fbe1df08e480ba57b5/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd35aa21299def8db7ef4fe5c4ff862941a9a158ca7b63d61e66fe67d30416b4", size = 2137657, upload-time = "2026-04-20T14:42:45.149Z" }, ] [[package]] @@ -2505,16 +2505,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.13.1" +version = "2.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" } +sdist = { url = "https://files.pythonhosted.org/packages/42/98/c8345dccdc31de4228c039a98f6467a941e39558da41c1744fbe29fa5666/pydantic_settings-2.14.0.tar.gz", hash = "sha256:24285fd4b0e0c06507dd9fdfd331ee23794305352aaec8fc4eb92d4047aeb67d", size = 235709, upload-time = "2026-04-20T13:37:40.293Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" }, + { url = "https://files.pythonhosted.org/packages/01/dd/bebff3040138f00ae8a102d426b27349b9a49acc310fcae7f92112d867e3/pydantic_settings-2.14.0-py3-none-any.whl", hash = "sha256:fc8d5d692eb7092e43c8647c1c35a3ecd00e040fcf02ed86f4cb5458ca62182e", size = 60940, upload-time = "2026-04-20T13:37:38.586Z" }, ] [[package]] @@ -3083,27 +3083,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/d9/aa3f7d59a10ef6b14fe3431706f854dbf03c5976be614a9796d36326810c/ruff-0.15.10.tar.gz", hash = "sha256:d1f86e67ebfdef88e00faefa1552b5e510e1d35f3be7d423dc7e84e63788c94e", size = 4631728, upload-time = "2026-04-09T14:06:09.884Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/00/a1c2fdc9939b2c03691edbda290afcd297f1f389196172826b03d6b6a595/ruff-0.15.10-py3-none-linux_armv6l.whl", hash = "sha256:0744e31482f8f7d0d10a11fcbf897af272fefdfcb10f5af907b18c2813ff4d5f", size = 10563362, upload-time = "2026-04-09T14:06:21.189Z" }, - { url = "https://files.pythonhosted.org/packages/5c/15/006990029aea0bebe9d33c73c3e28c80c391ebdba408d1b08496f00d422d/ruff-0.15.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b1e7c16ea0ff5a53b7c2df52d947e685973049be1cdfe2b59a9c43601897b22e", size = 10951122, upload-time = "2026-04-09T14:06:02.236Z" }, - { url = "https://files.pythonhosted.org/packages/f2/c0/4ac978fe874d0618c7da647862afe697b281c2806f13ce904ad652fa87e4/ruff-0.15.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93cc06a19e5155b4441dd72808fdf84290d84ad8a39ca3b0f994363ade4cebb1", size = 10314005, upload-time = "2026-04-09T14:06:00.026Z" }, - { url = "https://files.pythonhosted.org/packages/da/73/c209138a5c98c0d321266372fc4e33ad43d506d7e5dd817dd89b60a8548f/ruff-0.15.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e1dd04312997c99ea6965df66a14fb4f03ba978564574ffc68b0d61fd3989e", size = 10643450, upload-time = "2026-04-09T14:05:42.137Z" }, - { url = "https://files.pythonhosted.org/packages/ec/76/0deec355d8ec10709653635b1f90856735302cb8e149acfdf6f82a5feb70/ruff-0.15.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8154d43684e4333360fedd11aaa40b1b08a4e37d8ffa9d95fee6fa5b37b6fab1", size = 10379597, upload-time = "2026-04-09T14:05:49.984Z" }, - { url = "https://files.pythonhosted.org/packages/dc/be/86bba8fc8798c081e28a4b3bb6d143ccad3fd5f6f024f02002b8f08a9fa3/ruff-0.15.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ab88715f3a6deb6bde6c227f3a123410bec7b855c3ae331b4c006189e895cef", size = 11146645, upload-time = "2026-04-09T14:06:12.246Z" }, - { url = "https://files.pythonhosted.org/packages/a8/89/140025e65911b281c57be1d385ba1d932c2366ca88ae6663685aed8d4881/ruff-0.15.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a768ff5969b4f44c349d48edf4ab4f91eddb27fd9d77799598e130fb628aa158", size = 12030289, upload-time = "2026-04-09T14:06:04.776Z" }, - { url = "https://files.pythonhosted.org/packages/88/de/ddacca9545a5e01332567db01d44bd8cf725f2db3b3d61a80550b48308ea/ruff-0.15.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ee3ef42dab7078bda5ff6a1bcba8539e9857deb447132ad5566a038674540d0", size = 11496266, upload-time = "2026-04-09T14:05:55.485Z" }, - { url = "https://files.pythonhosted.org/packages/bc/bb/7ddb00a83760ff4a83c4e2fc231fd63937cc7317c10c82f583302e0f6586/ruff-0.15.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51cb8cc943e891ba99989dd92d61e29b1d231e14811db9be6440ecf25d5c1609", size = 11256418, upload-time = "2026-04-09T14:05:57.69Z" }, - { url = "https://files.pythonhosted.org/packages/dc/8d/55de0d35aacf6cd50b6ee91ee0f291672080021896543776f4170fc5c454/ruff-0.15.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e59c9bdc056a320fb9ea1700a8d591718b8faf78af065484e801258d3a76bc3f", size = 11288416, upload-time = "2026-04-09T14:05:44.695Z" }, - { url = "https://files.pythonhosted.org/packages/68/cf/9438b1a27426ec46a80e0a718093c7f958ef72f43eb3111862949ead3cc1/ruff-0.15.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:136c00ca2f47b0018b073f28cb5c1506642a830ea941a60354b0e8bc8076b151", size = 10621053, upload-time = "2026-04-09T14:05:52.782Z" }, - { url = "https://files.pythonhosted.org/packages/4c/50/e29be6e2c135e9cd4cb15fbade49d6a2717e009dff3766dd080fcb82e251/ruff-0.15.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b80a2f3c9c8a950d6237f2ca12b206bccff626139be9fa005f14feb881a1ae8", size = 10378302, upload-time = "2026-04-09T14:06:14.361Z" }, - { url = "https://files.pythonhosted.org/packages/18/2f/e0b36a6f99c51bb89f3a30239bc7bf97e87a37ae80aa2d6542d6e5150364/ruff-0.15.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e3e53c588164dc025b671c9df2462429d60357ea91af7e92e9d56c565a9f1b07", size = 10850074, upload-time = "2026-04-09T14:06:16.581Z" }, - { url = "https://files.pythonhosted.org/packages/11/08/874da392558ce087a0f9b709dc6ec0d60cbc694c1c772dab8d5f31efe8cb/ruff-0.15.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b0c52744cf9f143a393e284125d2576140b68264a93c6716464e129a3e9adb48", size = 11358051, upload-time = "2026-04-09T14:06:18.948Z" }, - { url = "https://files.pythonhosted.org/packages/e4/46/602938f030adfa043e67112b73821024dc79f3ab4df5474c25fa4c1d2d14/ruff-0.15.10-py3-none-win32.whl", hash = "sha256:d4272e87e801e9a27a2e8df7b21011c909d9ddd82f4f3281d269b6ba19789ca5", size = 10588964, upload-time = "2026-04-09T14:06:07.14Z" }, - { url = "https://files.pythonhosted.org/packages/25/b6/261225b875d7a13b33a6d02508c39c28450b2041bb01d0f7f1a83d569512/ruff-0.15.10-py3-none-win_amd64.whl", hash = "sha256:28cb32d53203242d403d819fd6983152489b12e4a3ae44993543d6fe62ab42ed", size = 11745044, upload-time = "2026-04-09T14:05:39.473Z" }, - { url = "https://files.pythonhosted.org/packages/58/ed/dea90a65b7d9e69888890fb14c90d7f51bf0c1e82ad800aeb0160e4bacfd/ruff-0.15.10-py3-none-win_arm64.whl", hash = "sha256:601d1610a9e1f1c2165a4f561eeaa2e2ea1e97f3287c5aa258d3dab8b57c6188", size = 11035607, upload-time = "2026-04-09T14:05:47.593Z" }, +version = "0.15.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/8d/192f3d7103816158dfd5ea50d098ef2aec19194e6cbccd4b3485bdb2eb2d/ruff-0.15.11.tar.gz", hash = "sha256:f092b21708bf0e7437ce9ada249dfe688ff9a0954fc94abab05dcea7dcd29c33", size = 4637264, upload-time = "2026-04-16T18:46:26.58Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/1e/6aca3427f751295ab011828e15e9bf452200ac74484f1db4be0197b8170b/ruff-0.15.11-py3-none-linux_armv6l.whl", hash = "sha256:e927cfff503135c558eb581a0c9792264aae9507904eb27809cdcff2f2c847b7", size = 10607943, upload-time = "2026-04-16T18:46:05.967Z" }, + { url = "https://files.pythonhosted.org/packages/e7/26/1341c262e74f36d4e84f3d6f4df0ac68cd53331a66bfc5080daa17c84c0b/ruff-0.15.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7a1b5b2938d8f890b76084d4fa843604d787a912541eae85fd7e233398bbb73e", size = 10988592, upload-time = "2026-04-16T18:46:00.742Z" }, + { url = "https://files.pythonhosted.org/packages/03/71/850b1d6ffa9564fbb6740429bad53df1094082fe515c8c1e74b6d8d05f18/ruff-0.15.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d4176f3d194afbdaee6e41b9ccb1a2c287dba8700047df474abfbe773825d1cb", size = 10338501, upload-time = "2026-04-16T18:46:03.723Z" }, + { url = "https://files.pythonhosted.org/packages/f2/11/cc1284d3e298c45a817a6aadb6c3e1d70b45c9b36d8d9cce3387b495a03a/ruff-0.15.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b17c886fb88203ced3afe7f14e8d5ae96e9d2f4ccc0ee66aa19f2c2675a27e4", size = 10670693, upload-time = "2026-04-16T18:46:41.941Z" }, + { url = "https://files.pythonhosted.org/packages/ce/9e/f8288b034ab72b371513c13f9a41d9ba3effac54e24bfb467b007daee2ca/ruff-0.15.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:49fafa220220afe7758a487b048de4c8f9f767f37dfefad46b9dd06759d003eb", size = 10416177, upload-time = "2026-04-16T18:46:21.717Z" }, + { url = "https://files.pythonhosted.org/packages/85/71/504d79abfd3d92532ba6bbe3d1c19fada03e494332a59e37c7c2dabae427/ruff-0.15.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2ab8427e74a00d93b8bda1307b1e60970d40f304af38bccb218e056c220120d", size = 11221886, upload-time = "2026-04-16T18:46:15.086Z" }, + { url = "https://files.pythonhosted.org/packages/43/5a/947e6ab7a5ad603d65b474be15a4cbc6d29832db5d762cd142e4e3a74164/ruff-0.15.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:195072c0c8e1fc8f940652073df082e37a5d9cb43b4ab1e4d0566ab8977a13b7", size = 12075183, upload-time = "2026-04-16T18:46:07.944Z" }, + { url = "https://files.pythonhosted.org/packages/9f/a1/0b7bb6268775fdd3a0818aee8efd8f5b4e231d24dd4d528ced2534023182/ruff-0.15.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a0996d486af3920dec930a2e7daed4847dfc12649b537a9335585ada163e9e", size = 11516575, upload-time = "2026-04-16T18:46:31.687Z" }, + { url = "https://files.pythonhosted.org/packages/30/c3/bb5168fc4d233cc06e95f482770d0f3c87945a0cd9f614b90ea8dc2f2833/ruff-0.15.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bef2cb556d509259f1fe440bb9cd33c756222cf0a7afe90d15edf0866702431", size = 11306537, upload-time = "2026-04-16T18:46:36.988Z" }, + { url = "https://files.pythonhosted.org/packages/e4/92/4cfae6441f3967317946f3b788136eecf093729b94d6561f963ed810c82e/ruff-0.15.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:030d921a836d7d4a12cf6e8d984a88b66094ccb0e0f17ddd55067c331191bf19", size = 11296813, upload-time = "2026-04-16T18:46:24.182Z" }, + { url = "https://files.pythonhosted.org/packages/43/26/972784c5dde8313acde8ac71ba8ac65475b85db4a2352a76c9934361f9bc/ruff-0.15.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0e783b599b4577788dbbb66b9addcef87e9a8832f4ce0c19e34bf55543a2f890", size = 10633136, upload-time = "2026-04-16T18:46:39.802Z" }, + { url = "https://files.pythonhosted.org/packages/5b/53/3985a4f185020c2f367f2e08a103032e12564829742a1b417980ce1514a0/ruff-0.15.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ae90592246625ba4a34349d68ec28d4400d75182b71baa196ddb9f82db025ef5", size = 10424701, upload-time = "2026-04-16T18:46:10.381Z" }, + { url = "https://files.pythonhosted.org/packages/d3/57/bf0dfb32241b56c83bb663a826133da4bf17f682ba8c096973065f6e6a68/ruff-0.15.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1f111d62e3c983ed20e0ca2e800f8d77433a5b1161947df99a5c2a3fb60514f0", size = 10873887, upload-time = "2026-04-16T18:46:29.157Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/e48076b2a57dc33ee8c7a957296f97c744ca891a8ffb4ffb1aaa3b3f517d/ruff-0.15.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:06f483d6646f59eaffba9ae30956370d3a886625f511a3108994000480621d1c", size = 11404316, upload-time = "2026-04-16T18:46:19.462Z" }, + { url = "https://files.pythonhosted.org/packages/88/27/0195d15fe7a897cbcba0904792c4b7c9fdd958456c3a17d2ea6093716a9a/ruff-0.15.11-py3-none-win32.whl", hash = "sha256:476a2aa56b7da0b73a3ee80b6b2f0e19cce544245479adde7baa65466664d5f3", size = 10655535, upload-time = "2026-04-16T18:46:12.47Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5e/c927b325bd4c1d3620211a4b96f47864633199feed60fa936025ab27e090/ruff-0.15.11-py3-none-win_amd64.whl", hash = "sha256:8b6756d88d7e234fb0c98c91511aae3cd519d5e3ed271cae31b20f39cb2a12a3", size = 11779692, upload-time = "2026-04-16T18:46:17.268Z" }, + { url = "https://files.pythonhosted.org/packages/63/b6/aeadee5443e49baa2facd51131159fd6301cc4ccfc1541e4df7b021c37dd/ruff-0.15.11-py3-none-win_arm64.whl", hash = "sha256:063fed18cc1bbe0ee7393957284a6fe8b588c6a406a285af3ee3f46da2391ee4", size = 11032614, upload-time = "2026-04-16T18:46:34.487Z" }, ] [[package]] @@ -3272,7 +3272,7 @@ wheels = [ [[package]] name = "textual" -version = "8.2.3" +version = "8.2.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py", extra = ["linkify"] }, @@ -3282,9 +3282,9 @@ dependencies = [ { name = "rich" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/2f/d44f0f12b3ddb1f0b88f7775652e99c6b5a43fd733badf4ce064bdbfef4a/textual-8.2.3.tar.gz", hash = "sha256:beea7b86b03b03558a2224f0cc35252e60ef8b0c4353b117b2f40972902d976a", size = 1848738, upload-time = "2026-04-05T09:12:45.338Z" } +sdist = { url = "https://files.pythonhosted.org/packages/19/89/bec5709fb759f9c784bbcb30b2e3497df3f901691d13c2b864dbf6694a17/textual-8.2.4.tar.gz", hash = "sha256:d4e2b2ddd7157191d00b228592b7c739ea080b7d792fd410f23ca75f05ea76c4", size = 1848933, upload-time = "2026-04-19T04:20:45.845Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/28/a81d6ce9f4804818bd1231a9a6e4d56ea84ebbe8385c49591444f0234fa2/textual-8.2.3-py3-none-any.whl", hash = "sha256:5008ac581bebf1f6fa0520404261844a231e5715fdbddd10ca73916a3af48ca2", size = 724231, upload-time = "2026-04-05T09:12:48.747Z" }, + { url = "https://files.pythonhosted.org/packages/5c/32/02932f0d597cdbb34e34bf24266ff0f2cf292ccb3aafc37dd9efcb0cc416/textual-8.2.4-py3-none-any.whl", hash = "sha256:a83bd3f0cc7125ca203845af753f9d6b6be030025ecd1b05cc75ebe645b9c4ba", size = 724390, upload-time = "2026-04-19T04:20:49.968Z" }, ] [package.optional-dependencies] @@ -3664,7 +3664,7 @@ wheels = [ [[package]] name = "typer" -version = "0.24.1" +version = "0.24.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -3672,9 +3672,9 @@ dependencies = [ { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/24/cb09efec5cc954f7f9b930bf8279447d24618bb6758d4f6adf2574c41780/typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45", size = 118613, upload-time = "2026-02-21T16:54:40.609Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/b8/9ebb531b6c2d377af08ac6746a5df3425b21853a5d2260876919b58a2a4a/typer-0.24.2.tar.gz", hash = "sha256:ec070dcfca1408e85ee203c6365001e818c3b7fffe686fd07ff2d68095ca0480", size = 119849, upload-time = "2026-04-22T17:45:34.413Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/91/48db081e7a63bb37284f9fbcefda7c44c277b18b0e13fbc36ea2335b71e6/typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e", size = 56085, upload-time = "2026-02-21T16:54:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/39/d1/9484b497e0a0410b901c12b8251c3e746e1e863f7d28419ffe06f7892fda/typer-0.24.2-py3-none-any.whl", hash = "sha256:b618bc3d721f9a8d30f3e05565be26416d06e9bcc29d49bc491dc26aba674fa8", size = 55977, upload-time = "2026-04-22T17:45:33.055Z" }, ] [[package]] @@ -3736,15 +3736,15 @@ wheels = [ [[package]] name = "uvicorn" -version = "0.44.0" +version = "0.46.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/da/6eee1ff8b6cbeed47eeb5229749168e81eb4b7b999a1a15a7176e51410c9/uvicorn-0.44.0.tar.gz", hash = "sha256:6c942071b68f07e178264b9152f1f16dfac5da85880c4ce06366a96d70d4f31e", size = 86947, upload-time = "2026-04-06T09:23:22.826Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1f/93/041fca8274050e40e6791f267d82e0e2e27dd165627bd640d3e0e378d877/uvicorn-0.46.0.tar.gz", hash = "sha256:fb9da0926999cc6cb22dc7cd71a94a632f078e6ae47ff683c5c420750fb7413d", size = 88758, upload-time = "2026-04-23T07:16:00.151Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/23/a5bbd9600dd607411fa644c06ff4951bec3a4d82c4b852374024359c19c0/uvicorn-0.44.0-py3-none-any.whl", hash = "sha256:ce937c99a2cc70279556967274414c087888e8cec9f9c94644dfca11bd3ced89", size = 69425, upload-time = "2026-04-06T09:23:21.524Z" }, + { url = "https://files.pythonhosted.org/packages/31/a3/5b1562db76a5a488274b2332a97199b32d0442aca0ed193697fd47786316/uvicorn-0.46.0-py3-none-any.whl", hash = "sha256:bbebbcbed972d162afca128605223022bedd345b7bc7855ce66deb31487a9048", size = 70926, upload-time = "2026-04-23T07:15:58.355Z" }, ] [package.optional-dependencies] @@ -3805,7 +3805,7 @@ wheels = [ [[package]] name = "virtualenv" -version = "21.2.3" +version = "21.2.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, @@ -3813,9 +3813,9 @@ dependencies = [ { name = "platformdirs" }, { name = "python-discovery" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/8c/bdd9f89f89e4a787ac61bb2da4d884bc45e0c287ec694dfa3170dddd5cfe/virtualenv-21.2.3.tar.gz", hash = "sha256:9bb6d1414ab55ca624371e30c7719c32f183ef44da544ef8aa44a456de7ac191", size = 5844776, upload-time = "2026-04-14T01:10:36.692Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0c/98/3a7e644e19cb26133488caff231be390579860bbbb3da35913c49a1d0a46/virtualenv-21.2.4.tar.gz", hash = "sha256:b294ef68192638004d72524ce7ef303e9d0cf5a44c95ce2e54a7500a6381cada", size = 5850742, upload-time = "2026-04-14T22:15:31.438Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/19/bc7c4e05f42532863cf2ae7e7e847beab25835934e0410160b47eeff1e35/virtualenv-21.2.3-py3-none-any.whl", hash = "sha256:486652347ea8526d91e9807c0274583cb7ba31dd4942ff10fb5621402f0fe0d8", size = 5828329, upload-time = "2026-04-14T01:10:34.809Z" }, + { url = "https://files.pythonhosted.org/packages/27/8d/edd0bd910ff803c308ee9a6b7778621af0d10252219ad9f19ef4d4982a61/virtualenv-21.2.4-py3-none-any.whl", hash = "sha256:29d21e941795206138d0f22f4e45ff7050e5da6c6472299fb7103318763861ac", size = 5831232, upload-time = "2026-04-14T22:15:29.342Z" }, ] [[package]] diff --git a/dev.Dockerfile b/dev.Dockerfile index 5c15ae3..75f526e 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -19,16 +19,21 @@ ENV PATH="/root/.local/bin/:$PATH" # Install the project into `/app` WORKDIR /app +# Project setup +ENV UV_PROJECT=/app/backend +ENV UV_PROJECT_ENVIRONMENT=/opt/venv + # Enable bytecode compilation ENV UV_COMPILE_BYTECODE=1 # Copy from the cache instead of linking since it's a mounted volume ENV UV_LINK_MODE=copy + # Install the project's dependencies using the lockfile and settings 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 \ + --mount=type=bind,source=backend/uv.lock,target=backend/uv.lock \ + --mount=type=bind,source=backend/pyproject.toml,target=backend/pyproject.toml \ uv sync --frozen --no-install-project RUN echo 'alias pip="uv pip"' >> ~/.bashrc @@ -39,9 +44,11 @@ COPY . /app RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen +# setup default PYTEST opts to get config from the right place +ENV PYTEST_ADDOPTS="--rootdir=/app/backend -c /app/backend/pyproject.toml /app/backend" # Place executables in the environment at the front of the path -ENV PATH="/app/.venv/bin:$PATH" +ENV PATH="/opt/venv/bin:$PATH" COPY ./entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh diff --git a/prod.Dockerfile b/prod.Dockerfile index ecb5ca2..13e6581 100644 --- a/prod.Dockerfile +++ b/prod.Dockerfile @@ -19,6 +19,10 @@ ENV PATH="/root/.local/bin/:$PATH" # Install the project into `/app` WORKDIR /app +# Project setup +ENV UV_PROJECT=/app/backend +ENV UV_PROJECT_ENVIRONMENT=/opt/venv + # Enable bytecode compilation ENV UV_COMPILE_BYTECODE=1 @@ -27,8 +31,8 @@ ENV UV_LINK_MODE=copy # Install the project's dependencies using the lockfile and settings 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 \ + --mount=type=bind,source=backend/uv.lock,target=backend/uv.lock \ + --mount=type=bind,source=backend/pyproject.toml,target=backend/pyproject.toml \ uv sync --frozen --no-install-project --no-dev RUN echo 'alias pip="uv pip"' >> ~/.bashrc @@ -40,7 +44,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev # Place executables in the environment at the front of the path -ENV PATH="/app/.venv/bin:$PATH" +ENV PATH="/opt/venv/bin:$PATH" COPY ./entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh diff --git a/sonar-project.properties b/sonar-project.properties index 908b252..a955962 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,8 +3,8 @@ sonar.organization=softwareone-mpt-github sonar.language=py -sonar.sources=app -sonar.tests=tests +sonar.sources=backend/app +sonar.tests=backend/tests sonar.inclusions=app/** sonar.exclusions=tests/**, app/main.py, app/__main__.py