From 7d1a7d1212da92a9972407c4ab2c16b695949cb6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 14:20:43 +0200 Subject: [PATCH 001/100] [v3-2-test] add concurrency in update-constrants-on-push (#64645) (#64671) (cherry picked from commit 7047e0326f8d6f1e890fa0cd5294a46e214b9fe7) Co-authored-by: Henry Chen --- .github/workflows/update-constraints-on-push.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/update-constraints-on-push.yml b/.github/workflows/update-constraints-on-push.yml index 3dcd806c3aea1..182ad7374e4bc 100644 --- a/.github/workflows/update-constraints-on-push.yml +++ b/.github/workflows/update-constraints-on-push.yml @@ -26,6 +26,10 @@ on: # yamllint disable-line rule:truthy - 'uv.lock' permissions: contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From d31266748da7b30fac4fd0b3dbf3accf4a44b69d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 16:47:54 +0200 Subject: [PATCH 002/100] [v3-2-test] Skip UI E2E tests on derived full tests needed, canary, and scheduled builds (#64673) (#64675) UI E2E tests are expensive and should only run when UI files actually changed or the "full tests needed" label is explicitly set. Previously they ran on every push to main, canary build, scheduled run, and any PR that triggered derived full_tests_needed (env file changes, large PRs, etc.). (cherry picked from commit b15a5c9595d5fa93a6a4a8134d1a3e579262aae0) Co-authored-by: Jarek Potiuk --- .../airflow_breeze/utils/selective_checks.py | 21 ++++++++++++++++++- dev/breeze/tests/test_selective_checks.py | 2 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py b/dev/breeze/src/airflow_breeze/utils/selective_checks.py index 1985da6ece1dd..9c40ee982ee64 100644 --- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py +++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py @@ -944,7 +944,26 @@ def run_ui_tests(self) -> bool: @cached_property def run_ui_e2e_tests(self) -> bool: - return self._should_be_run(FileGroupForCi.UI_FILES) + # E2E tests should not be triggered by derived full_tests_needed (push events, + # env file changes, large PRs, etc.) - only by explicit label or actual file changes. + if FULL_TESTS_NEEDED_LABEL in self._pr_labels: + console_print( + f"[warning]{FileGroupForCi.UI_FILES} e2e enabled because " + f"'{FULL_TESTS_NEEDED_LABEL}' label is set[/]" + ) + return True + matched_files = self._matching_files(FileGroupForCi.UI_FILES, CI_FILE_GROUP_MATCHES) + if matched_files: + console_print( + f"[warning]{FileGroupForCi.UI_FILES} e2e enabled because " + f"it matched {len(matched_files)} changed files[/]" + ) + return True + console_print( + f"[warning]{FileGroupForCi.UI_FILES} e2e disabled because " + f"it did not match any changed files and no explicit label[/]" + ) + return False @cached_property def run_remote_logging_s3_e2e_tests(self) -> bool: diff --git a/dev/breeze/tests/test_selective_checks.py b/dev/breeze/tests/test_selective_checks.py index bd26d1f6ba573..9d674bd761da9 100644 --- a/dev/breeze/tests/test_selective_checks.py +++ b/dev/breeze/tests/test_selective_checks.py @@ -1581,6 +1581,7 @@ def test_full_test_needed_when_scripts_changes(files: tuple[str, ...], expected_ "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, "run-mypy": "true", "mypy-checks": ALL_MYPY_CHECKS, + "run-ui-e2e-tests": "true", }, id="Everything should run including all providers when full tests are needed " "but with single python and kubernetes if no version label is set", @@ -1922,6 +1923,7 @@ def test_expected_output_pull_request_v2_7( "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, "run-mypy": "true", "mypy-checks": ALL_MYPY_CHECKS, + "run-ui-e2e-tests": "false", }, id="All tests run on push if core file changed", ), From 87fc18bad72e231ca110e0e9b18f39572821132e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 14:57:39 +0200 Subject: [PATCH 003/100] [v3-2-test] Temporarily upgrade allowlist-check to latest version (#64713) (#64717) Temporary switch to the latest commit of infrastructure-actions allowlist-check until apache/infrastructure-actions#662 is merged, which will provide a proper tagged release. (cherry picked from commit 04b3dd02a53e9810d6f9d17d03feae53ae8b7835) Co-authored-by: Jarek Potiuk --- .github/workflows/asf-allowlist-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/asf-allowlist-check.yml b/.github/workflows/asf-allowlist-check.yml index 3112509faae16..3e6d5fe9f0c48 100644 --- a/.github/workflows/asf-allowlist-check.yml +++ b/.github/workflows/asf-allowlist-check.yml @@ -31,4 +31,4 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: apache/infrastructure-actions/allowlist-check@493edcdbd80d9e78a767f256a877b1cc6c9712ba # main + - uses: apache/infrastructure-actions/allowlist-check@e9aff90d22568865baa7d1d12676c01fa29f59c4 # main From f02df24e88023453e0a8629cf2c309d565c03c15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:17:43 +0200 Subject: [PATCH 004/100] Bump the github-actions-updates group with 3 updates (#64686) Bumps the github-actions-updates group with 3 updates: [actions/setup-go](https://github.com/actions/setup-go), [github/codeql-action](https://github.com/github/codeql-action) and [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv). Updates `actions/setup-go` from 6.3.0 to 6.4.0 - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/4b73464bb391d4059bd26b0524d20df3927bd417...4a3601121dd01d1626a1e23e37211e3254c1c06c) Updates `github/codeql-action` from 4.32.6 to 4.35.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0d579ffd059c29b07949a3cce3983f0780820c98...c10b8064de6f491fea524254123dbe5e09572f13) Updates `astral-sh/setup-uv` from 7.6.0 to 8.0.0 - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/37802adc94f370d6bfd71619e3f0bf239e1f3b78...cec208311dfd045dd5311c1add060b2062131d57) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: github/codeql-action dependency-version: 4.35.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: astral-sh/setup-uv dependency-version: 8.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-updates ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-amd-arm.yml | 2 +- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/registry-backfill.yml | 2 +- .github/workflows/registry-tests.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-amd-arm.yml b/.github/workflows/ci-amd-arm.yml index b69791a09a5dc..ab34ba25882bb 100644 --- a/.github/workflows/ci-amd-arm.yml +++ b/.github/workflows/ci-amd-arm.yml @@ -843,7 +843,7 @@ jobs: persist-credentials: false # keep this in sync with go.mod in go-sdk/ - name: Setup Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version: 1.24 cache-dependency-path: go-sdk/go.sum diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0c21c6e43d652..a6ae94fd3fa65 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -52,15 +52,15 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: # Provide more context to the SARIF output (shows up in run.automationDetails.id field) category: "/language:${{matrix.language}}" diff --git a/.github/workflows/registry-backfill.yml b/.github/workflows/registry-backfill.yml index 62483ca8c3d6b..a421ee4680a3d 100644 --- a/.github/workflows/registry-backfill.yml +++ b/.github/workflows/registry-backfill.yml @@ -118,7 +118,7 @@ jobs: done - name: "Install uv" - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 - name: "Install Breeze" uses: ./.github/actions/breeze diff --git a/.github/workflows/registry-tests.yml b/.github/workflows/registry-tests.yml index 38143ab8a6bf3..2c38e724b8658 100644 --- a/.github/workflows/registry-tests.yml +++ b/.github/workflows/registry-tests.yml @@ -50,7 +50,7 @@ jobs: persist-credentials: false - name: "Install uv" - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 with: python-version: "3.12" From c31ec53cebe6ee86f59ac11f77d7c7186852c833 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:18:50 +0200 Subject: [PATCH 005/100] [v3-2-test] Simplify ci_image_build and add test coverage for remote logging e2e (#64697) (#64698) Refactor ci_image_build to delegate to prod_image_build instead of duplicating conditions. Add ci-image-build assertions to all 5 remote logging e2e test cases to verify CI image is built when remote logging files change. (cherry picked from commit 3cf4f51c2f09532d5ffa6c028694f7073fe90ffc) Co-authored-by: Jarek Potiuk --- dev/breeze/src/airflow_breeze/utils/selective_checks.py | 4 +--- dev/breeze/tests/test_selective_checks.py | 5 +++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py b/dev/breeze/src/airflow_breeze/utils/selective_checks.py index 9c40ee982ee64..5167505275a03 100644 --- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py +++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py @@ -1065,12 +1065,10 @@ def ci_image_build(self) -> bool: self.run_unit_tests or self.docs_build or self.run_kubernetes_tests - or self.run_task_sdk_integration_tests - or self.run_airflow_ctl_integration_tests - or self.run_helm_tests or self.run_ui_tests or self.pyproject_toml_changed or self.any_provider_yaml_or_pyproject_toml_changed + or self.prod_image_build ) @cached_property diff --git a/dev/breeze/tests/test_selective_checks.py b/dev/breeze/tests/test_selective_checks.py index 9d674bd761da9..6135a9f77399e 100644 --- a/dev/breeze/tests/test_selective_checks.py +++ b/dev/breeze/tests/test_selective_checks.py @@ -1256,6 +1256,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str): { "run-remote-logging-s3-e2e-tests": "true", "run-remote-logging-elasticsearch-e2e-tests": "false", + "ci-image-build": "true", "prod-image-build": "true", }, id="S3 remote logging changes enable only S3 e2e", @@ -1267,6 +1268,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str): { "run-remote-logging-s3-e2e-tests": "false", "run-remote-logging-elasticsearch-e2e-tests": "true", + "ci-image-build": "true", "prod-image-build": "true", }, id="Elasticsearch remote logging changes enable only Elasticsearch e2e", @@ -1278,6 +1280,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str): { "run-remote-logging-s3-e2e-tests": "false", "run-remote-logging-elasticsearch-e2e-tests": "true", + "ci-image-build": "true", "prod-image-build": "true", }, id="Elasticsearch helper changes enable Elasticsearch e2e", @@ -1289,6 +1292,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str): { "run-remote-logging-s3-e2e-tests": "true", "run-remote-logging-elasticsearch-e2e-tests": "true", + "ci-image-build": "true", "prod-image-build": "true", }, id="Shared remote logging changes enable both remote logging e2e jobs", @@ -1300,6 +1304,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str): { "run-remote-logging-s3-e2e-tests": "true", "run-remote-logging-elasticsearch-e2e-tests": "true", + "ci-image-build": "true", "prod-image-build": "true", }, id="Shared logging library changes enable both remote logging e2e jobs", From 5a4768c653440cdb8696042cb2cd95e76259d433 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:41:05 +0200 Subject: [PATCH 006/100] [v3-2-test] Add --frozen to uv run commands in run_tests and document uv lock behavior (#64699) (#64721) (cherry picked from commit f2a3e5feac7c4d5a34f3691daf766ae84b130486) Co-authored-by: Jarek Potiuk Co-authored-by: Claude Opus 4.6 (1M context) --- contributing-docs/07_local_virtualenv.rst | 75 +++++++++---------- .../13_airflow_dependencies_and_extras.rst | 11 ++- .../src/airflow_breeze/utils/run_tests.py | 13 +++- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/contributing-docs/07_local_virtualenv.rst b/contributing-docs/07_local_virtualenv.rst index e6a0409ac9d80..b75db8d4dbd9e 100644 --- a/contributing-docs/07_local_virtualenv.rst +++ b/contributing-docs/07_local_virtualenv.rst @@ -267,57 +267,52 @@ for the provider is as simple as running: uv run pytest -Installing "golden" version of dependencies -------------------------------------------- +Locked versions of dependencies +------------------------------- -Whatever virtualenv solution you use, when you want to make sure you are using the same -version of dependencies as in main, you can install recommended version of the dependencies by using pip: -constraint-python.txt files as ``constraint`` file. This might be useful -to avoid "works-for-me" syndrome, where you use different version of dependencies than the ones -that are used in main, CI tests and by other contributors. +The ``uv.lock`` file is committed to the Airflow repository and is used by ``uv sync`` to ensure +consistent dependency versions across all developers. When you run ``uv sync``, it uses the lock file +to install exact dependency versions, so you don't need to pass constraint files manually. -There are different constraint files for different python versions. For example this command will install -all basic devel requirements and requirements of google provider as last successfully tested for Python 3.10: - -.. code:: bash - - uv pip install -e ".[devel,google]" \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-source-providers-3.10.txt" +The ``uv sync`` command prefers the locked versions of dependencies from ``uv.lock``. It will only +attempt to resolve new dependencies when ``pyproject.toml`` files change (e.g. when a new dependency +is added or version bounds are modified). This means that day-to-day ``uv sync`` is fast and +deterministic — it simply installs what the lock file specifies without re-resolving the dependency +tree. +If you want to make sure that ``uv sync`` does not update your lock file at all (for example in CI +or when running tests), you can pass the ``--frozen`` flag: -In the future we will utilise ``uv.lock`` to manage dependencies and constraints, but for the moment we do not -commit ``uv.lock`` file to Airflow repository because we need to figure out automation of updating the ``uv.lock`` -very frequently (few times a day sometimes). With Airflow's 700+ dependencies it's all but guaranteed that we -will have 3-4 changes a day and currently automated constraints generation mechanism in ``canary`` build keeps -constraints updated, but for ASF policy reasons we cannot update ``uv.lock`` in the same way - but work is in -progress to fix it. - -Make sure to use latest main for such installation, those constraints are "development constraints" and they -are refreshed several times a day to make sure they are up to date with the latest changes in the main branch. +.. code:: bash -Note that this might not always work as expected, because the constraints are not always updated -immediately after the dependencies are updated, sometimes there is a very recent change (few hours, rarely more -than a day) which still runs in ``canary`` build and constraints will not be updated until the canary build -succeeds. Usually what works in this case is running your install command without constraints. + uv sync --frozen -You can upgrade just airflow, without paying attention to provider's dependencies by using -the 'constraints-no-providers' constraint files. This allows you to keep installed provider dependencies -and install to latest supported ones by pure Airflow core. +This will fail if the lock file is out of date with respect to ``pyproject.toml``, rather than +silently updating it. This is useful when you want to guarantee fully reproducible environments. -.. code:: bash +Cooldown via ``exclude-newer`` +.............................. - uv pip install -e ".[devel]" \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-no-providers-3.10.txt" +The ``[tool.uv]`` section in the top-level ``pyproject.toml`` sets ``exclude-newer = "4 days"``. +This acts as a cooldown period — when ``uv`` resolves new dependencies, it ignores package versions +released in the last 4 days. This protects against broken or yanked releases that might otherwise +immediately break the dependency resolution for all developers. When ``uv`` writes the lock file, it +records the resolved ``exclude-newer`` timestamp so that subsequent ``uv sync`` calls use the same +cutoff, ensuring consistency across machines. -These are examples of the development options available with the local virtualenv in your IDE: +Constraints generated from the lock file +......................................... -* local debugging; -* Airflow source view; -* auto-completion; -* documentation support; -* unit tests. +Airflow also publishes traditional ``pip``-style constraint files (see +`Airflow dependencies and extras <13_airflow_dependencies_and_extras.rst>`_ for details). When +installing Airflow from sources, these constraint files are generated directly from ``uv.lock`` using +``uv export --frozen``, which converts the lock file into a flat list of pinned versions suitable for +``pip install --constraint``. This ensures that both the ``uv sync`` workflow and the ``pip`` constraint +workflow install the same dependency versions. -This document describes minimum requirements and instructions for using a standalone version of the local virtualenv. +The lock file is updated regularly — whenever dependencies are changed via any ``pyproject.toml`` and +when ``breeze ci upgrade`` is run. Make sure to use the latest main branch to get the most +up-to-date ``uv.lock``. Running Tests ------------- diff --git a/contributing-docs/13_airflow_dependencies_and_extras.rst b/contributing-docs/13_airflow_dependencies_and_extras.rst index cd43e486ffbdf..7c59ce25d17b1 100644 --- a/contributing-docs/13_airflow_dependencies_and_extras.rst +++ b/contributing-docs/13_airflow_dependencies_and_extras.rst @@ -318,17 +318,17 @@ example ``pip install apache-airflow==1.10.2 Werkzeug<1.0.0``) There are several sets of constraints we keep: -* 'constraints' - these are constraints generated by matching the current Airflow version from sources +* ``constraints`` - these are constraints generated by matching the current Airflow version from sources and providers that are installed from PyPI. Those are constraints used by the users who want to install Airflow with pip, they are named ``constraints-.txt``. -* "constraints-source-providers" - these are constraints generated by using providers installed from +* ``constraints-source-providers`` - these are constraints generated by using providers installed from current sources. While adding new providers their dependencies might change, so this set of providers is the current set of the constraints for Airflow and providers from the current main sources. Those providers are used by CI system to keep "stable" set of constraints. They are named ``constraints-source-providers-.txt`` -* "constraints-no-providers" - these are constraints generated from only Apache Airflow, without any +* ``constraints-no-providers`` - these are constraints generated from only Apache Airflow, without any providers. If you want to manage Airflow separately and then add providers individually, you can use them. Those constraints are named ``constraints-no-providers-.txt``. @@ -375,6 +375,11 @@ using ``constraints-no-providers`` constraint files as well. --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-no-providers-3.10.txt" +These constraint files are generated from the ``uv.lock`` file committed in the repository, using +``uv export --frozen`` to convert the lock file into a flat list of pinned versions suitable for +``pip install --constraint``. This means the constraint files always reflect the same dependency +versions that ``uv sync`` installs for developers. + The ``constraints-.txt`` and ``constraints-no-providers-.txt`` will be automatically regenerated by CI job every time after the ``pyproject.toml`` is updated and pushed if the tests are successful. diff --git a/dev/breeze/src/airflow_breeze/utils/run_tests.py b/dev/breeze/src/airflow_breeze/utils/run_tests.py index 5cd4e6692d85c..752c3c66cf7c0 100644 --- a/dev/breeze/src/airflow_breeze/utils/run_tests.py +++ b/dev/breeze/src/airflow_breeze/utils/run_tests.py @@ -90,7 +90,16 @@ def verify_an_image( if slim_image: env["TEST_SLIM_IMAGE"] = "true" command_result = run_command( - ["uv", "run", "--isolated", "pytest", test_path.as_posix(), *pytest_args, *extra_pytest_args], + [ + "uv", + "run", + "--frozen", + "--isolated", + "pytest", + test_path.as_posix(), + *pytest_args, + *extra_pytest_args, + ], env=env, output=output, check=False, @@ -177,7 +186,7 @@ def run_docker_compose_tests( env["INCLUDE_SUCCESS_OUTPUTS"] = "true" env["AIRFLOW_UID"] = str(os.getuid()) command_result = run_command( - ["uv", "run", "pytest", *pytest_args], + ["uv", "run", "--frozen", "pytest", *pytest_args], env=env, check=False, cwd=cwd, From e26e574bcd61c4895ff480acf9163a1746dce737 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 13:37:55 +0300 Subject: [PATCH 007/100] [v3-2-test] Fix start_date in example DAGs to avoid TZ conversion overflow (#63882) (#64758) * Fix start_date in example DAGs to avoid TZ conversion overflow * Update airflow-core/src/airflow/example_dags/example_inlet_event_extra.py * Update airflow-core/src/airflow/example_dags/example_inlet_event_extra.py * Update airflow-core/src/airflow/example_dags/example_outlet_event_extra.py * Update airflow-core/src/airflow/example_dags/example_outlet_event_extra.py * Apply suggestion from @yuseok89 --------- (cherry picked from commit db5e555cc628c7613e37772c07f7acc70a3d0c40) Co-authored-by: HuangWei Co-authored-by: yuseok89 --- .../src/airflow/example_dags/example_inlet_event_extra.py | 4 ++-- .../src/airflow/example_dags/example_outlet_event_extra.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/airflow-core/src/airflow/example_dags/example_inlet_event_extra.py b/airflow-core/src/airflow/example_dags/example_inlet_event_extra.py index ead4b442b782e..eb61ed443f6b2 100644 --- a/airflow-core/src/airflow/example_dags/example_inlet_event_extra.py +++ b/airflow-core/src/airflow/example_dags/example_inlet_event_extra.py @@ -33,7 +33,7 @@ with DAG( dag_id="read_asset_event", catchup=False, - start_date=datetime.datetime.min, + start_date=datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc), schedule="@daily", tags=["consumes"], ): @@ -48,7 +48,7 @@ def read_asset_event(*, inlet_events=None): with DAG( dag_id="read_asset_event_from_classic", catchup=False, - start_date=datetime.datetime.min, + start_date=datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc), schedule="@daily", tags=["consumes"], ): diff --git a/airflow-core/src/airflow/example_dags/example_outlet_event_extra.py b/airflow-core/src/airflow/example_dags/example_outlet_event_extra.py index 04e88554d16d3..7baab90625ded 100644 --- a/airflow-core/src/airflow/example_dags/example_outlet_event_extra.py +++ b/airflow-core/src/airflow/example_dags/example_outlet_event_extra.py @@ -33,7 +33,7 @@ with DAG( dag_id="asset_with_extra_by_yield", catchup=False, - start_date=datetime.datetime.min, + start_date=datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc), schedule="@daily", tags=["produces"], ): @@ -47,7 +47,7 @@ def asset_with_extra_by_yield(): with DAG( dag_id="asset_with_extra_by_context", catchup=False, - start_date=datetime.datetime.min, + start_date=datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc), schedule="@daily", tags=["produces"], ): @@ -61,7 +61,7 @@ def asset_with_extra_by_context(*, outlet_events=None): with DAG( dag_id="asset_with_extra_from_classic_operator", catchup=False, - start_date=datetime.datetime.min, + start_date=datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc), schedule="@daily", tags=["produces"], ): From 5d15870660cbfa3a87677da849c01455e294071f Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Mon, 6 Apr 2026 19:47:15 +0800 Subject: [PATCH 008/100] i18n: add missing keys and fix Taiwanese Mandarin terminology --- .../ui/public/i18n/locales/zh-TW/admin.json | 3 ++- .../ui/public/i18n/locales/zh-TW/assets.json | 2 +- .../ui/public/i18n/locales/zh-TW/browse.json | 4 ++-- .../ui/public/i18n/locales/zh-TW/common.json | 20 +++++++++++++++++++ .../public/i18n/locales/zh-TW/components.json | 4 ++-- .../ui/public/i18n/locales/zh-TW/dag.json | 3 ++- .../ui/public/i18n/locales/zh-TW/dags.json | 2 +- 7 files changed, 30 insertions(+), 8 deletions(-) diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/admin.json index f7d17f2bb9230..22b38661efb7f 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/admin.json @@ -120,7 +120,8 @@ "includeDeferred": "包含延後任務", "nameMaxLength": "名稱最多只能包含 256 個字元", "nameRequired": "名稱是必填的", - "slots": "配額" + "slots": "配額", + "slotsHelperText": "使用 -1 表示無限制配額。" }, "noPoolsFound": "找不到資源池", "pool_one": "資源池", diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/assets.json index 3e3bedd805547..843fed1452273 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/assets.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/assets.json @@ -29,7 +29,7 @@ "group": "群組", "lastAssetEvent": "最後資源事件", "name": "名稱", - "producingTasks": "生產任務", + "producingTasks": "生產者任務", "scheduledDags": "已排程的 Dags", "scheduling": "排程", "searchPlaceholder": "搜尋資源", diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/browse.json index e98d66cfb959e..f798eb6b875b0 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/browse.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/browse.json @@ -26,11 +26,11 @@ }, "delete": { "error": "刪除 XCom 失敗", - "errorTitle": "Error", + "errorTitle": "錯誤", "success": "成功刪除 XCom", "successTitle": "已刪除 XCom", "title": "刪除 XCom", - "warning": "你確定要刪除這個 XCom 嗎?此動作無法復原。" + "warning": "您確定要刪除這個 XCom 嗎?此動作無法復原。" }, "edit": { "error": "更新 XCom 失敗", diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/common.json index efaa36625d231..4562f9cb980d7 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/common.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/common.json @@ -103,6 +103,12 @@ "notFound": "找不到頁面", "title": "錯誤" }, + "errors": { + "forbidden": { + "description": "您沒有執行此操作的權限。", + "title": "存取被拒" + } + }, "expand": { "collapse": "收合", "expand": "展開", @@ -128,6 +134,7 @@ "selectDateRange": "選擇日期範圍", "startTime": "起始時間" }, + "generateToken": "產生權杖", "logicalDate": "邏輯日期", "logout": "登出", "logoutConfirmation": "確定要登出嗎?", @@ -171,6 +178,7 @@ "reset": "重置", "runId": "執行 ID", "runTypes": { + "asset_materialization": "資源實體化", "asset_triggered": "資源觸發", "backfill": "回填", "manual": "手動觸發", @@ -327,6 +335,18 @@ } } }, + "tokenGeneration": { + "apiToken": "API 權杖", + "cliToken": "CLI 權杖", + "errorDescription": "產生權杖時發生錯誤,請再試一次。", + "errorTitle": "權杖產生失敗", + "generate": "產生", + "selectType": "選擇要產生的權杖類型。", + "title": "產生權杖", + "tokenExpiresIn": "此權杖將在 {{duration}} 後過期。", + "tokenGenerated": "您的權杖已產生。", + "tokenShownOnce": "此權杖僅會顯示一次,請立即複製。" + }, "total": "總計 {{state}}", "triggered": "已觸發", "tryNumber": "嘗試次數", diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json index 32994e4f3099b..7e9e22e38141c 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json @@ -99,7 +99,7 @@ "limitedList.allTags_other": "所有標籤 ({{count}})", "limitedList.clickToInteract": "點擊標籤以篩選 Dags", "limitedList.clickToOpenFull": "點擊 \"+{{count}} 更多\" 以開啟完整檢視", - "limitedList.copyPasteText": "你可以複製並貼上上方文字", + "limitedList.copyPasteText": "您可以複製並貼上上方文字", "limitedList.showingItems_one": "顯示 1 個項目", "limitedList.showingItems_other": "顯示 {{count}} 個項目", "logs": { @@ -144,7 +144,7 @@ "title": "已觸發 Dag 執行" } }, - "triggerAgainWithConfig": "使用此配置再次觸發", + "triggerAgainWithConfig": "使用此設定再次觸發", "unpause": "觸發時取消暫停 {{dagDisplayName}}" }, "trimText": { diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dag.json index 9c6dced4c52fe..9702718cfff52 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dag.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dag.json @@ -45,7 +45,8 @@ "buttons": { "resetToLatest": "重設為最新", "toggleGroup": "切換群組狀態" - } + }, + "runTypeLegend": "執行類型圖例" }, "header": { "buttons": { diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dags.json index c55fe8367b0f7..473fecdda8262 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dags.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dags.json @@ -65,7 +65,7 @@ "future": "未來", "onlyFailed": "只清除失敗任務", "past": "過去", - "preventRunningTasks": "如果任務正在運行,則阻止重新運行", + "preventRunningTasks": "若任務正在執行中,則防止重新執行", "queueNew": "排隊新任務", "runOnLatestVersion": "執行最新套件包版本", "upstream": "上游" From b224e4c6a1e50672b834b1458fa0bcd002744eaf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:07:25 +0200 Subject: [PATCH 009/100] [v3-2-test] Fix OTel metrics lost in forked task processes (#64703) (#64720) Reset the OTel SDK's Once() guard on _METER_PROVIDER_SET_ONCE before calling set_meter_provider() in get_otel_logger(). When a forked child process re-initializes Stats (detected via PID mismatch in stats.py), the inherited Once._done = True flag prevents the new MeterProvider from being registered. The child falls back to the parent's stale provider whose PeriodicExportingMetricReader thread is dead after fork, causing task-level metrics like ti.finish to be silently dropped. The fix resets _done and _METER_PROVIDER before each set_meter_provider() call. On first initialization (no fork), _done is already False so this is a no-op. On re-initialization after fork, it allows the new provider to be set correctly. (cherry picked from commit ff77bd2f095ae3169d04024ecf8c444c3123a973) Closes: #64690 Co-authored-by: Michael Black <4128408+MichaelRBlack@users.noreply.github.com> --- .../observability/metrics/otel_logger.py | 16 +++++++ .../observability/metrics/test_otel_logger.py | 43 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/shared/observability/src/airflow_shared/observability/metrics/otel_logger.py b/shared/observability/src/airflow_shared/observability/metrics/otel_logger.py index 4b5174a3bf3ca..14726e3ecc064 100644 --- a/shared/observability/src/airflow_shared/observability/metrics/otel_logger.py +++ b/shared/observability/src/airflow_shared/observability/metrics/otel_logger.py @@ -433,6 +433,22 @@ def get_otel_logger( ) readers.append(export_to_console) + # Reset the OTel SDK's Once() guard so set_meter_provider() can succeed. + # This is necessary when get_otel_logger() is called after a process fork: + # the parent's _METER_PROVIDER_SET_ONCE._done = True is inherited by the child, + # causing set_meter_provider() to silently fail with "Overriding of current + # MeterProvider is not allowed". The child then uses the parent's stale provider + # whose PeriodicExportingMetricReader thread is dead after fork. + # On first call (no fork), _done is already False so this is a no-op. + # See: https://github.com/apache/airflow/issues/64690 + try: + import opentelemetry.metrics._internal as _metrics_internal + + _metrics_internal._METER_PROVIDER_SET_ONCE._done = False + _metrics_internal._METER_PROVIDER = None + except (ImportError, AttributeError): + pass + metrics.set_meter_provider( MeterProvider( resource=resource, diff --git a/shared/observability/tests/observability/metrics/test_otel_logger.py b/shared/observability/tests/observability/metrics/test_otel_logger.py index c27c372996968..f7b348354d7c9 100644 --- a/shared/observability/tests/observability/metrics/test_otel_logger.py +++ b/shared/observability/tests/observability/metrics/test_otel_logger.py @@ -442,7 +442,50 @@ def test_atexit_flush_on_process_exit(self): f"stderr:\n{proc.stderr}" ) + def test_reinit_after_fork_exports_metrics(self): + """Calling get_otel_logger() twice (simulating post-fork re-init) should still export metrics. + + Reproduces https://github.com/apache/airflow/issues/64690: the OTel SDK's Once() + guard on set_meter_provider() survives fork, preventing the child from setting a + fresh MeterProvider. The fix resets the guard before each set_meter_provider() call. + """ + test_module_name = "tests.observability.metrics.test_otel_logger" + function_call_str = f"import {test_module_name} as m; m.mock_service_run_reinit()" + + proc = subprocess.run( + [sys.executable, "-c", function_call_str], + check=False, + env=os.environ.copy(), + capture_output=True, + text=True, + timeout=20, + ) + + assert proc.returncode == 0, f"Process failed\nstdout:\n{proc.stdout}\nstderr:\n{proc.stderr}" + + assert "post_fork_stat" in proc.stdout, ( + "Expected 'post_fork_stat' in stdout after re-initialization but it wasn't found. " + "This suggests set_meter_provider() failed due to the Once() guard.\n" + f"stdout:\n{proc.stdout}\n" + f"stderr:\n{proc.stderr}" + ) + def mock_service_run(): logger = get_otel_logger(debug=True) logger.incr("my_test_stat") + + +def mock_service_run_reinit(): + """Simulate re-initialization after fork by calling get_otel_logger() twice. + + The first call sets the global MeterProvider and the Once() guard. + The second call simulates what happens in a forked child: stats.py detects + a PID mismatch and calls the factory again. Without the fix, the second + set_meter_provider() silently fails and the child uses a stale provider. + """ + # First init — sets Once._done = True + get_otel_logger(debug=True) + # Second init — simulates post-fork re-initialization + logger = get_otel_logger(debug=True) + logger.incr("post_fork_stat") From f67b341d7d9ffce30d405d8e03316e59b1d62d31 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 11:33:10 -0400 Subject: [PATCH 010/100] [v3-2-test] Fix #62414: Remove spurious blank lines in filtered task log download (#64235) (#64640) * Fix #62414: Remove spurious blank lines in filtered task log download When log level or source filters were applied, renderStructuredLog returned empty strings for dropped lines. Joining those with newlines still inserted blank lines, often at the start of the downloaded file. * Fix prek formatting in Logs.tsx and logDownloadContent.test.ts Reformats getLogString arrow function to stay within line length limit, and fixes object key ordering (content before continuation_token) in test fixtures to match Prettier's alphabetical sorting. (cherry picked from commit 32ac5645c9eee1ec6fb7f6693d001099aadb9c91) Co-authored-by: Bernardo Gunzburger Lopes <130933290+bennyc0de@users.noreply.github.com> --- .../ui/src/pages/TaskInstance/Logs/Logs.tsx | 5 +- .../Logs/logDownloadContent.test.ts | 131 ++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/logDownloadContent.test.ts diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx index 681a92e68e3d7..c37b1e0b0525f 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx @@ -116,7 +116,10 @@ export const Logs = () => { ); }; - const getLogString = () => getParsedLogs().join("\n"); + const getLogString = () => + getParsedLogs() + .filter((line) => line !== "") + .join("\n"); const downloadLogs = () => { const logContent = getLogString(); diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/logDownloadContent.test.ts b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/logDownloadContent.test.ts new file mode 100644 index 0000000000000..84ccfbeaddbf0 --- /dev/null +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/logDownloadContent.test.ts @@ -0,0 +1,131 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import type { TFunction } from "i18next"; +import { describe, expect, it } from "vitest"; + +import type { TaskInstancesLogResponse } from "openapi/requests/types.gen"; +import { renderStructuredLog } from "src/components/renderStructuredLog"; +import { parseStreamingLogContent } from "src/utils/logs"; + +/** Same construction as Logs.tsx getLogString (download path). */ +const logStringForDownload = ( + fetchedData: TaskInstancesLogResponse | undefined, + logLevelFilters: Array, + translate: TFunction, +) => + parseStreamingLogContent(fetchedData) + .map((line) => + renderStructuredLog({ + index: 0, + logLevelFilters, + logLink: "", + logMessage: line, + renderingMode: "text", + showSource: false, + showTimestamp: true, + sourceFilters: [], + translate, + }), + ) + .filter((line) => line !== "") + .join("\n"); + +describe("Task log download content (log level filter)", () => { + const translate = ((key: string) => key) as unknown as TFunction; + + it("is empty when every structured line is excluded by the level filter", () => { + const fetchedData: TaskInstancesLogResponse = { + content: [ + { + event: "hello", + level: "info", + logger: "task.stdout", + timestamp: "2025-09-11T17:44:52.597476Z", + }, + ], + continuation_token: null, + }; + + const text = logStringForDownload(fetchedData, ["error"], translate); + + expect(text).toBe(""); + }); + + it("is empty when structured lines have no level and any log level filter is set", () => { + const fetchedData: TaskInstancesLogResponse = { + content: [ + { + event: "[timestamp] {file.py:1} INFO - legacy line without level field", + timestamp: "2025-02-28T10:49:09.679000+05:30", + }, + ], + continuation_token: null, + }; + + const text = logStringForDownload(fetchedData, ["info"], translate); + + expect(text).toBe(""); + }); + + it("does not prefix the download with newlines when earlier lines are filtered out", () => { + const fetchedData: TaskInstancesLogResponse = { + content: [ + { + event: "hidden-group-marker", + level: "debug", + logger: "task.stdout", + timestamp: "2025-09-11T17:44:52.597476Z", + }, + { + event: "visible-line", + level: "info", + logger: "task.stdout", + timestamp: "2025-09-11T17:44:52.597500Z", + }, + ], + continuation_token: null, + }; + + const text = logStringForDownload(fetchedData, ["info"], translate); + + expect(text.startsWith("\n")).toBe(false); + expect(text).toContain("visible-line"); + expect(text).not.toContain("hidden-group-marker"); + }); + + it("includes matching structured lines when the filter matches level", () => { + const fetchedData: TaskInstancesLogResponse = { + content: [ + { + event: "hello", + level: "info", + logger: "task.stdout", + timestamp: "2025-09-11T17:44:52.597476Z", + }, + ], + continuation_token: null, + }; + + const text = logStringForDownload(fetchedData, ["info"], translate); + + expect(text.length).toBeGreaterThan(0); + expect(text).toContain("hello"); + expect(text).toContain("INFO"); + }); +}); From 1826619b1c935863163064b887f1c09dab60ceaa Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Mon, 6 Apr 2026 17:46:56 +0200 Subject: [PATCH 011/100] [v3-2-test] [main] Force building CI image on upgrade important CI environment (#64536) (#64769) * Build CI image before syncing breeze lock in version upgrades When upgrade_important_versions.py detects changed versions, force-build the CI image for Python 3.10 before running breeze's uv sync so that the lock file is generated against the updated image. * CI: Upgrade important CI environment (cherry picked from commit 152295362e53098f660c6f2bac822c2756a4d05a) --- .pre-commit-config.yaml | 2 +- contributing-docs/08_static_code_checks.rst | 16 ------- dev/breeze/doc/images/output_ci_upgrade.svg | 46 ++++++++----------- dev/breeze/doc/images/output_ci_upgrade.txt | 2 +- .../airflow_breeze/commands/ci_commands.py | 18 ++++---- .../commands/ci_commands_config.py | 1 - 6 files changed, 30 insertions(+), 55 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4d47e392fd301..5ae63005dc511 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -256,7 +256,7 @@ repos: (?x) ^\.pre-commit-config\.yaml$| ^\.github/\.pre-commit-config\.yaml$| - ^scripts/ci/prek/update_installers_and_prek\.py$ + ^scripts/ci/prek/upgrade_important_versions\.py$ pass_filenames: false require_serial: true - repo: https://github.com/adamchainz/blacken-docs diff --git a/contributing-docs/08_static_code_checks.rst b/contributing-docs/08_static_code_checks.rst index 2750cbafe5dc7..1d009b92cefb4 100644 --- a/contributing-docs/08_static_code_checks.rst +++ b/contributing-docs/08_static_code_checks.rst @@ -276,22 +276,6 @@ Most of the checks we run are configured to run automatically when you commit th there are some checks that are not run automatically and you need to run them manually. You can run them manually by running ``prek --stage manual ``. -Special pin-versions prek -------------------------- - -There is a separate prek ``pin-versions`` prek hook which is used to pin versions of -GitHub Actions in the CI workflows. - -This action requires ``GITHUB_TOKEN`` to be set, otherwise you might hit the rate limits with GitHub API, it -It is not run automatically when you commit the code but in runs as a separate job in the CI. -However, you can run it manually by running: - -.. code-block:: bash - - export GITHUB_TOKEN=YOUR_GITHUB_TOKEN - prek --all-files --stage manual --verbose pin-versions - - Mypy checks ----------- diff --git a/dev/breeze/doc/images/output_ci_upgrade.svg b/dev/breeze/doc/images/output_ci_upgrade.svg index 930f22c68e246..5370d25bff3fc 100644 --- a/dev/breeze/doc/images/output_ci_upgrade.svg +++ b/dev/breeze/doc/images/output_ci_upgrade.svg @@ -1,4 +1,4 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -84,21 +84,21 @@ - + - - Usage:airflowctl plugins [-hCOMMAND... - -Perform Plugins operations - -Positional Arguments: -COMMAND -listPerform list operation -list-import-errors -Perform list_import_errors operation - -Options: --h--helpshow this help message and exit + + Usage:airflowctl plugins [-hCOMMAND... + +Perform Plugins operations + +Positional Arguments: +COMMAND +listList all installed Airflow plugins +list-import-errors +List all plugin import errors + +Options: +-h--helpshow this help message and exit diff --git a/airflow-ctl/docs/images/output_pools.svg b/airflow-ctl/docs/images/output_pools.svg index 9423ec2d7c5dd..f30061e3deced 100644 --- a/airflow-ctl/docs/images/output_pools.svg +++ b/airflow-ctl/docs/images/output_pools.svg @@ -1,4 +1,4 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - Usage:airflowctl pools [-hCOMMAND... - -Perform Pools operations - -Positional Arguments: -COMMAND -createPerform create operation -deletePerform delete operation -exportExport all pools -getPerform get operation -importImport pools -listPerform list operation -updatePerform update operation - -Options: --h--helpshow this help message and exit + + Usage:airflowctl pools [-hCOMMAND... + +Perform Pools operations + +Positional Arguments: +COMMAND +createCreate a new pool +deleteDelete a pool by its name +exportExport all pools +getRetrieve a pool by its name +importImport pools +listList all pools +updateUpdate an existing pool + +Options: +-h--helpshow this help message and exit diff --git a/airflow-ctl/docs/images/output_providers.svg b/airflow-ctl/docs/images/output_providers.svg index ff4a2c8e4d243..f4ce50e83cd57 100644 --- a/airflow-ctl/docs/images/output_providers.svg +++ b/airflow-ctl/docs/images/output_providers.svg @@ -1,4 +1,4 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - Usage:airflowctl providers [-hCOMMAND... - -Perform Providers operations - -Positional Arguments: -COMMAND -listPerform list operation - -Options: --h--helpshow this help message and exit + + Usage:airflowctl providers [-hCOMMAND... + +Perform Providers operations + +Positional Arguments: +COMMAND +listList all installed Airflow providers + +Options: +-h--helpshow this help message and exit diff --git a/airflow-ctl/docs/images/output_variables.svg b/airflow-ctl/docs/images/output_variables.svg index 78c24d31074b6..a8833a923899d 100644 --- a/airflow-ctl/docs/images/output_variables.svg +++ b/airflow-ctl/docs/images/output_variables.svg @@ -19,69 +19,69 @@ font-weight: 700; } - .terminal-938427142-matrix { + .terminal-1391084489-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-938427142-title { + .terminal-1391084489-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-938427142-r1 { fill: #ff8700 } -.terminal-938427142-r2 { fill: #c5c8c6 } -.terminal-938427142-r3 { fill: #808080 } -.terminal-938427142-r4 { fill: #68a0b3 } + .terminal-1391084489-r1 { fill: #ff8700 } +.terminal-1391084489-r2 { fill: #c5c8c6 } +.terminal-1391084489-r3 { fill: #808080 } +.terminal-1391084489-r4 { fill: #68a0b3 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -93,24 +93,24 @@ - + - - Usage:airflowctl variables [-hCOMMAND... - -Perform Variables operations - -Positional Arguments: -COMMAND -createPerform create operation -deletePerform delete operation -getPerform get operation -importImport variables from a file exported with local CLI. -listPerform list operation -updatePerform update operation - -Options: --h--helpshow this help message and exit + + Usage:airflowctl variables [-hCOMMAND... + +Perform Variables operations + +Positional Arguments: +COMMAND +createCreate a new variable +deleteDelete a variable by its key +getRetrieve a variable by its key +importImport variables from a file exported with local CLI. +listList all variables +updateUpdate an existing variable + +Options: +-h--helpshow this help message and exit diff --git a/airflow-ctl/src/airflowctl/ctl/cli_config.py b/airflow-ctl/src/airflowctl/ctl/cli_config.py index 5f17c60335734..95fb11d03ce49 100755 --- a/airflow-ctl/src/airflowctl/ctl/cli_config.py +++ b/airflow-ctl/src/airflowctl/ctl/cli_config.py @@ -34,6 +34,7 @@ import httpx import rich +import yaml import airflowctl.api.datamodels.generated as generated_datamodels from airflowctl.api.client import NEW_API_CLIENT, Client, ClientKind, provide_api_client @@ -192,6 +193,14 @@ def string_lower_type(val): return val.strip().lower() +def _load_help_texts_yaml() -> dict[str, dict[str, str]]: + """Load the help texts yaml for the auto-generated commands.""" + help_texts_path = Path(__file__).parent / "help_texts.yaml" + with open(help_texts_path) as yaml_file: + help_texts = yaml.safe_load(yaml_file) + return help_texts + + # Common Positional Arguments ARG_FILE = Arg( flags=("file",), @@ -368,6 +377,7 @@ class CommandFactory: output_command_list: list[str] exclude_operation_names: list[str] exclude_method_names: list[str] + help_texts: dict[str, dict[str, str]] def __init__(self, file_path: str | Path | None = None): self.datamodels_extended_map = {} @@ -376,6 +386,7 @@ def __init__(self, file_path: str | Path | None = None): self.args_map = {} self.commands_map = {} self.group_commands_list = [] + self.help_texts = _load_help_texts_yaml() self.file_path = inspect.getfile(BaseOperations) if file_path is None else file_path # Excluded Lists are in Class Level for further usage and avoid searching them # Exclude parameters that are not needed for CLI from datamodels @@ -718,12 +729,15 @@ def _create_group_commands_from_operation(self): for operation in self.operations: operation_name = operation["name"] operation_group_name = operation["parent"].name + help_text = self.help_texts.get(operation_group_name.replace("Operations", "").lower(), {}).get( + operation_name.replace("_", "-") + ) if operation_group_name not in self.commands_map: self.commands_map[operation_group_name] = [] self.commands_map[operation_group_name].append( ActionCommand( name=operation["name"].replace("_", "-"), - help=f"Perform {operation_name} operation", + help=help_text, func=self.func_map[(operation_name, operation_group_name)], args=self.args_map[(operation_name, operation_group_name)], ) diff --git a/airflow-ctl/src/airflowctl/ctl/help_texts.yaml b/airflow-ctl/src/airflowctl/ctl/help_texts.yaml new file mode 100644 index 0000000000000..3dac52be0bc99 --- /dev/null +++ b/airflow-ctl/src/airflowctl/ctl/help_texts.yaml @@ -0,0 +1,102 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +--- +assets: + get: "Retrieve an asset by its ID" + get-by-alias: "Retrieve an asset by its alias" + list: "List all assets" + list-by-alias: "List all asset aliases" + create-event: "Create an event for a given asset" + materialize: "Trigger materialization of an asset by its ID" + get-queued-events: "List queued events for a given asset" + get-dag-queued-events: "List queued asset events for a given DAG" + get-dag-queued-event: "Retrieve a specific queued asset event for a given DAG and asset" + delete-queued-events: "Delete all queued events for a given asset" + delete-dag-queued-events: "Delete all queued asset events for a given DAG" + delete-queued-event: "Delete a specific queued asset event for a given DAG and asset" + +backfill: + create: "Create a backfill job for a given DAG ID and date range" + create-dry-run: "Preview a backfill job without executing it" + get: "Retrieve details of a backfill job by its ID" + list: "List all backfill jobs for a given DAG" + pause: "Pause an active backfill job" + unpause: "Resume a paused backfill job" + cancel: "Cancel a backfill job" + +config: + get: "Retrieve the value of a specific configuration option" + list: "List all configuration sections and their options" + +connections: + get: "Retrieve a connection by its ID" + list: "List all configured connections" + create: "Create a new connection" + create-defaults: "Populate default connections for installed providers" + delete: "Delete a connection by its ID" + update: "Update an existing connection" + test: "Test connectivity for a given connection" + +dags: + get: "Retrieve a DAG by its ID" + get-details: "Retrieve detailed information for a DAG" + get-tags: "List all tags used across DAGs" + list: "List all DAGs" + update: "Update properties of a DAG" + delete: "Delete a DAG by its ID" + get-import-error: "Retrieve a DAG import error by its ID" + list-import-errors: "List all DAG import errors" + get-stats: "Retrieve run statistics for one or more DAGs" + get-version: "Retrieve a specific version of a DAG" + list-version: "List all versions of a DAG" + list-warning: "List all DAG warnings" + trigger: "Trigger a new DAG run" + +dagrun: + get: "Retrieve a DAG run by DAG ID and run ID" + list: "List DAG runs, optionally filtered by state and date range" + +jobs: + list: "List scheduler, triggerer, and other Airflow jobs" + +pools: + get: "Retrieve a pool by its name" + list: "List all pools" + create: "Create a new pool" + delete: "Delete a pool by its name" + update: "Update an existing pool" + +providers: + list: "List all installed Airflow providers" + +variables: + get: "Retrieve a variable by its key" + list: "List all variables" + create: "Create a new variable" + delete: "Delete a variable by its key" + update: "Update an existing variable" + +xcom: + get: "Retrieve an XCom entry for a specific task instance" + list: "List XCom entries for a specific task instance" + add: "Add a new XCom entry for a specific task instance" + edit: "Update an existing XCom entry for a specific task instance" + delete: "Delete an XCom entry for a specific task instance" + +plugins: + list: "List all installed Airflow plugins" + list-import-errors: "List all plugin import errors" diff --git a/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py b/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py index 117f874c34651..56d3ddcd64c29 100644 --- a/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py +++ b/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py @@ -554,3 +554,22 @@ def test_apply_datamodel_defaults_other_datamodel(self): # Should return params unchanged for other datamodels assert result == params, "Params should be unchanged for non-TriggerDAGRunPostBody datamodels" + + @pytest.mark.parametrize( + ("group_name", "subcommand_name", "expected_help"), + [ + ("assets", "get", "Retrieve an asset by its ID"), + ("connections", "get", "Retrieve a connection by its ID"), + ], + ) + def test_help_texts_used_for_auto_generated_commands(self, group_name, subcommand_name, expected_help): + """Test that help texts from YAML are used for auto-generated commands.""" + command_factory = CommandFactory() + for group_command in command_factory.group_commands: + if group_command.name == group_name: + for subcommand in group_command.subcommands: + if subcommand.name == subcommand_name: + assert subcommand.help == expected_help, ( + "Help message should match the help_text.yaml" + ) + return diff --git a/scripts/ci/prek/check_airflowctl_command_coverage.py b/scripts/ci/prek/check_airflowctl_command_coverage.py index 2b808db9c006f..6ee54d369bb7d 100755 --- a/scripts/ci/prek/check_airflowctl_command_coverage.py +++ b/scripts/ci/prek/check_airflowctl_command_coverage.py @@ -28,11 +28,10 @@ from __future__ import annotations -import ast import re import sys -from common_prek_utils import AIRFLOW_ROOT_PATH, console +from common_prek_utils import AIRFLOW_ROOT_PATH, console, parse_operations OPERATIONS_FILE = AIRFLOW_ROOT_PATH / "airflow-ctl" / "src" / "airflowctl" / "api" / "operations.py" CTL_TESTS_FILE = ( @@ -74,31 +73,6 @@ } -def parse_operations() -> dict[str, list[str]]: - commands: dict[str, list[str]] = {} - - with open(OPERATIONS_FILE) as f: - tree = ast.parse(f.read(), filename=str(OPERATIONS_FILE)) - - for node in ast.walk(tree): - if isinstance(node, ast.ClassDef) and node.name.endswith("Operations"): - if node.name in EXCLUDED_OPERATION_CLASSES: - continue - - group_name = node.name.replace("Operations", "").lower() - commands[group_name] = [] - - for child in node.body: - if isinstance(child, ast.FunctionDef): - method_name = child.name - if method_name in EXCLUDED_METHODS or method_name.startswith("_"): - continue - subcommand = method_name.replace("_", "-") - commands[group_name].append(subcommand) - - return commands - - def parse_tested_commands() -> set[str]: tested: set[str] = set() @@ -117,7 +91,11 @@ def parse_tested_commands() -> set[str]: def main(): - available = parse_operations() + available = parse_operations( + operations_file=OPERATIONS_FILE, + exclude_operation_classes=EXCLUDED_OPERATION_CLASSES, + exclude_methods=EXCLUDED_METHODS, + ) tested = parse_tested_commands() missing = [] diff --git a/scripts/ci/prek/check_airflowctl_help_texts.py b/scripts/ci/prek/check_airflowctl_help_texts.py new file mode 100755 index 0000000000000..8f31e092d88a2 --- /dev/null +++ b/scripts/ci/prek/check_airflowctl_help_texts.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# /// script +# requires-python = ">=3.10,<3.11" +# dependencies = [ +# "rich>=13.6.0", +# "pyyaml>=6.0.3", +# ] +# /// +""" +Check that auto-generated airflowctl CLI commands have corresponding help texts in the help_texts.yaml file. +""" + +from __future__ import annotations + +import sys + +import yaml +from common_prek_utils import AIRFLOW_ROOT_PATH, console, parse_operations + +OPERATIONS_FILE = AIRFLOW_ROOT_PATH / "airflow-ctl" / "src" / "airflowctl" / "api" / "operations.py" +HELP_TEXTS_FILE = AIRFLOW_ROOT_PATH / "airflow-ctl" / "src" / "airflowctl" / "ctl" / "help_texts.yaml" +# Operations excluded from CLI (see cli_config.py) +EXCLUDED_OPERATION_CLASSES = {"BaseOperations", "LoginOperations", "VersionOperations"} +EXCLUDED_METHODS = { + "__init__", + "__init_subclass__", + "error", + "_check_flag_and_exit_if_server_response_error", + "bulk", + "export", +} + + +def load_help_texts_yaml() -> dict: + """Load the help texts yaml for the auto-generated commands.""" + with open(HELP_TEXTS_FILE) as yaml_file: + help_texts = yaml.safe_load(yaml_file) + return help_texts + + +def main(): + available = parse_operations( + operations_file=OPERATIONS_FILE, + exclude_operation_classes=EXCLUDED_OPERATION_CLASSES, + exclude_methods=EXCLUDED_METHODS, + ) + help_texts = load_help_texts_yaml() + missing = [] + for group, subcommands in sorted(available.items()): + for subcommand in sorted(subcommands): + help_text = help_texts.get(group, {}).get(subcommand) + if help_text is None: + missing.append(f"{group} {subcommand}") + + if missing: + console.print("[red]ERROR: Commands do not have help texts:[/]") + for cmd in missing: + console.print(f" [red]- {cmd}[/]") + console.print() + console.print("[yellow]Fix by:[/]") + console.print(f"Adding help texts to {HELP_TEXTS_FILE}") + sys.exit(1) + + total = sum(len(cmds) for cmds in available.values()) + console.print(f"[green]All {total} CLI help texts are covered [/]") + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/scripts/ci/prek/common_prek_utils.py b/scripts/ci/prek/common_prek_utils.py index c242396fc65b5..3559e523cf09d 100644 --- a/scripts/ci/prek/common_prek_utils.py +++ b/scripts/ci/prek/common_prek_utils.py @@ -519,3 +519,31 @@ def retrieve_gh_token(*, token: str | None = None, description: str, scopes: str ) sys.exit(1) return token + + +def parse_operations( + operations_file: Path, exclude_operation_classes: set, exclude_methods: set +) -> dict[str, list[str]]: + """Parse airflowctl operations file and return a mapping of CLI group names to subcommands.""" + commands: dict[str, list[str]] = {} + + with open(operations_file) as f: + tree = ast.parse(f.read(), filename=str(operations_file)) + + for node in ast.walk(tree): + if isinstance(node, ast.ClassDef) and node.name.endswith("Operations"): + if node.name in exclude_operation_classes: + continue + + group_name = node.name.replace("Operations", "").lower() + commands[group_name] = [] + + for child in node.body: + if isinstance(child, ast.FunctionDef): + method_name = child.name + if method_name in exclude_methods or method_name.startswith("_"): + continue + subcommand = method_name.replace("_", "-") + commands[group_name].append(subcommand) + + return commands From eb3896d59f5192df72c0039cbc7a982c2bd28553 Mon Sep 17 00:00:00 2001 From: Bugra Ozturk Date: Sun, 12 Apr 2026 17:15:24 +0200 Subject: [PATCH 063/100] [v3-2-test] fix(cli): change is_alive default to None in jobs list (#65065) (#65091) (cherry picked from commit 6ef5165) Co-authored-by: rjgoyln <151457491+rjgoyln@users.noreply.github.com> --- airflow-ctl/src/airflowctl/api/operations.py | 14 +++++++-- airflow-ctl/src/airflowctl/ctl/cli_config.py | 5 +-- .../tests/airflow_ctl/api/test_operations.py | 31 +++++++++++++++++++ .../tests/airflow_ctl/ctl/test_cli_config.py | 30 ++++++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/airflow-ctl/src/airflowctl/api/operations.py b/airflow-ctl/src/airflowctl/api/operations.py index 8c7b4a1408d56..2890304743b4c 100644 --- a/airflow-ctl/src/airflowctl/api/operations.py +++ b/airflow-ctl/src/airflowctl/api/operations.py @@ -642,10 +642,20 @@ class JobsOperations(BaseOperations): """Job operations.""" def list( - self, job_type: str, hostname: str, is_alive: bool + self, + job_type: str | None = None, + hostname: str | None = None, + is_alive: bool | None = None, ) -> JobCollectionResponse | ServerResponseError: """List all jobs.""" - params = {"job_type": job_type, "hostname": hostname, "is_alive": is_alive} + params: dict[str, Any] = {} + if job_type: + params["job_type"] = job_type + if hostname: + params["hostname"] = hostname + if is_alive is not None: + params["is_alive"] = is_alive + return super().execute_list(path="jobs", data_model=JobCollectionResponse, params=params) diff --git a/airflow-ctl/src/airflowctl/ctl/cli_config.py b/airflow-ctl/src/airflowctl/ctl/cli_config.py index 95fb11d03ce49..2ad55b91a0fe2 100755 --- a/airflow-ctl/src/airflowctl/ctl/cli_config.py +++ b/airflow-ctl/src/airflowctl/ctl/cli_config.py @@ -578,14 +578,15 @@ def _create_args_map_from_operation(self): for parameter in operation.get("parameters"): for parameter_key, parameter_type in parameter.items(): if self._is_primitive_type(type_name=parameter_type): - is_bool = parameter_type == "bool" + base_parameter_type = parameter_type.replace(" | None", "").strip() + is_bool = base_parameter_type == "bool" args.append( self._create_arg( arg_flags=("--" + self._sanitize_arg_parameter_key(parameter_key),), arg_type=self._python_type_from_string(parameter_type), arg_action=argparse.BooleanOptionalAction if is_bool else None, arg_help=f"{parameter_key} for {operation.get('name')} operation in {operation.get('parent').name}", - arg_default=False if is_bool else None, + arg_default=None, ) ) else: diff --git a/airflow-ctl/tests/airflow_ctl/api/test_operations.py b/airflow-ctl/tests/airflow_ctl/api/test_operations.py index 7d875054c3fbe..2f2e0b0f54738 100644 --- a/airflow-ctl/tests/airflow_ctl/api/test_operations.py +++ b/airflow-ctl/tests/airflow_ctl/api/test_operations.py @@ -1129,6 +1129,11 @@ class TestJobsOperations: def test_list(self): def handle_request(request: httpx.Request) -> httpx.Response: assert request.url.path == "/api/v2/jobs" + params = dict(request.url.params) + assert params["job_type"] == "job_type" + assert params["hostname"] == "hostname" + assert params["is_alive"] == "true" + assert params["limit"] == "50" return httpx.Response(200, json=json.loads(self.job_collection_response.model_dump_json())) client = make_api_client(transport=httpx.MockTransport(handle_request)) @@ -1139,6 +1144,32 @@ def handle_request(request: httpx.Request) -> httpx.Response: ) assert response == self.job_collection_response + @pytest.mark.parametrize( + ("job_type", "hostname", "is_alive", "expected_subset"), + [ + (None, None, None, {}), + ("scheduler", None, None, {"job_type": "scheduler"}), + (None, "host-a", None, {"hostname": "host-a"}), + (None, None, False, {"is_alive": "false"}), + ], + ) + def test_list_omits_empty_filters(self, job_type, hostname, is_alive, expected_subset): + def handle_request(request: httpx.Request) -> httpx.Response: + assert request.url.path == "/api/v2/jobs" + params = dict(request.url.params) + assert params["limit"] == "50" + for key, value in expected_subset.items(): + assert params[key] == value + + assert ("job_type" in params) is ("job_type" in expected_subset) + assert ("hostname" in params) is ("hostname" in expected_subset) + assert ("is_alive" in params) is ("is_alive" in expected_subset) + return httpx.Response(200, json=json.loads(self.job_collection_response.model_dump_json())) + + client = make_api_client(transport=httpx.MockTransport(handle_request)) + response = client.jobs.list(job_type=job_type, hostname=hostname, is_alive=is_alive) + assert response == self.job_collection_response + class TestPoolsOperations: pool_name = "pool_name" diff --git a/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py b/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py index 56d3ddcd64c29..2525b85e49faf 100644 --- a/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py +++ b/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py @@ -287,6 +287,36 @@ def delete(self, backfill_id: str) -> ServerResponseError | None: assert arg.kwargs["default"] == test_arg[1]["default"] assert arg.kwargs["type"] == test_arg[1]["type"] + def test_command_factory_optional_bool_uses_boolean_optional_action(self): + """Optional bool parameters should support --flag and --no-flag forms.""" + temp_file = "test_command.py" + self._save_temp_operations_py( + temp_file=temp_file, + file_content=""" + class JobsOperations(BaseOperations): + def list(self, is_alive: bool | None = None) -> JobCollectionResponse | ServerResponseError: + self.response = self.client.get("jobs") + return JobCollectionResponse.model_validate_json(self.response.content) + """, + ) + + command_factory = CommandFactory(file_path=temp_file) + generated_group_commands = command_factory.group_commands + + jobs_list_args = [] + for generated_group_command in generated_group_commands: + if generated_group_command.name != "jobs": + continue + for sub_command in generated_group_command.subcommands: + if sub_command.name == "list": + jobs_list_args = list(sub_command.args) + break + + is_alive_arg = next(arg for arg in jobs_list_args if arg.flags == ("--is-alive",)) + assert is_alive_arg.kwargs["action"] == BooleanOptionalAction + assert is_alive_arg.kwargs["default"] is None + assert is_alive_arg.kwargs["type"] is bool + class TestCliConfigMethods: def test_add_to_parser_drops_type_for_boolean_optional_action(self): From 98b3e0db39fd62c8767d66f1a10c1a2fdb76de8f Mon Sep 17 00:00:00 2001 From: Bugra Ozturk Date: Sun, 12 Apr 2026 17:31:55 +0200 Subject: [PATCH 064/100] sync airflowctl from main to v3-2-test (#65069) --- .../installation/installing-from-pypi.rst | 34 ++++++- airflow-ctl/pyproject.toml | 2 + airflow-ctl/src/airflowctl/api/client.py | 31 +++++-- airflow-ctl/src/airflowctl/api/operations.py | 24 +++-- .../airflowctl/ctl/commands/auth_command.py | 6 +- .../tests/airflow_ctl/api/test_client.py | 18 +++- .../tests/airflow_ctl/api/test_operations.py | 91 ++++++++++++------- .../ctl/commands/test_auth_command.py | 18 ++++ 8 files changed, 171 insertions(+), 53 deletions(-) diff --git a/airflow-ctl/docs/installation/installing-from-pypi.rst b/airflow-ctl/docs/installation/installing-from-pypi.rst index 9ec3a5e73ab84..826cbee7e957c 100644 --- a/airflow-ctl/docs/installation/installing-from-pypi.rst +++ b/airflow-ctl/docs/installation/installing-from-pypi.rst @@ -21,8 +21,38 @@ Installation from PyPI This page describes installations using the ``apache-airflow-ctl`` package `published in PyPI `__. -Installation tools -'''''''''''''''''' +Installation via ``pipx`` or ``uv`` as tool +''''''''''''''''''''''''''''''''''''''''''' + +You can locally deploy or run airflowctl without installing it in your environment using tools like `pipx `_ or `uv `_. + +Via ``pipx`` it is possible to install airflowctl directly from PyPI using the command below: + +.. code-block:: bash + + pipx install "apache-airflow-ctl==|version|" + +As well as directly run w/o installing it first: + +.. code-block:: bash + + pipx run "apache-airflow-ctl --help" + +Same via Astral ``uv`` to install airflowctl from PyPI using the command below: + +.. code-block:: bash + + uv tool install "apache-airflow-ctl==|version|" + +Additionally to jump-start using it you can also use the shortcut via ``uvx`` command and directly run it without installing it first: + +.. code-block:: bash + + uvx apache-airflow-ctl --help + + +Installation in your environment +'''''''''''''''''''''''''''''''' Only ``pip`` and ``uv`` installation is currently officially supported. diff --git a/airflow-ctl/pyproject.toml b/airflow-ctl/pyproject.toml index a14d42ecb15fd..06278d01cd602 100644 --- a/airflow-ctl/pyproject.toml +++ b/airflow-ctl/pyproject.toml @@ -67,6 +67,8 @@ YouTube = "https://www.youtube.com/channel/UCSXwxpWZQ7XZ1WL3wqevChA/" [project.scripts] airflowctl = "airflowctl.__main__:main" +# Redundant definition allowing direct execution via `uvx apache-airflow-ctl ...` +apache-airflow-ctl = "airflowctl.__main__:main" [build-system] requires = [ diff --git a/airflow-ctl/src/airflowctl/api/client.py b/airflow-ctl/src/airflowctl/api/client.py index 06e78a6a32a90..51786bfcfcbff 100644 --- a/airflow-ctl/src/airflowctl/api/client.py +++ b/airflow-ctl/src/airflowctl/api/client.py @@ -169,6 +169,11 @@ def input_cli_config_file(self) -> str: """Generate path for the CLI config file.""" return f"{self.api_environment}.json" + @staticmethod + def token_key_for_environment(api_environment: str) -> str: + """Build the keyring/debug token key for a given environment name.""" + return f"api_token_{api_environment}" + def save(self, skip_keyring: bool = False): """ Save the credentials to keyring and URL to disk as a file. @@ -186,7 +191,7 @@ def save(self, skip_keyring: bool = False): with open( os.path.join(default_config_dir, f"debug_creds_{self.input_cli_config_file}"), "w" ) as f: - json.dump({f"api_token_{self.api_environment}": self.api_token}, f) + json.dump({self.token_key_for_environment(self.api_environment): self.api_token}, f) else: if skip_keyring: return @@ -199,7 +204,11 @@ def save(self, skip_keyring: bool = False): for candidate in candidates: if hasattr(candidate, "_get_new_password"): candidate._get_new_password = _bounded_get_new_password - keyring.set_password("airflowctl", f"api_token_{self.api_environment}", self.api_token) # type: ignore[arg-type] + keyring.set_password( + "airflowctl", + self.token_key_for_environment(self.api_environment), + self.api_token, # type: ignore[arg-type] + ) except (NoKeyringError, NotImplementedError) as e: log.error(e) raise AirflowCtlKeyringException( @@ -228,13 +237,23 @@ def load(self) -> Credentials: debug_creds_path = os.path.join( default_config_dir, f"debug_creds_{self.input_cli_config_file}" ) - with open(debug_creds_path) as df: - debug_credentials = json.load(df) - self.api_token = debug_credentials.get(f"api_token_{self.api_environment}") + try: + with open(debug_creds_path) as df: + debug_credentials = json.load(df) + self.api_token = debug_credentials.get( + self.token_key_for_environment(self.api_environment) + ) + except FileNotFoundError as e: + if self.client_kind == ClientKind.CLI: + raise AirflowCtlCredentialNotFoundException( + f"Debug credentials file not found: {debug_creds_path}. " + "Set AIRFLOW_CLI_DEBUG_MODE=false or log in with debug mode enabled first." + ) from e + self.api_token = None else: try: self.api_token = keyring.get_password( - "airflowctl", f"api_token_{self.api_environment}" + "airflowctl", self.token_key_for_environment(self.api_environment) ) except ValueError as e: # Incorrect keyring password diff --git a/airflow-ctl/src/airflowctl/api/operations.py b/airflow-ctl/src/airflowctl/api/operations.py index 2890304743b4c..3ce196c10cb32 100644 --- a/airflow-ctl/src/airflowctl/api/operations.py +++ b/airflow-ctl/src/airflowctl/api/operations.py @@ -195,6 +195,9 @@ def __init_subclass__(cls, **kwargs): setattr(cls, attr, _check_flag_and_exit_if_server_response_error(value)) def execute_list(self, *, path, data_model, offset=0, limit=50, params=None): + if limit <= 0: + raise ValueError(f"limit must be a positive integer, got {limit}") + shared_params = {"limit": limit, **(params or {})} def safe_validate(content: bytes) -> BaseModel: @@ -610,32 +613,33 @@ def list( dag_id: str | None = None, ) -> DAGRunCollectionResponse | ServerResponseError: """ - List all dag runs. + List dag runs (at most `limit` results). Args: state: Filter dag runs by state start_date: Filter dag runs by start date (optional) end_date: Filter dag runs by end date (optional) - state: Filter dag runs by state - limit: Limit the number of results + limit: Limit the number of results returned dag_id: The DAG ID to filter by. If None, retrieves dag runs for all DAGs (using "~"). """ # Use "~" for all DAGs if dag_id is not specified if not dag_id: dag_id = "~" - params: dict[str, object] = { - "state": state, + params: dict[str, Any] = { + "state": str(state), "limit": limit, } if start_date is not None: - params["start_date"] = start_date + params["start_date"] = start_date.isoformat() if end_date is not None: - params["end_date"] = end_date + params["end_date"] = end_date.isoformat() - return super().execute_list( - path=f"/dags/{dag_id}/dagRuns", data_model=DAGRunCollectionResponse, params=params - ) + try: + self.response = self.client.get(f"/dags/{dag_id}/dagRuns", params=params) + return DAGRunCollectionResponse.model_validate_json(self.response.content) + except ServerResponseError as e: + raise e class JobsOperations(BaseOperations): diff --git a/airflow-ctl/src/airflowctl/ctl/commands/auth_command.py b/airflow-ctl/src/airflowctl/ctl/commands/auth_command.py index 236b8d5c6b8de..cf521cbe7eea0 100644 --- a/airflow-ctl/src/airflowctl/ctl/commands/auth_command.py +++ b/airflow-ctl/src/airflowctl/ctl/commands/auth_command.py @@ -144,7 +144,7 @@ def list_envs(args) -> None: if filename.startswith("debug_creds_") or filename.endswith("_generated.json"): continue - env_name = filename.replace(".json", "") + env_name, _ = os.path.splitext(filename) # Try to read config file api_url = None @@ -168,11 +168,11 @@ def list_envs(args) -> None: if os.path.exists(debug_path): with open(debug_path) as f: debug_creds = json.load(f) - if f"api_token_{env_name}" in debug_creds: + if Credentials.token_key_for_environment(env_name) in debug_creds: token_status = "authenticated" else: # Check keyring - token = keyring.get_password("airflowctl", f"api_token_{env_name}") + token = keyring.get_password("airflowctl", Credentials.token_key_for_environment(env_name)) if token: token_status = "authenticated" except NoKeyringError: diff --git a/airflow-ctl/tests/airflow_ctl/api/test_client.py b/airflow-ctl/tests/airflow_ctl/api/test_client.py index 0617d62276a1c..f495b357d8d4b 100644 --- a/airflow-ctl/tests/airflow_ctl/api/test_client.py +++ b/airflow-ctl/tests/airflow_ctl/api/test_client.py @@ -30,7 +30,10 @@ from airflowctl.api.client import Client, ClientKind, Credentials, _bounded_get_new_password from airflowctl.api.operations import ServerResponseError -from airflowctl.exceptions import AirflowCtlCredentialNotFoundException, AirflowCtlKeyringException +from airflowctl.exceptions import ( + AirflowCtlCredentialNotFoundException, + AirflowCtlKeyringException, +) def make_client_w_responses(responses: list[httpx.Response]) -> Client: @@ -376,3 +379,16 @@ def test_retry_handling_ok(self): response = client.get("http://error") assert response.status_code == 200 assert len(responses) == 1 + + def test_debug_mode_missing_debug_creds_reports_correct_error(self, monkeypatch, tmp_path): + monkeypatch.setenv("AIRFLOW_HOME", str(tmp_path)) + monkeypatch.setenv("AIRFLOW_CLI_DEBUG_MODE", "true") + monkeypatch.setenv("AIRFLOW_CLI_ENVIRONMENT", "TEST_DEBUG") + + config_path = tmp_path / "TEST_DEBUG.json" + config_path.write_text(json.dumps({"api_url": "http://localhost:8080"}), encoding="utf-8") + # Intentionally do not create debug_creds_TEST_DEBUG.json to simulate a missing file + + creds = Credentials(client_kind=ClientKind.CLI, api_environment="TEST_DEBUG") + with pytest.raises(AirflowCtlCredentialNotFoundException, match="Debug credentials file not found"): + creds.load() diff --git a/airflow-ctl/tests/airflow_ctl/api/test_operations.py b/airflow-ctl/tests/airflow_ctl/api/test_operations.py index 2f2e0b0f54738..aa559f174214b 100644 --- a/airflow-ctl/tests/airflow_ctl/api/test_operations.py +++ b/airflow-ctl/tests/airflow_ctl/api/test_operations.py @@ -230,6 +230,16 @@ def test_execute_list_sends_limit_on_subsequent_pages(self): for call in mock_client.get.call_args_list: assert call.kwargs["params"]["limit"] == 2 + @pytest.mark.parametrize("limit", [0, -1]) + def test_execute_list_rejects_non_positive_limit(self, limit): + mock_client = Mock() + base_operation = BaseOperations(client=mock_client) + + with pytest.raises(ValueError, match="limit must be a positive integer"): + base_operation.execute_list(path="hello", data_model=HelloCollectionResponse, limit=limit) + + mock_client.get.assert_not_called() + class TestAssetsOperations: asset_id: int = 1 @@ -1068,44 +1078,63 @@ def handle_request(request: httpx.Request) -> httpx.Response: ) assert response == self.dag_run_collection_response - def test_list_all_dags(self): - """Test listing dag runs for all DAGs using default dag_id='~'.""" - - def handle_request(request: httpx.Request) -> httpx.Response: - # When dag_id is "~", it should query all DAGs - assert request.url.path == "/api/v2/dags/~/dagRuns" + @pytest.mark.parametrize( + ( + "dag_id_input", + "state", + "limit", + "start_date", + "end_date", + "expected_path_suffix", + "expected_params_subset", + ), + [ + # Test --limit with various values and configurations (covers CLI --limit flag) + ("dag1", "queued", 5, None, None, "dag1", {"state": "queued", "limit": "5"}), + (None, "running", 1, None, None, "~", {"state": "running", "limit": "1"}), + ( + "example_dag", + "success", + 10, + None, + None, + "example_dag", + {"state": "success", "limit": "10"}, + ), + ("dag2", "failed", 0, None, None, "dag2", {"state": "failed", "limit": "0"}), + ], + ids=["limit-5", "all-dags-limit-1", "string-state-limit-10", "limit-zero"], + ) + def test_list_with_various_limits( + self, + dag_id_input: str | None, + state: str | DagRunState, + limit: int, + start_date: datetime.datetime | None, + end_date: datetime.datetime | None, + expected_path_suffix: str, + expected_params_subset: dict, + ) -> None: + """Test listing dag runs with various limit values (especially --limit flag).""" + + def handle_request(request: httpx.Request) -> httpx.Response: + assert request.url.path.endswith(f"/dags/{expected_path_suffix}/dagRuns") + params = dict(request.url.params) + for key, value in expected_params_subset.items(): + assert key in params + assert str(params[key]) == str(value) return httpx.Response(200, json=json.loads(self.dag_run_collection_response.model_dump_json())) client = make_api_client(transport=httpx.MockTransport(handle_request)) - # Call without specifying dag_id - should use default "~" response = client.dag_runs.list( - start_date=datetime.datetime(2025, 1, 1, 0, 0, 0), - end_date=datetime.datetime(2025, 1, 1, 0, 0, 0), - state="running", - limit=1, + state=state, + limit=limit, + start_date=start_date, + end_date=end_date, + dag_id=dag_id_input, ) assert response == self.dag_run_collection_response - def test_list_with_optional_parameters(self): - """Test listing dag runs with only some optional parameters.""" - - def handle_request(request: httpx.Request) -> httpx.Response: - assert request.url.path == "/api/v2/dags/dag1/dagRuns" - # Verify that only state and limit are in query params - params = dict(request.url.params) - assert "state" in params - assert params["state"] == "queued" - assert "limit" in params - assert params["limit"] == "5" - # start_date and end_date should not be present - assert "start_date" not in params - assert "end_date" not in params - return httpx.Response(200, json=json.loads(self.dag_run_collection_response.model_dump_json())) - - client = make_api_client(transport=httpx.MockTransport(handle_request)) - response = client.dag_runs.list(state="queued", limit=5, dag_id="dag1") - assert response == self.dag_run_collection_response - class TestJobsOperations: job_response = JobResponse( diff --git a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py index e76fafc28adf9..2bda56b0fdc18 100644 --- a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py +++ b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py @@ -477,3 +477,21 @@ def test_list_envs_filters_special_files(self, monkeypatch): # Only production environment should be checked, not the special files mock_get_password.assert_called_once_with("airflowctl", "api_token_production") + + def test_list_envs_environment_name_with_json_substring(self, monkeypatch): + """Test list-envs keeps '.json' substrings in environment name for key lookup.""" + with ( + tempfile.TemporaryDirectory() as temp_airflow_home, + patch("keyring.get_password") as mock_get_password, + ): + monkeypatch.setenv("AIRFLOW_HOME", temp_airflow_home) + + with open(os.path.join(temp_airflow_home, "prod.json.region.json"), "w") as f: + json.dump({"api_url": "http://localhost:8080"}, f) + + mock_get_password.return_value = "test_token" + + args = self.parser.parse_args(["auth", "list-envs"]) + auth_command.list_envs(args) + + mock_get_password.assert_called_once_with("airflowctl", "api_token_prod.json.region") From e86585dd5cd5f3d1c07c9c9b3b39b51ddce7f840 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Apr 2026 17:57:40 +0200 Subject: [PATCH 065/100] [v3-2-test] Trigger unit tests when only shared/*.py files change (#64999) (#65094) Add shared/*.py pattern to ALL_SOURCE_FILES so changes that only touch the shared libraries (e.g., shared/timezones, shared/logging) trigger the unit test suite. Previously such changes were missed by selective checks because the shared/ folder was not part of the source files patterns, leading to skipped tests for changes that affect symlinked code in airflow-core, task-sdk, and providers. (cherry picked from commit f13b71371da3ae1ee5bb0b60d48fe535fa0abb26) Co-authored-by: Jarek Potiuk --- .../src/airflow_breeze/utils/selective_checks.py | 1 + dev/breeze/tests/test_selective_checks.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py b/dev/breeze/src/airflow_breeze/utils/selective_checks.py index 6a756289db649..19506d490b6a5 100644 --- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py +++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py @@ -302,6 +302,7 @@ def __hash__(self): r"^chart/templates/.*", r"^providers/.*/src/.*", r"^providers/.*/tests/.*", + r"^shared/.*\.py$", r"^task-sdk/src/.*", r"^task-sdk/tests/.*", r"^devel-common/src/.*", diff --git a/dev/breeze/tests/test_selective_checks.py b/dev/breeze/tests/test_selective_checks.py index 90e5551ce3377..3838f779e4c2d 100644 --- a/dev/breeze/tests/test_selective_checks.py +++ b/dev/breeze/tests/test_selective_checks.py @@ -1297,6 +1297,16 @@ def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str): id="Shared logging library changes enable both remote logging e2e jobs", ) ), + ( + pytest.param( + ("shared/timezones/src/airflow_shared/timezones/timezone.py",), + { + "ci-image-build": "true", + "run-unit-tests": "true", + }, + id="Shared library python changes trigger unit tests", + ) + ), ], ) def test_expected_output_pull_request_main( From 8e55051fc55cb669766071ce9ba1c4000286658c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Apr 2026 18:43:34 +0200 Subject: [PATCH 066/100] [v3-2-test] Prevent path traversal via AIRFLOW_CLI_ENVIRONMENT in airflowctl (#64618) (#65096) * replace by target.is_relative_to(base) * Update airflow-ctl/tests/airflow_ctl/api/test_client.py * fix(cli): add path traversal protection and improve exception handling --------- (cherry picked from commit eae5f754463dff63ef2a87d3049e871cf837362a) Co-authored-by: rjgoyln <151457491+rjgoyln@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- airflow-ctl/src/airflowctl/api/client.py | 36 +++++++++++++++---- .../tests/airflow_ctl/api/test_client.py | 19 ++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/airflow-ctl/src/airflowctl/api/client.py b/airflow-ctl/src/airflowctl/api/client.py index 51786bfcfcbff..f3ca3f673f119 100644 --- a/airflow-ctl/src/airflowctl/api/client.py +++ b/airflow-ctl/src/airflowctl/api/client.py @@ -26,6 +26,7 @@ import sys from collections.abc import Callable from functools import wraps +from pathlib import Path from typing import TYPE_CHECKING, Any, Literal, ParamSpec, TypeVar, cast import httpx @@ -62,6 +63,7 @@ ) from airflowctl.exceptions import ( AirflowCtlCredentialNotFoundException, + AirflowCtlException, AirflowCtlKeyringException, AirflowCtlNotFoundException, ) @@ -144,6 +146,17 @@ def _bounded_get_new_password() -> str: ) +def _safe_path_under_airflow_home(airflow_home: str, filename: str) -> str: + base = Path(airflow_home).resolve() + target = (base / filename).resolve() + if not target.is_relative_to(base): + raise AirflowCtlException( + f"Security Error: Path traversal detected in '{filename}'. " + f"The resolved path must stay within AIRFLOW_HOME." + ) + return str(target) + + # Credentials for the API class Credentials: """Credentials for the API.""" @@ -161,8 +174,15 @@ def __init__( ): self.api_url = api_url self.api_token = api_token - self.api_environment = os.getenv("AIRFLOW_CLI_ENVIRONMENT") or api_environment self.client_kind = client_kind + raw_env = os.getenv("AIRFLOW_CLI_ENVIRONMENT") or api_environment + if "/" in raw_env or "\\" in raw_env or ".." in raw_env: + raise AirflowCtlException( + f"Invalid environment name: '{raw_env}'. " + f"Environment names cannot contain path separators ('/', '\\') or '..'." + ) + + self.api_environment = raw_env @property def input_cli_config_file(self) -> str: @@ -183,14 +203,16 @@ def save(self, skip_keyring: bool = False): """ default_config_dir = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow")) os.makedirs(default_config_dir, exist_ok=True) - with open(os.path.join(default_config_dir, self.input_cli_config_file), "w") as f: + config_path = _safe_path_under_airflow_home(default_config_dir, self.input_cli_config_file) + with open(config_path, "w") as f: json.dump({"api_url": self.api_url}, f) try: if os.getenv("AIRFLOW_CLI_DEBUG_MODE") == "true": - with open( - os.path.join(default_config_dir, f"debug_creds_{self.input_cli_config_file}"), "w" - ) as f: + debug_path = _safe_path_under_airflow_home( + default_config_dir, f"debug_creds_{self.input_cli_config_file}" + ) + with open(debug_path, "w") as f: json.dump({self.token_key_for_environment(self.api_environment): self.api_token}, f) else: if skip_keyring: @@ -226,7 +248,7 @@ def save(self, skip_keyring: bool = False): def load(self) -> Credentials: """Load the credentials from keyring and URL from disk file.""" default_config_dir = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow")) - config_path = os.path.join(default_config_dir, self.input_cli_config_file) + config_path = _safe_path_under_airflow_home(default_config_dir, self.input_cli_config_file) try: with open(config_path) as f: credentials = json.load(f) @@ -234,7 +256,7 @@ def load(self) -> Credentials: if self.api_token is not None: return self if os.getenv("AIRFLOW_CLI_DEBUG_MODE") == "true": - debug_creds_path = os.path.join( + debug_creds_path = _safe_path_under_airflow_home( default_config_dir, f"debug_creds_{self.input_cli_config_file}" ) try: diff --git a/airflow-ctl/tests/airflow_ctl/api/test_client.py b/airflow-ctl/tests/airflow_ctl/api/test_client.py index f495b357d8d4b..f2d216fcc82fb 100644 --- a/airflow-ctl/tests/airflow_ctl/api/test_client.py +++ b/airflow-ctl/tests/airflow_ctl/api/test_client.py @@ -32,6 +32,7 @@ from airflowctl.api.operations import ServerResponseError from airflowctl.exceptions import ( AirflowCtlCredentialNotFoundException, + AirflowCtlException, AirflowCtlKeyringException, ) @@ -392,3 +393,21 @@ def test_debug_mode_missing_debug_creds_reports_correct_error(self, monkeypatch, creds = Credentials(client_kind=ClientKind.CLI, api_environment="TEST_DEBUG") with pytest.raises(AirflowCtlCredentialNotFoundException, match="Debug credentials file not found"): creds.load() + + +def test_credentials_accepts_safe_env(): + creds = Credentials(client_kind=ClientKind.CLI, api_environment="prod-us_1") + assert creds.api_environment == "prod-us_1" + + +@pytest.mark.parametrize("api_environment", ["../evil", "..\\evil", "a/b", "a\\b"]) +def test_credentials_rejects_unsafe_env_argument(api_environment): + with pytest.raises(AirflowCtlException, match="environment"): + Credentials(client_kind=ClientKind.CLI, api_environment=api_environment) + + +@pytest.mark.parametrize("api_environment", ["../evil", "..\\evil", "a/b", "a\\b"]) +def test_credentials_rejects_unsafe_env_from_environment_variable(monkeypatch, api_environment): + monkeypatch.setenv("AIRFLOW_CLI_ENVIRONMENT", api_environment) + with pytest.raises(AirflowCtlException, match="environment"): + Credentials(client_kind=ClientKind.CLI) From 27324ce7e5c16486373bcdbc4a3772662abab144 Mon Sep 17 00:00:00 2001 From: Bugra Ozturk Date: Sun, 12 Apr 2026 19:06:28 +0200 Subject: [PATCH 067/100] [v3-2-test] Fix CLI error handling and exit codes for failed commands (#65052) (#65097) (cherry picked from commit 9f8678a) Co-authored-by: rjgoyln <151457491+rjgoyln@users.noreply.github.com> --- airflow-ctl/src/airflowctl/ctl/cli_config.py | 6 +- .../tests/airflow_ctl/ctl/test_cli_config.py | 66 +++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/airflow-ctl/src/airflowctl/ctl/cli_config.py b/airflow-ctl/src/airflowctl/ctl/cli_config.py index 2ad55b91a0fe2..466ee671b61b2 100755 --- a/airflow-ctl/src/airflowctl/ctl/cli_config.py +++ b/airflow-ctl/src/airflowctl/ctl/cli_config.py @@ -25,6 +25,7 @@ import datetime import inspect import os +import sys from argparse import Namespace from collections.abc import Callable, Iterable from enum import Enum @@ -65,8 +66,6 @@ def command(*args, **kwargs): def safe_call_command(function: Callable, args: Iterable[Arg]) -> None: - import sys - if os.getenv("AIRFLOW_CLI_DEBUG_MODE") == "true": rich.print( "[yellow]Debug mode is enabled. Please be aware that your credentials are not secure.\n" @@ -91,10 +90,12 @@ def safe_call_command(function: Callable, args: Iterable[Arg]) -> None: f"[red]Server response error: {e}. " "Please check if the server is running and the API URL is correct.[/red]" ) + sys.exit(1) except httpx.ReadTimeout as e: rich.print(f"[red]Read timeout error: {e}[/red]") if "timed out" in str(e): rich.print("[red]Please check if the server is running and the API ready to accept calls.[/red]") + sys.exit(1) except ServerResponseError as e: rich.print(f"Server response error: {e}") if "Client error message:" in str(e): @@ -103,6 +104,7 @@ def safe_call_command(function: Callable, args: Iterable[Arg]) -> None: "Please check the command and its parameters. " "If you need help, run the command with --help." ) + sys.exit(1) class DefaultHelpParser(argparse.ArgumentParser): diff --git a/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py b/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py index 2525b85e49faf..e0278cd7c5348 100644 --- a/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py +++ b/airflow-ctl/tests/airflow_ctl/ctl/test_cli_config.py @@ -21,8 +21,10 @@ from argparse import BooleanOptionalAction from textwrap import dedent +import httpx import pytest +from airflowctl.api.operations import ServerResponseError from airflowctl.ctl.cli_config import ( ARG_AUTH_TOKEN, ActionCommand, @@ -31,6 +33,13 @@ GroupCommand, add_auth_token_to_all_commands, merge_commands, + safe_call_command, +) +from airflowctl.exceptions import ( + AirflowCtlConnectionException, + AirflowCtlCredentialNotFoundException, + AirflowCtlKeyringException, + AirflowCtlNotFoundException, ) @@ -319,6 +328,63 @@ def list(self, is_alive: bool | None = None) -> JobCollectionResponse | ServerRe class TestCliConfigMethods: + @pytest.mark.parametrize( + "raised_exception", + [ + AirflowCtlCredentialNotFoundException("missing credentials"), + AirflowCtlConnectionException("connection failed"), + AirflowCtlKeyringException("keyring failure"), + AirflowCtlNotFoundException("resource not found"), + ], + ids=["credential-not-found", "connection-error", "keyring-error", "not-found"], + ) + def test_safe_call_command_exits_non_zero_for_airflowctl_exceptions(self, raised_exception): + def raise_error(_args): + raise raised_exception + + with pytest.raises(SystemExit) as ctx: + safe_call_command(raise_error, args=argparse.Namespace()) + + assert ctx.value.code == 1 + + @pytest.mark.parametrize( + "raised_exception", + [ + httpx.RemoteProtocolError("remote protocol error"), + httpx.ReadError("read error"), + ], + ids=["remote-protocol-error", "read-error"], + ) + def test_safe_call_command_exits_non_zero_for_httpx_protocol_errors(self, raised_exception): + def raise_error(_args): + raise raised_exception + + with pytest.raises(SystemExit) as ctx: + safe_call_command(raise_error, args=argparse.Namespace()) + + assert ctx.value.code == 1 + + def test_safe_call_command_exits_non_zero_for_httpx_read_timeout(self): + def raise_error(_args): + raise httpx.ReadTimeout("timed out") + + with pytest.raises(SystemExit) as ctx: + safe_call_command(raise_error, args=argparse.Namespace()) + + assert ctx.value.code == 1 + + def test_safe_call_command_exits_non_zero_for_server_response_error(self): + request = httpx.Request("GET", "http://localhost:8080/api/v2/dags") + response = httpx.Response(500, request=request, json={"detail": "boom"}) + + def raise_error(_args): + raise ServerResponseError("server error", request=request, response=response) + + with pytest.raises(SystemExit) as ctx: + safe_call_command(raise_error, args=argparse.Namespace()) + + assert ctx.value.code == 1 + def test_add_to_parser_drops_type_for_boolean_optional_action(self): """Test add_to_parser removes type for BooleanOptionalAction.""" parser = argparse.ArgumentParser() From 8ff94bfcd9fc84993700f4d8f25d14bbf9fbcb47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 02:36:19 +0200 Subject: [PATCH 068/100] Bump aws-actions/configure-aws-credentials (#65023) Bumps the github-actions-updates group with 1 update: [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials). Updates `aws-actions/configure-aws-credentials` from 6.0.0 to 6.1.0 - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/8df5847569e6427dd6c4fb1cf565c83acfa8afa7...ec61189d14ec14c8efccab744f656cffd0e33f37) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-image-checks.yml | 2 +- .github/workflows/publish-docs-to-s3.yml | 2 +- .github/workflows/registry-backfill.yml | 4 ++-- .github/workflows/registry-build.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-image-checks.yml b/.github/workflows/ci-image-checks.yml index 1f25943204179..6b30ceec54e97 100644 --- a/.github/workflows/ci-image-checks.yml +++ b/.github/workflows/ci-image-checks.yml @@ -439,7 +439,7 @@ jobs: inputs.canary-run == 'true' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-access-key-id: ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/publish-docs-to-s3.yml b/.github/workflows/publish-docs-to-s3.yml index 165774c57abd8..3296482366cc7 100644 --- a/.github/workflows/publish-docs-to-s3.yml +++ b/.github/workflows/publish-docs-to-s3.yml @@ -397,7 +397,7 @@ jobs: sudo /tmp/aws/install --update rm -rf /tmp/aws/ - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-access-key-id: ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/registry-backfill.yml b/.github/workflows/registry-backfill.yml index a421ee4680a3d..2e1d089e967a2 100644 --- a/.github/workflows/registry-backfill.yml +++ b/.github/workflows/registry-backfill.yml @@ -136,7 +136,7 @@ jobs: rm -rf /tmp/aws/ - name: "Configure AWS credentials" - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-access-key-id: ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }} @@ -252,7 +252,7 @@ jobs: rm -rf /tmp/aws/ - name: "Configure AWS credentials" - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-access-key-id: ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/registry-build.yml b/.github/workflows/registry-build.yml index 50ab3dbb874b3..fe4655cf30f01 100644 --- a/.github/workflows/registry-build.yml +++ b/.github/workflows/registry-build.yml @@ -133,7 +133,7 @@ jobs: rm -rf /tmp/aws/ - name: "Configure AWS credentials" - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-access-key-id: ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }} From 8fc8caaed1dc8da28d5b833ffd1e22d542dc8d55 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 10:18:30 +0300 Subject: [PATCH 069/100] [v3-2-test] Remove breeze k8s configure-k8s-cluster (#65088) (#65117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 9bbac9d789cc2084c680762be91020ae59df3155) Co-authored-by: Przemysław Mirowski <17602603+Miretpl@users.noreply.github.com> --- .../commands/kubernetes_commands_config.py | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py b/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py index 4a048949be882..fcabbbcba93c1 100644 --- a/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py +++ b/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py @@ -131,27 +131,6 @@ ], }, ], - "breeze k8s configure-k8s-cluster": [ - { - "name": "Configure cluster flags", - "options": [ - "--python", - "--kubernetes-version", - ], - }, - { - "name": "Parallel options", - "options": [ - "--run-in-parallel", - "--parallelism", - "--python-versions", - "--kubernetes-versions", - "--skip-cleanup", - "--debug-resources", - "--include-success-outputs", - ], - }, - ], "breeze k8s deploy-airflow": [ { "name": "Airflow deploy flags", From d563d69e41f46b655d6cd4da0ee53d17ada65ebf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:08:20 +0200 Subject: [PATCH 070/100] [v3-2-test] Speed up Publish Docs to S3 workflow with main CI image cache (#65108) (#65144) The `build-docs` job in `publish-docs-to-s3.yml` was rebuilding the CI image from scratch because it never logged in to ghcr.io, so Buildx could not reach the registry cache tag pushed by the main "Test" workflow. The manual `docker buildx build` fallback also had no `--cache-from`, and a hardcoded `python3.9` tag that no longer matched the Python version used for the docs build. Add a `docker login ghcr.io` step, set `DOCKER_CACHE=registry` and `PYTHON_MAJOR_MINOR_VERSION` explicitly, and grant `packages: read` on the job so `breeze ci-image build` consumes the same `:cache-` tag that `push-image-cache.yml` publishes from main. Fix the stale python tag in the fallback and refresh the comments that still claimed the job "will not use cache". (cherry picked from commit f3843d969bc3d22c937773a3b21b7a8617f6560c) Co-authored-by: Jarek Potiuk --- .github/workflows/publish-docs-to-s3.yml | 28 +++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/.github/workflows/publish-docs-to-s3.yml b/.github/workflows/publish-docs-to-s3.yml index 3296482366cc7..4e0ce4d260dbf 100644 --- a/.github/workflows/publish-docs-to-s3.yml +++ b/.github/workflows/publish-docs-to-s3.yml @@ -185,6 +185,9 @@ jobs: timeout-minutes: 150 name: "Build documentation" runs-on: ubuntu-latest + permissions: + contents: read + packages: read env: GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -193,6 +196,8 @@ jobs: VERBOSE: "true" EXTRA_BUILD_OPTIONS: ${{ needs.build-info.outputs.extra-build-options }} APPLY_COMMITS: ${{ inputs.apply-commits || '' }} + PYTHON_MAJOR_MINOR_VERSION: "${{ needs.build-info.outputs.default-python-version }}" + DOCKER_CACHE: "registry" steps: - name: "Cleanup repo" shell: bash @@ -211,9 +216,10 @@ jobs: run: ./current-version/scripts/ci/move_docker_to_mnt.sh - name: "Copy the version retrieval script" run: cp ./current-version/scripts/ci/docs/store_stable_versions.py /tmp/store_stable_versions.py - # We are checking repo for both - breeze and docs from the ref provided as input - # This will take longer as we need to rebuild CI image and it will not use cache - # but it will build the CI image from the version of Airflow that is used to check out things + # We check out repo for both - breeze and docs from the ref provided as input, so the CI + # image is built from the version of Airflow matching the docs. The build uses the + # registry buildx cache pushed by the last "main" Test workflow so that layer rebuilds + # are avoided whenever the ref is close enough to main for the cache to apply. - name: "Checkout ${{ inputs.ref }} " uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -241,14 +247,20 @@ jobs: uses: ./.github/actions/breeze with: python-version: "${{ needs.build-info.outputs.default-python-version }}" + - name: "Login to ghcr.io" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ACTOR: ${{ github.actor }} + run: echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${ACTOR}" --password-stdin - name: "Building image from the ${{ inputs.ref }} reference" env: INCLUDE_DOCS: ${{ needs.build-info.outputs.include-docs }} INCLUDE_COMMITS: ${{ startsWith(inputs.ref, 'providers') && 'true' || 'false' }} - # if the regular breeze ci-image build fails, we will try to build the image using docker buildx - # This is needed for the case when we are building an old image which tries to use main as - # a cache and it fails because the main branch has changed and does not have the same pyproject.toml - # Structure as the one we are trying to build. + # The regular `breeze ci-image build` path uses the registry cache pushed by the last + # successful "main" Test workflow (DOCKER_CACHE=registry, --cache-from=
:cache-), + # which is the fast path for builds from main or main-like refs. When building from an old + # ref whose pyproject.toml has diverged from main, reusing the main cache can fail the build, + # so we fall back to a plain buildx build with no cache-from. run: > breeze ci-image build || docker buildx build --load --builder default --progress=auto --pull @@ -256,7 +268,7 @@ jobs: --build-arg AIRFLOW_USE_UV=true --build-arg BUILD_PROGRESS=auto --build-arg INSTALL_MYSQL_CLIENT_TYPE=mariadb --build-arg VERSION_SUFFIX_FOR_PYPI=dev0 - -t ghcr.io/apache/airflow/main/ci/python3.9:latest --target main . + -t "ghcr.io/apache/airflow/main/ci/python${PYTHON_MAJOR_MINOR_VERSION}:latest" --target main . -f Dockerfile.ci --platform linux/amd64 - name: "Restore docs inventory cache" uses: apache/infrastructure-actions/stash/restore@1c35b5ccf8fba5d4c3fdf25a045ca91aa0cbc468 From 02f5c1374771243057f3c2c44553d87a3a5bffd6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:08:38 +0200 Subject: [PATCH 071/100] [v3-2-test] Fix E2E Flaky Tests Report failing with gh api 404 (#65120) (#65157) scripts/ci/analyze_e2e_flaky_tests.py builds 'gh api -f key=val ...' to list workflow runs. The gh CLI defaults to POST whenever -f parameters are present, so the workflow runs endpoint returned 'Not Found (HTTP 404)' and the script wrote no output file, causing the downstream slack-github-action step to crash with ENOENT on slack-message.json. Force --method GET in the gh_api helper and add a regression test. (cherry picked from commit 7ae29fb783593e6ec1f25a8864bd25b26c172670) Co-authored-by: Jarek Potiuk --- scripts/ci/analyze_e2e_flaky_tests.py | 9 +++++++-- scripts/tests/ci/test_analyze_e2e_flaky_tests.py | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/scripts/ci/analyze_e2e_flaky_tests.py b/scripts/ci/analyze_e2e_flaky_tests.py index bf5aef53ffadb..c56fb7e48ebfc 100755 --- a/scripts/ci/analyze_e2e_flaky_tests.py +++ b/scripts/ci/analyze_e2e_flaky_tests.py @@ -65,8 +65,13 @@ def escape_slack_mrkdwn(text: str) -> str: def gh_api(endpoint: str, **kwargs: str) -> str | None: - """Call GitHub API via gh CLI.""" - cmd = ["gh", "api", endpoint] + """Call GitHub API via gh CLI. + + Forces ``--method GET``: ``gh api`` defaults to POST whenever ``-f`` + parameters are present, which makes read-only endpoints (such as the + workflow runs list) return 404. + """ + cmd = ["gh", "api", "--method", "GET", endpoint] for key, value in kwargs.items(): cmd.extend(["-f", f"{key}={value}"]) result = subprocess.run(cmd, capture_output=True, text=True, check=False) diff --git a/scripts/tests/ci/test_analyze_e2e_flaky_tests.py b/scripts/tests/ci/test_analyze_e2e_flaky_tests.py index ff7097c7aeeca..fcd56d15adae7 100644 --- a/scripts/tests/ci/test_analyze_e2e_flaky_tests.py +++ b/scripts/tests/ci/test_analyze_e2e_flaky_tests.py @@ -17,8 +17,10 @@ from __future__ import annotations import importlib.util +import subprocess import sys from pathlib import Path +from unittest.mock import patch import pytest @@ -37,6 +39,17 @@ def analyze_module(): return module +class TestGhApi: + def test_forces_get_method(self, analyze_module): + """`gh api` defaults to POST when -f is passed; we must force GET to avoid 404.""" + completed = subprocess.CompletedProcess(args=[], returncode=0, stdout="{}", stderr="") + with patch.object(subprocess, "run", return_value=completed) as mock_run: + analyze_module.gh_api("repos/apache/airflow/actions/workflows/x/runs", branch="main") + args = mock_run.call_args[0][0] + assert "--method" in args + assert args[args.index("--method") + 1] == "GET" + + class TestEscapeSlackMrkdwn: def test_escapes_ampersand(self, analyze_module): assert analyze_module.escape_slack_mrkdwn("a & b") == "a & b" From f92d22b803d0b2eea9e3adf28533026de261ec5d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:09:05 +0200 Subject: [PATCH 072/100] [v3-2-test] Expose queueing/scheduled time in the Gantt Chart (#63372) (#65016) * Expose queueing time in the Gantt Chart * Also expose scheduled_dttm in the Gantt Chart * Simplify Gantt tooltip and ensure minimum bar visibility for short segments * Null safety for dayjs calls and add tests for timing segments (cherry picked from commit cd851646fba29e89c848a19ee78c9ee8f81ad238) Co-authored-by: Saumyajit Chowdhury <77187489+smyjt@users.noreply.github.com> --- .../core_api/datamodels/ui/gantt.py | 2 + .../core_api/openapi/_private_ui.yaml | 14 +++ .../api_fastapi/core_api/routes/ui/gantt.py | 6 ++ .../ui/openapi-gen/requests/schemas.gen.ts | 26 +++++- .../ui/openapi-gen/requests/types.gen.ts | 2 + .../src/layouts/Details/Gantt/utils.test.ts | 89 +++++++++++++++++++ .../ui/src/layouts/Details/Gantt/utils.ts | 50 +++++++++-- .../core_api/routes/ui/test_gantt.py | 24 +++++ 8 files changed, 207 insertions(+), 6 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/gantt.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/gantt.py index 57a96c8a0ad70..3b74e84b47f3d 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/gantt.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/gantt.py @@ -30,6 +30,8 @@ class GanttTaskInstance(BaseModel): task_display_name: str try_number: int state: TaskInstanceState | None + scheduled_dttm: datetime | None + queued_dttm: datetime | None start_date: datetime | None end_date: datetime | None is_group: bool = False diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml index 706cf64b492aa..87ed72c730be0 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml @@ -2249,6 +2249,18 @@ components: anyOf: - $ref: '#/components/schemas/TaskInstanceState' - type: 'null' + scheduled_dttm: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Scheduled Dttm + queued_dttm: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Queued Dttm start_date: anyOf: - type: string @@ -2275,6 +2287,8 @@ components: - task_display_name - try_number - state + - scheduled_dttm + - queued_dttm - start_date - end_date title: GanttTaskInstance diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/gantt.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/gantt.py index f33b12e6f7e8a..7807e3fd6bc0f 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/gantt.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/gantt.py @@ -67,6 +67,8 @@ def get_gantt_data( TaskInstance.task_display_name.label("task_display_name"), # type: ignore[attr-defined] TaskInstance.try_number.label("try_number"), TaskInstance.state.label("state"), + TaskInstance.scheduled_dttm.label("scheduled_dttm"), + TaskInstance.queued_dttm.label("queued_dttm"), TaskInstance.start_date.label("start_date"), TaskInstance.end_date.label("end_date"), ).where( @@ -81,6 +83,8 @@ def get_gantt_data( TaskInstanceHistory.task_display_name.label("task_display_name"), TaskInstanceHistory.try_number.label("try_number"), TaskInstanceHistory.state.label("state"), + TaskInstanceHistory.scheduled_dttm.label("scheduled_dttm"), + TaskInstanceHistory.queued_dttm.label("queued_dttm"), TaskInstanceHistory.start_date.label("start_date"), TaskInstanceHistory.end_date.label("end_date"), ).where( @@ -106,6 +110,8 @@ def get_gantt_data( task_display_name=row.task_display_name, try_number=row.try_number, state=row.state, + scheduled_dttm=row.scheduled_dttm, + queued_dttm=row.queued_dttm, start_date=row.start_date, end_date=row.end_date, ) diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts index 356802aab9fcc..be72276746c77 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts @@ -8028,6 +8028,30 @@ export const $GanttTaskInstance = { } ] }, + scheduled_dttm: { + anyOf: [ + { + type: 'string', + format: 'date-time' + }, + { + type: 'null' + } + ], + title: 'Scheduled Dttm' + }, + queued_dttm: { + anyOf: [ + { + type: 'string', + format: 'date-time' + }, + { + type: 'null' + } + ], + title: 'Queued Dttm' + }, start_date: { anyOf: [ { @@ -8064,7 +8088,7 @@ export const $GanttTaskInstance = { } }, type: 'object', - required: ['task_id', 'task_display_name', 'try_number', 'state', 'start_date', 'end_date'], + required: ['task_id', 'task_display_name', 'try_number', 'state', 'scheduled_dttm', 'queued_dttm', 'start_date', 'end_date'], title: 'GanttTaskInstance', description: 'Task instance data for Gantt chart.' } as const; diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts index 1601e54b01a33..3622838903261 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts @@ -1973,6 +1973,8 @@ export type GanttTaskInstance = { task_display_name: string; try_number: number; state: TaskInstanceState | null; + scheduled_dttm: string | null; + queued_dttm: string | null; start_date: string | null; end_date: string | null; is_group?: boolean; diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.test.ts b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.test.ts index b9fa6a491be54..a0e61cc857922 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.test.ts +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.test.ts @@ -1,3 +1,5 @@ +/* eslint-disable max-lines */ + /*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -166,6 +168,10 @@ describe("transformGanttData", () => { end_date: null, is_mapped: false, // eslint-disable-next-line unicorn/no-null + queued_dttm: null, + // eslint-disable-next-line unicorn/no-null + scheduled_dttm: null, + // eslint-disable-next-line unicorn/no-null start_date: null, // eslint-disable-next-line unicorn/no-null state: null, @@ -189,6 +195,10 @@ describe("transformGanttData", () => { // eslint-disable-next-line unicorn/no-null end_date: null, is_mapped: false, + // eslint-disable-next-line unicorn/no-null + queued_dttm: null, + // eslint-disable-next-line unicorn/no-null + scheduled_dttm: null, start_date: "2024-03-14T10:00:00+00:00", state: "running", task_display_name: "task_1", @@ -237,6 +247,10 @@ describe("transformGanttData", () => { { end_date: "2024-03-14T10:05:00+00:00", is_mapped: false, + // eslint-disable-next-line unicorn/no-null + queued_dttm: null, + // eslint-disable-next-line unicorn/no-null + scheduled_dttm: null, start_date: "2024-03-14T10:00:00+00:00", state: "success", task_display_name: "task_1", @@ -258,4 +272,79 @@ describe("transformGanttData", () => { expect(Number.isNaN(start.valueOf())).toBe(false); expect(Number.isNaN(end.valueOf())).toBe(false); }); + + it("should produce 3 segments when scheduled_dttm and queued_dttm are present", () => { + const result = transformGanttData({ + allTries: [ + { + end_date: "2024-03-14T10:05:00+00:00", + is_mapped: false, + queued_dttm: "2024-03-14T09:59:00+00:00", + scheduled_dttm: "2024-03-14T09:58:00+00:00", + start_date: "2024-03-14T10:00:00+00:00", + state: "success", + task_display_name: "task_1", + task_id: "task_1", + try_number: 1, + }, + ], + flatNodes: [{ depth: 0, id: "task_1", is_mapped: false, label: "task_1" }], + gridSummaries: [], + }); + + expect(result).toHaveLength(3); + expect(result[0]?.state).toBe("scheduled"); + expect(result[1]?.state).toBe("queued"); + expect(result[2]?.state).toBe("success"); + }); + + it("should produce 2 segments when only queued_dttm is present", () => { + const result = transformGanttData({ + allTries: [ + { + end_date: "2024-03-14T10:05:00+00:00", + is_mapped: false, + queued_dttm: "2024-03-14T09:59:00+00:00", + // eslint-disable-next-line unicorn/no-null + scheduled_dttm: null, + start_date: "2024-03-14T10:00:00+00:00", + state: "success", + task_display_name: "task_1", + task_id: "task_1", + try_number: 1, + }, + ], + flatNodes: [{ depth: 0, id: "task_1", is_mapped: false, label: "task_1" }], + gridSummaries: [], + }); + + expect(result).toHaveLength(2); + expect(result[0]?.state).toBe("queued"); + expect(result[1]?.state).toBe("success"); + }); + + it("should produce 1 segment when scheduled_dttm and queued_dttm are null", () => { + const result = transformGanttData({ + allTries: [ + { + end_date: "2024-03-14T10:05:00+00:00", + is_mapped: false, + // eslint-disable-next-line unicorn/no-null + queued_dttm: null, + // eslint-disable-next-line unicorn/no-null + scheduled_dttm: null, + start_date: "2024-03-14T10:00:00+00:00", + state: "success", + task_display_name: "task_1", + task_id: "task_1", + try_number: 1, + }, + ], + flatNodes: [{ depth: 0, id: "task_1", is_mapped: false, label: "task_1" }], + gridSummaries: [], + }); + + expect(result).toHaveLength(1); + expect(result[0]?.state).toBe("success"); + }); }); diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts index fab1d1bcf773a..621f22e8ab923 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts @@ -122,14 +122,47 @@ export const transformGanttData = ({ if (tries && tries.length > 0) { return tries .filter((tryInstance) => tryInstance.start_date !== null) - .map((tryInstance) => { + .flatMap((tryInstance) => { const hasTaskRunning = isStatePending(tryInstance.state); const endTime = hasTaskRunning || tryInstance.end_date === null ? dayjs().toISOString() : tryInstance.end_date; - - return { + const items: Array = []; + + // Scheduled segment: from scheduled_dttm to queued_dttm (or start_date if no queued_dttm) + if (tryInstance.scheduled_dttm !== null) { + const scheduledEnd = tryInstance.queued_dttm ?? tryInstance.start_date ?? undefined; + + items.push({ + isGroup: false, + isMapped: tryInstance.is_mapped, + state: "scheduled" as TaskInstanceState, + taskId: tryInstance.task_id, + tryNumber: tryInstance.try_number, + x: [dayjs(tryInstance.scheduled_dttm).toISOString(), dayjs(scheduledEnd).toISOString()], + y: tryInstance.task_display_name, + }); + } + + // Queue segment: from queued_dttm to start_date + if (tryInstance.queued_dttm !== null) { + items.push({ + isGroup: false, + isMapped: tryInstance.is_mapped, + state: "queued" as TaskInstanceState, + taskId: tryInstance.task_id, + tryNumber: tryInstance.try_number, + x: [ + dayjs(tryInstance.queued_dttm).toISOString(), + dayjs(tryInstance.start_date ?? undefined).toISOString(), + ], + y: tryInstance.task_display_name, + }); + } + + // Execution segment: from start_date to end_date + items.push({ isGroup: false, isMapped: tryInstance.is_mapped, state: tryInstance.state, @@ -137,7 +170,9 @@ export const transformGanttData = ({ tryNumber: tryInstance.try_number, x: [dayjs(tryInstance.start_date).toISOString(), dayjs(endTime).toISOString()], y: tryInstance.task_display_name, - }; + }); + + return items; }); } } @@ -259,6 +294,11 @@ export const createChartOptions = ({ duration: 150, easing: "linear" as const, }, + datasets: { + bar: { + minBarLength: 4, + }, + }, indexAxis: "y" as const, maintainAspectRatio: false, onClick: handleBarClick, @@ -331,7 +371,7 @@ export const createChartOptions = ({ label(tooltipItem: TooltipItem<"bar">) { const taskInstance = data[tooltipItem.dataIndex]; - return `${translate("state")}: ${translate(`states.${taskInstance?.state}`)}`; + return `${translate("state")}: ${translate(`common:states.${taskInstance?.state}`)}`; }, }, }, diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_gantt.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_gantt.py index 162c82682afcf..0e2be9e277cae 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_gantt.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_gantt.py @@ -51,6 +51,8 @@ "task_display_name": TASK_DISPLAY_NAME, "try_number": 1, "state": "success", + "scheduled_dttm": "2024-11-30T09:50:00Z", + "queued_dttm": "2024-11-30T09:55:00Z", "start_date": "2024-11-30T10:00:00Z", "end_date": "2024-11-30T10:05:00Z", "is_group": False, @@ -62,6 +64,8 @@ "task_display_name": TASK_DISPLAY_NAME_2, "try_number": 1, "state": "failed", + "scheduled_dttm": "2024-11-30T10:02:00Z", + "queued_dttm": "2024-11-30T10:03:00Z", "start_date": "2024-11-30T10:05:00Z", "end_date": "2024-11-30T10:10:00Z", "is_group": False, @@ -73,6 +77,8 @@ "task_display_name": TASK_DISPLAY_NAME_3, "try_number": 1, "state": "running", + "scheduled_dttm": None, + "queued_dttm": None, "start_date": "2024-11-30T10:10:00Z", "end_date": None, "is_group": False, @@ -116,16 +122,22 @@ def setup(dag_maker, session=None): if ti.task_id == TASK_ID: ti.state = TaskInstanceState.SUCCESS ti.try_number = 1 + ti.scheduled_dttm = pendulum.DateTime(2024, 11, 30, 9, 50, 0, tzinfo=pendulum.UTC) + ti.queued_dttm = pendulum.DateTime(2024, 11, 30, 9, 55, 0, tzinfo=pendulum.UTC) ti.start_date = pendulum.DateTime(2024, 11, 30, 10, 0, 0, tzinfo=pendulum.UTC) ti.end_date = pendulum.DateTime(2024, 11, 30, 10, 5, 0, tzinfo=pendulum.UTC) elif ti.task_id == TASK_ID_2: ti.state = TaskInstanceState.FAILED ti.try_number = 1 + ti.scheduled_dttm = pendulum.DateTime(2024, 11, 30, 10, 2, 0, tzinfo=pendulum.UTC) + ti.queued_dttm = pendulum.DateTime(2024, 11, 30, 10, 3, 0, tzinfo=pendulum.UTC) ti.start_date = pendulum.DateTime(2024, 11, 30, 10, 5, 0, tzinfo=pendulum.UTC) ti.end_date = pendulum.DateTime(2024, 11, 30, 10, 10, 0, tzinfo=pendulum.UTC) elif ti.task_id == TASK_ID_3: ti.state = TaskInstanceState.RUNNING ti.try_number = 1 + ti.scheduled_dttm = None + ti.queued_dttm = None ti.start_date = pendulum.DateTime(2024, 11, 30, 10, 10, 0, tzinfo=pendulum.UTC) ti.end_date = None @@ -306,6 +318,18 @@ def test_sorted_by_task_id_and_try_number(self, test_client): sorted_tis = sorted(task_instances, key=lambda x: (x["task_id"], x["try_number"])) assert task_instances == sorted_tis + def test_timing_fields_are_returned(self, test_client): + response = test_client.get(f"/gantt/{DAG_ID}/run_1") + assert response.status_code == 200 + data = response.json() + tis = {ti["task_id"]: ti for ti in data["task_instances"]} + assert tis[TASK_ID]["scheduled_dttm"] == "2024-11-30T09:50:00Z" + assert tis[TASK_ID]["queued_dttm"] == "2024-11-30T09:55:00Z" + assert tis[TASK_ID_2]["scheduled_dttm"] == "2024-11-30T10:02:00Z" + assert tis[TASK_ID_2]["queued_dttm"] == "2024-11-30T10:03:00Z" + assert tis[TASK_ID_3]["scheduled_dttm"] is None + assert tis[TASK_ID_3]["queued_dttm"] is None + def test_should_response_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get(f"/gantt/{DAG_ID}/run_1") assert response.status_code == 401 From f6aca26aaa2b1c35f1a67ed41ce6c307a63fa677 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 19:42:58 +0300 Subject: [PATCH 073/100] [v3-2-test] Validate operator arg types at decoration time in @task decorator (#65041) (#65050) (cherry picked from commit 7d3364b22f3217a9639e2680c81587981433fcbc) Co-authored-by: Kaxil Naik --- task-sdk/src/airflow/sdk/bases/decorator.py | 8 +++++ .../tests/task_sdk/bases/test_decorator.py | 33 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/task-sdk/src/airflow/sdk/bases/decorator.py b/task-sdk/src/airflow/sdk/bases/decorator.py index 2e98f826c7ea1..8634fbe99647c 100644 --- a/task-sdk/src/airflow/sdk/bases/decorator.py +++ b/task-sdk/src/airflow/sdk/bases/decorator.py @@ -30,6 +30,7 @@ from airflow.sdk import TriggerRule, timezone from airflow.sdk.bases.operator import ( + BASEOPERATOR_ARGS_EXPECTED_TYPES, BaseOperator, coerce_resources, coerce_timedelta, @@ -498,6 +499,13 @@ def __attrs_post_init__(self): if "self" in self.function_signature.parameters: raise TypeError(f"@{self.decorator_name} does not support methods") self.kwargs.setdefault("task_id", self.function.__name__) + for arg_name, expected_type in BASEOPERATOR_ARGS_EXPECTED_TYPES.items(): + if arg_name in self.kwargs: + value = self.kwargs[arg_name] + if value is not None and not isinstance(value, expected_type): + raise TypeError( + f"Expected {arg_name!r} to be {expected_type}, got {type(value).__name__}: {value!r}" + ) update_wrapper(self, self.function) def __call__(self, *args: FParams.args, **kwargs: FParams.kwargs) -> XComArg: diff --git a/task-sdk/tests/task_sdk/bases/test_decorator.py b/task-sdk/tests/task_sdk/bases/test_decorator.py index 6021f6f0aad41..860eb6e7b3312 100644 --- a/task-sdk/tests/task_sdk/bases/test_decorator.py +++ b/task-sdk/tests/task_sdk/bases/test_decorator.py @@ -197,6 +197,39 @@ def dummy_task(a, b=1, *args, kw_required, **kwargs): assert make_op(dummy_task, op_kwargs={"a": 1, "kw_required": "x"}) is not None + @pytest.mark.parametrize( + ("kwargs", "match"), + [ + pytest.param( + {"task_id": "fetch_{}".format}, + "Expected 'task_id' to be .*, got builtin_function_or_method", + id="task_id_bound_method", + ), + pytest.param( + {"retries": "three"}, + "Expected 'retries' to be .*, got str", + id="retries_string", + ), + pytest.param( + {"queue": 42}, + "Expected 'queue' to be .*, got int", + id="queue_int", + ), + pytest.param( + {"priority_weight": 1.5}, + "Expected 'priority_weight' to be .*, got float", + id="priority_weight_float", + ), + ], + ) + def test_wrong_arg_type_raises_type_error_at_decoration_time(self, kwargs, match): + """Non-matching types for operator kwargs raise TypeError at decoration time.""" + with pytest.raises(TypeError, match=match): + + @task(**kwargs) + def my_task(): + return 1 + def make_op(func, op_args=None, op_kwargs=None, **kwargs): return DummyDecoratedOperator( From 78ed84c71361e780672b643c787dac2c3c37b3e5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 19:45:29 +0300 Subject: [PATCH 074/100] [v3-2-test] restore OpenSearch log integration (#64764) (#65003) * add changes for os provider * bump pyproject.toml provider lib version * Fix failing CI (cherry picked from commit 9465591c0f696504488ee78c2e5f5391f28af66b) Co-authored-by: Owen Leung --- .../airflow_local_settings.py | 44 ++++++++++--------- pyproject.toml | 4 +- .../ci/prek/update_airflow_pyproject_toml.py | 1 + 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/airflow-core/src/airflow/config_templates/airflow_local_settings.py b/airflow-core/src/airflow/config_templates/airflow_local_settings.py index 48f14b0f9a9ee..0c54c55573575 100644 --- a/airflow-core/src/airflow/config_templates/airflow_local_settings.py +++ b/airflow-core/src/airflow/config_templates/airflow_local_settings.py @@ -334,34 +334,36 @@ def _default_conn_name_from(mod_path, hook_name): ) elif OPENSEARCH_HOST: - OPENSEARCH_END_OF_LOG_MARK: str = conf.get_mandatory_value("opensearch", "END_OF_LOG_MARK") - OPENSEARCH_PORT: str = conf.get_mandatory_value("opensearch", "PORT") + from airflow.providers.opensearch.log.os_task_handler import OpensearchRemoteLogIO + + OPENSEARCH_PORT = conf.getint("opensearch", "PORT", fallback=9200) OPENSEARCH_USERNAME: str = conf.get_mandatory_value("opensearch", "USERNAME") OPENSEARCH_PASSWORD: str = conf.get_mandatory_value("opensearch", "PASSWORD") OPENSEARCH_WRITE_STDOUT: bool = conf.getboolean("opensearch", "WRITE_STDOUT") + OPENSEARCH_WRITE_TO_OS: bool = conf.getboolean("opensearch", "WRITE_TO_OS") OPENSEARCH_JSON_FORMAT: bool = conf.getboolean("opensearch", "JSON_FORMAT") - OPENSEARCH_JSON_FIELDS: str = conf.get_mandatory_value("opensearch", "JSON_FIELDS") + OPENSEARCH_TARGET_INDEX: str = conf.get_mandatory_value("opensearch", "TARGET_INDEX") OPENSEARCH_HOST_FIELD: str = conf.get_mandatory_value("opensearch", "HOST_FIELD") OPENSEARCH_OFFSET_FIELD: str = conf.get_mandatory_value("opensearch", "OFFSET_FIELD") + OPENSEARCH_LOG_ID_TEMPLATE: str = conf.get("opensearch", "LOG_ID_TEMPLATE", fallback="") or ( + "{dag_id}-{task_id}-{run_id}-{map_index}-{try_number}" + ) - OPENSEARCH_REMOTE_HANDLERS: dict[str, dict[str, str | bool | None]] = { - "task": { - "class": "airflow.providers.opensearch.log.os_task_handler.OpensearchTaskHandler", - "formatter": "airflow", - "base_log_folder": BASE_LOG_FOLDER, - "end_of_log_mark": OPENSEARCH_END_OF_LOG_MARK, - "host": OPENSEARCH_HOST, - "port": OPENSEARCH_PORT, - "username": OPENSEARCH_USERNAME, - "password": OPENSEARCH_PASSWORD, - "write_stdout": OPENSEARCH_WRITE_STDOUT, - "json_format": OPENSEARCH_JSON_FORMAT, - "json_fields": OPENSEARCH_JSON_FIELDS, - "host_field": OPENSEARCH_HOST_FIELD, - "offset_field": OPENSEARCH_OFFSET_FIELD, - }, - } - DEFAULT_LOGGING_CONFIG["handlers"].update(OPENSEARCH_REMOTE_HANDLERS) + REMOTE_TASK_LOG = OpensearchRemoteLogIO( + host=OPENSEARCH_HOST, + port=OPENSEARCH_PORT, + username=OPENSEARCH_USERNAME, + password=OPENSEARCH_PASSWORD, + target_index=OPENSEARCH_TARGET_INDEX, + write_stdout=OPENSEARCH_WRITE_STDOUT, + write_to_opensearch=OPENSEARCH_WRITE_TO_OS, + offset_field=OPENSEARCH_OFFSET_FIELD, + host_field=OPENSEARCH_HOST_FIELD, + base_log_folder=BASE_LOG_FOLDER, + delete_local_copy=delete_local_copy, + json_format=OPENSEARCH_JSON_FORMAT, + log_id_template=OPENSEARCH_LOG_ID_TEMPLATE, + ) else: raise AirflowException( "Incorrect remote log configuration. Please check the configuration of option 'host' in " diff --git a/pyproject.toml b/pyproject.toml index b4490f0eebeba..53971c76fbcc6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -297,7 +297,7 @@ apache-airflow = "airflow.__main__:main" "apache-airflow-providers-openlineage>=2.3.0" # Set from MIN_VERSION_OVERRIDE in update_airflow_pyproject_toml.py ] "opensearch" = [ - "apache-airflow-providers-opensearch>=1.5.0" + "apache-airflow-providers-opensearch>=1.9.0" # Set from MIN_VERSION_OVERRIDE in update_airflow_pyproject_toml.py ] "opsgenie" = [ "apache-airflow-providers-opsgenie>=5.8.0" @@ -461,7 +461,7 @@ apache-airflow = "airflow.__main__:main" "apache-airflow-providers-openai>=1.5.0", "apache-airflow-providers-openfaas>=3.7.0", "apache-airflow-providers-openlineage>=2.3.0", # Set from MIN_VERSION_OVERRIDE in update_airflow_pyproject_toml.py - "apache-airflow-providers-opensearch>=1.5.0", + "apache-airflow-providers-opensearch>=1.9.0", # Set from MIN_VERSION_OVERRIDE in update_airflow_pyproject_toml.py "apache-airflow-providers-opsgenie>=5.8.0", "apache-airflow-providers-oracle>=3.12.0", "apache-airflow-providers-pagerduty>=3.8.1", diff --git a/scripts/ci/prek/update_airflow_pyproject_toml.py b/scripts/ci/prek/update_airflow_pyproject_toml.py index ff3ee1e1fe244..ae65e8cf84bb5 100755 --- a/scripts/ci/prek/update_airflow_pyproject_toml.py +++ b/scripts/ci/prek/update_airflow_pyproject_toml.py @@ -78,6 +78,7 @@ "git": parse_version("0.0.2"), "common.messaging": parse_version("2.0.0"), "elasticsearch": parse_version("6.5.0"), + "opensearch": parse_version("1.9.0"), } From 1b12a49510d1139fc125c980becdbe41df877d2d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 19:46:42 +0300 Subject: [PATCH 075/100] [v3-2-test] Fix publishing failure when new providers are added to main (#65093) (#65101) * Fix publishing failure when new providers are added to main When publishing docs to S3 we attempt to move all the providers, including those that were added after release was prepared. This for example failed publishing step at the https://github.com/apache/airflow/actions/runs/24308895274/job/70977025250 We should skip all non-existing providers instead * Update .github/workflows/publish-docs-to-s3.yml --------- (cherry picked from commit 6a63b1e1c6bfee5a4cc5b0754614970de0096c0d) Co-authored-by: Jarek Potiuk Co-authored-by: Jens Scheffler <95105677+jscheffl@users.noreply.github.com> --- dev/breeze/src/airflow_breeze/utils/docs_publisher.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dev/breeze/src/airflow_breeze/utils/docs_publisher.py b/dev/breeze/src/airflow_breeze/utils/docs_publisher.py index 0162168166982..068d73d5b6f93 100644 --- a/dev/breeze/src/airflow_breeze/utils/docs_publisher.py +++ b/dev/breeze/src/airflow_breeze/utils/docs_publisher.py @@ -108,6 +108,10 @@ def publish(self, override_versioned: bool, airflow_site_dir: str): return 1, f"Skipping {self.package_name}: Previously existing directory" # If output directory exists and is not versioned, delete it shutil.rmtree(output_dir) + if not os.path.exists(self._build_dir): + get_console(output=self.output).print(f"Build directory {self._build_dir} does not exist!") + get_console(output=self.output).print() + return 0, f"Skipping {self.package_name}: Build directory does not exist" shutil.copytree(self._build_dir, output_dir) if self.is_versioned: with open(os.path.join(output_dir, "..", "stable.txt"), "w") as stable_file: From ea2ae1c2223e27426e7045ebc271ce3b99d6135d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 21:00:22 +0200 Subject: [PATCH 076/100] [v3-2-test] Grant write permissions to scheduled CI upgrade check workflows (#65168) (#65176) The scheduled upgrade check wrappers declared `contents: read`, which caps the permissions of the reusable `upgrade-check.yml` they call. That workflow needs `contents: write` and `pull-requests: write` to push the upgrade branch and open a draft PR, so every scheduled run failed immediately with startup_failure: The workflow is requesting 'contents: write, pull-requests: write', but is only allowed 'contents: read, pull-requests: none'. Raise the caller permissions to the ceiling required by the callee so the scheduled upgrade PR job can actually run. (cherry picked from commit 8291f3774fec5a01512dcdd9c820bddbcf13dea8) Co-authored-by: Jarek Potiuk --- .github/workflows/scheduled-upgrade-check-main.yml | 3 ++- .github/workflows/scheduled-upgrade-check-v3-2-test.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scheduled-upgrade-check-main.yml b/.github/workflows/scheduled-upgrade-check-main.yml index 5978721b97195..1c828f86b0368 100644 --- a/.github/workflows/scheduled-upgrade-check-main.yml +++ b/.github/workflows/scheduled-upgrade-check-main.yml @@ -23,7 +23,8 @@ on: # yamllint disable-line rule:truthy - cron: '0 6 * * 1,3,5' workflow_dispatch: permissions: - contents: read + contents: write + pull-requests: write jobs: upgrade-main: name: "[main] Upgrade" diff --git a/.github/workflows/scheduled-upgrade-check-v3-2-test.yml b/.github/workflows/scheduled-upgrade-check-v3-2-test.yml index 268dd798f2e7d..7c924f3e8f3eb 100644 --- a/.github/workflows/scheduled-upgrade-check-v3-2-test.yml +++ b/.github/workflows/scheduled-upgrade-check-v3-2-test.yml @@ -23,7 +23,8 @@ on: # yamllint disable-line rule:truthy - cron: '0 6 * * 2,4' workflow_dispatch: permissions: - contents: read + contents: write + pull-requests: write jobs: upgrade-v3-2-test: name: "[v3-2-test] Upgrade" From 3b2b3e4307200230cfab782067ad4e1390dc45bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 21:05:47 +0200 Subject: [PATCH 077/100] Bump actions/github-script in the github-actions-updates group (#65149) Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script). Updates `actions/github-script` from 8.0.0 to 9.0.0 - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/ed597411d8f924073f98dfc5c65a23a2325f34cd...3a2844b7e9c422d3c10d287c895573f7108da1b3) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: 9.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-updates ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/automatic-backport.yml | 2 +- .github/workflows/milestone-tag-assistant.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/automatic-backport.yml b/.github/workflows/automatic-backport.yml index 2abe2b8f3824b..afe20ce780d85 100644 --- a/.github/workflows/automatic-backport.yml +++ b/.github/workflows/automatic-backport.yml @@ -45,7 +45,7 @@ jobs: - name: Find PR information id: pr-info - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/milestone-tag-assistant.yml b/.github/workflows/milestone-tag-assistant.yml index dd902b8e17da8..d3815a5322bf9 100644 --- a/.github/workflows/milestone-tag-assistant.yml +++ b/.github/workflows/milestone-tag-assistant.yml @@ -50,7 +50,7 @@ jobs: - name: Find PR information id: pr-info - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From 70a928fc3b7421602ddc73c306719265060ca4aa Mon Sep 17 00:00:00 2001 From: Jens Scheffler <95105677+jscheffl@users.noreply.github.com> Date: Mon, 13 Apr 2026 21:07:48 +0200 Subject: [PATCH 078/100] [v3-2-test] Re export AirflowPlugin to fix mypy errors in plugins (#65132) (#65163) (cherry picked from commit 521d52579296f274dd9c4dcd7e22fd62cade1c22) Co-authored-by: Amogh Desai --- airflow-core/src/airflow/plugins_manager.py | 2 +- task-sdk/src/airflow/sdk/plugins_manager.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/airflow-core/src/airflow/plugins_manager.py b/airflow-core/src/airflow/plugins_manager.py index 6e2b94330d677..76b478db66f24 100644 --- a/airflow-core/src/airflow/plugins_manager.py +++ b/airflow-core/src/airflow/plugins_manager.py @@ -28,7 +28,7 @@ from airflow import settings from airflow._shared.module_loading import import_string, qualname from airflow._shared.plugins_manager import ( - AirflowPlugin, + AirflowPlugin as AirflowPlugin, AirflowPluginSource as AirflowPluginSource, PluginsDirectorySource as PluginsDirectorySource, _load_entrypoint_plugins, diff --git a/task-sdk/src/airflow/sdk/plugins_manager.py b/task-sdk/src/airflow/sdk/plugins_manager.py index 8147174cbfb79..594f69bc28cdc 100644 --- a/task-sdk/src/airflow/sdk/plugins_manager.py +++ b/task-sdk/src/airflow/sdk/plugins_manager.py @@ -27,7 +27,7 @@ from airflow.sdk._shared.module_loading import import_string from airflow.sdk._shared.observability.metrics.stats import Stats from airflow.sdk._shared.plugins_manager import ( - AirflowPlugin, + AirflowPlugin as AirflowPlugin, _load_entrypoint_plugins, _load_plugins_from_plugin_directory, integrate_listener_plugins as _integrate_listener_plugins, From 68be9e81fcd4385c0c9dff235a93f49a1e452af6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 21:15:56 +0200 Subject: [PATCH 079/100] [v3-2-test] Fix redirect loop when stale root-path `_token` cookie exists from older Airflow instance (#64955) (#65177) * Fix redirect loop when stale root-path `_token` cookie exists from older Airflow instance * Adapt conditions to clear stale root path cookies * Extend test for clearing stale root path cookies on logout (cherry picked from commit ad269edda8512793587c55bde682b518650d6afd) Co-authored-by: Daniel Wolf <95075445+wolfdn@users.noreply.github.com> --- .../auth/middlewares/refresh_token.py | 15 +++++++- .../core_api/routes/public/auth.py | 12 +++++- .../auth/middlewares/test_refresh_token.py | 38 ++++++++++++++++++- .../core_api/routes/public/test_auth.py | 6 ++- 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py b/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py index ac2a3d0dee52a..b8a3a268ba855 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py +++ b/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py @@ -61,16 +61,29 @@ async def dispatch(self, request: Request, call_next): response = await call_next(request) if new_token is not None: + cookie_path = get_cookie_path() secure = bool(conf.get("api", "ssl_cert", fallback="")) response.set_cookie( COOKIE_NAME_JWT_TOKEN, new_token, - path=get_cookie_path(), + path=cookie_path, httponly=True, secure=secure, samesite="lax", max_age=0 if new_token == "" else None, ) + # Clear any stale _token cookie at root path "/". + # Older Airflow instances may have set the cookie there; + # without this, the root-path cookie keeps being sent on + # every request, causing an infinite redirect loop. + if cookie_path != "/": + response.delete_cookie( + key=COOKIE_NAME_JWT_TOKEN, + path="/", + httponly=True, + secure=secure, + samesite="lax", + ) except HTTPException as exc: # If any HTTPException is raised during user resolution or refresh, return it as response return JSONResponse(status_code=exc.status_code, content={"detail": exc.detail}) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/auth.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/auth.py index 17f5edd134758..f85bcec3a6123 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/auth.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/auth.py @@ -66,12 +66,22 @@ def logout(request: Request, auth_manager: AuthManagerDep) -> RedirectResponse: auth_manager.revoke_token(token_str) secure = request.base_url.scheme == "https" or bool(conf.get("api", "ssl_cert", fallback="")) + cookie_path = get_cookie_path() response = RedirectResponse(auth_manager.get_url_login()) response.delete_cookie( key=COOKIE_NAME_JWT_TOKEN, - path=get_cookie_path(), + path=cookie_path, secure=secure, httponly=True, ) + # Clear any stale _token cookie at root path "/" left by + # older Airflow instances to prevent redirect loops. + if cookie_path != "/": + response.delete_cookie( + key=COOKIE_NAME_JWT_TOKEN, + path="/", + secure=secure, + httponly=True, + ) return response diff --git a/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py b/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py index 09943c2f6cf31..34b30ba1e7e4f 100644 --- a/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py +++ b/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py @@ -159,5 +159,39 @@ async def test_dispatch_cookie_uses_subpath( call_next = AsyncMock(return_value=Response()) response = await middleware.dispatch(mock_request, call_next) - set_cookie_headers = response.headers.get("set-cookie", "") - assert "Path=/team-a/" in set_cookie_headers + set_cookie_headers = response.headers.getlist("set-cookie") + assert any("Path=/team-a/" in h for h in set_cookie_headers) + # Stale root-path cookie must also be cleared + assert any( + "Path=/" in h and "Path=/team-a/" not in h and "Max-Age=0" in h for h in set_cookie_headers + ) + + @patch("airflow.api_fastapi.auth.middlewares.refresh_token.get_cookie_path", return_value="/team-a/") + @patch.object( + JWTRefreshMiddleware, + "_refresh_user", + side_effect=HTTPException(status_code=403, detail="Invalid JWT token"), + ) + @patch("airflow.api_fastapi.auth.middlewares.refresh_token.conf") + @pytest.mark.asyncio + async def test_dispatch_invalid_token_clears_root_cookie( + self, + mock_conf, + mock_refresh_user, + mock_cookie_path, + middleware, + mock_request, + ): + """When a stale _token exists at root path, clearing must target both the subpath and root.""" + mock_request.cookies = {COOKIE_NAME_JWT_TOKEN: "stale_root_token"} + mock_conf.get.return_value = "" + + call_next = AsyncMock(return_value=Response(status_code=401)) + response = await middleware.dispatch(mock_request, call_next) + + set_cookie_headers = response.headers.getlist("set-cookie") + # Expect two delete cookies: one at the subpath and one at root "/" + assert any("Path=/team-a/" in h and "Max-Age=0" in h for h in set_cookie_headers) + assert any( + "Path=/" in h and "Path=/team-a/" not in h and "Max-Age=0" in h for h in set_cookie_headers + ) diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_auth.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_auth.py index c860c847501cc..f0e170daf604f 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_auth.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_auth.py @@ -149,8 +149,12 @@ def test_logout_cookie_uses_subpath(self, mock_cookie_path, test_client): assert response.status_code == 307 cookies = response.headers.get_list("set-cookie") - token_cookie = next(c for c in cookies if f"{COOKIE_NAME_JWT_TOKEN}=" in c) + token_cookie = next(c for c in cookies if f"{COOKIE_NAME_JWT_TOKEN}=" in c and f"Path={SUBPATH}" in c) assert f"Path={SUBPATH}" in token_cookie + # Stale root-path cookie must also be cleared + assert any( + f"{COOKIE_NAME_JWT_TOKEN}=" in c and "Path=/" in c and f"Path={SUBPATH}" not in c for c in cookies + ) class TestLogoutTokenRevocation: From 88155f852e8295be4612c7d4b0aac2eeb972536a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:28:07 +0200 Subject: [PATCH 080/100] [v3-2-test] MD files only optimization only on PUSH (#65181) (#65182) When we merge to v3-2-test it usually triggers full build, however when there is only an .md file change (which happens for AGENTS.md updates for example) - it should not trigger the complete rebuild. (cherry picked from commit c8ebd28bdae9a1eb6f0e533a832c4d725b1efa74) Co-authored-by: Jarek Potiuk --- dev/breeze/src/airflow_breeze/utils/selective_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py b/dev/breeze/src/airflow_breeze/utils/selective_checks.py index 19506d490b6a5..ca7fbef3a3d56 100644 --- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py +++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py @@ -594,7 +594,7 @@ def default_constraints_branch(self) -> str: def _should_run_all_tests_and_versions(self) -> bool: if self._github_event in [GithubEvents.PUSH, GithubEvents.SCHEDULE, GithubEvents.WORKFLOW_DISPATCH]: - if self.only_text_non_doc_files_changed: + if self.only_text_non_doc_files_changed and self._github_event == GithubEvents.PUSH: console_print( f"[warning]Only text non doc files changed in {self._github_event}, skip full tests[/]" ) From 2c6ed8eaaeb4e0a5a9aee7aa9668e052566fa2b2 Mon Sep 17 00:00:00 2001 From: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:17:10 +0530 Subject: [PATCH 081/100] Prevent Session leak from StreamingResponse API endpoints. (#65162) (#65193) The comment in the test sums up what was going on, but essentially this result in `session.close` being called when the endpoint returned, but before the response was generated. Then SQLA was 'helpful' and re-opened it. However since the teardown/post-yield code has already run, this new session is never closed. This results in a connection open that leaks untli Python's full GC runs (i.e. `gc.collect()`) -- it going out of scope doesn't delete things as the Session and the RootTransaction form a cycle. (cherry picked from commit 5559365a4b016817fad3d16ec710b716f1ddd945) Co-authored-by: Ash Berlin-Taylor --- .../api_fastapi/core_api/routes/ui/grid.py | 6 +- .../unit/api_fastapi/core_api/test_app.py | 77 +++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py index 0143ae81e14ef..bea583d510167 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py @@ -25,10 +25,10 @@ from fastapi import Depends, HTTPException, Query, status from fastapi.responses import StreamingResponse from sqlalchemy import exists, select -from sqlalchemy.orm import joinedload, load_only, selectinload +from sqlalchemy.orm import Session, joinedload, load_only, selectinload from airflow.api_fastapi.auth.managers.models.resource_details import DagAccessEntity -from airflow.api_fastapi.common.db.common import SessionDep, paginated_select +from airflow.api_fastapi.common.db.common import SessionDep, _get_session, paginated_select from airflow.api_fastapi.common.parameters import ( QueryDagRunRunTypesFilter, QueryDagRunStateFilter, @@ -426,7 +426,7 @@ def get_node_summaries(): ) def get_grid_ti_summaries_stream( dag_id: str, - session: SessionDep, + session: Annotated[Session, Depends(_get_session)], run_ids: Annotated[list[str] | None, Query()] = None, ) -> StreamingResponse: """ diff --git a/airflow-core/tests/unit/api_fastapi/core_api/test_app.py b/airflow-core/tests/unit/api_fastapi/core_api/test_app.py index 4881976a6735f..75e44245b3924 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/test_app.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/test_app.py @@ -16,13 +16,90 @@ # under the License. from __future__ import annotations +import inspect +import typing + import pytest +from fastapi.params import Depends as DependsClass +from fastapi.responses import StreamingResponse +from starlette.routing import Mount + +from airflow.api_fastapi.app import create_app from tests_common.test_utils.db import clear_db_jobs pytestmark = pytest.mark.db_test +def _get_all_api_routes(app): + """Recursively yield all APIRoutes from the app and its mounted sub-apps.""" + for route in getattr(app, "routes", []): + if isinstance(route, Mount) and hasattr(route, "app"): + yield from _get_all_api_routes(route.app) + if hasattr(route, "endpoint"): + yield route + + +class TestStreamingEndpointSessionScope: + def test_no_streaming_endpoint_uses_function_scoped_depends(self): + """Streaming endpoints must not use function-scoped generator dependencies. + + FastAPI's ``function_stack`` (used for ``scope="function"`` dependencies) + is torn down after the route handler returns but *before* the response body + is sent. For ``StreamingResponse`` endpoints the response body is produced + by a generator that runs during sending, so any generator dependency with + ``scope="function"`` will have its cleanup run before the generator + executes. This causes the generator to silently reopen the session via + autobegin, and the resulting connection is never returned to the pool. + """ + # These endpoints mention StreamingResponse but only use the session + # *before* streaming begins — the generator does not capture it. + # Function scope is correct for them: close the session early rather + # than hold it open for the entire (potentially long) stream. + allowed = { + "airflow.api_fastapi.core_api.routes.public.log.get_log", + "airflow.api_fastapi.core_api.routes.public.dag_run.wait_dag_run_until_finished", + } + + app = create_app() + violations = [] + for route in _get_all_api_routes(app): + try: + hints = typing.get_type_hints(route.endpoint, include_extras=True) + except Exception: + continue + returns_streaming = hints.get("return") is StreamingResponse + if not returns_streaming: + try: + returns_streaming = "StreamingResponse" in inspect.getsource(route.endpoint) + except (OSError, TypeError): + pass + if not returns_streaming: + continue + fqn = f"{route.endpoint.__module__}.{route.endpoint.__qualname__}" + if fqn in allowed: + continue + for param_name, hint in hints.items(): + if param_name == "return": + continue + if typing.get_origin(hint) is not typing.Annotated: + continue + for metadata in typing.get_args(hint)[1:]: + if isinstance(metadata, DependsClass) and metadata.scope == "function": + violations.append( + f"{route.endpoint.__module__}.{route.endpoint.__qualname__}" + f" parameter '{param_name}'" + ) + + assert not violations, ( + "Streaming endpoints must not use function-scoped dependencies like " + "SessionDep. Use Annotated[Session, Depends(_get_session)] (default " + "request scope) instead — function-scoped cleanup runs before the " + "response body is streamed, leaking database connections.\n" + + "\n".join(f" - {v}" for v in violations) + ) + + class TestGzipMiddleware: @pytest.fixture(autouse=True) def setup(self): From a5c1b6b7f804256bdcf180ba253675a2aae9ee61 Mon Sep 17 00:00:00 2001 From: Pierre Jeambrun Date: Tue, 14 Apr 2026 11:44:32 +0200 Subject: [PATCH 082/100] Prevent Session from staying opened between yields (#65179) (#65195) --- .../api_fastapi/core_api/routes/ui/grid.py | 52 +++++++++++-------- .../unit/api_fastapi/core_api/test_app.py | 10 ++-- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py index bea583d510167..ecc4f8e4655ac 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py @@ -25,10 +25,10 @@ from fastapi import Depends, HTTPException, Query, status from fastapi.responses import StreamingResponse from sqlalchemy import exists, select -from sqlalchemy.orm import Session, joinedload, load_only, selectinload +from sqlalchemy.orm import joinedload, load_only, selectinload from airflow.api_fastapi.auth.managers.models.resource_details import DagAccessEntity -from airflow.api_fastapi.common.db.common import SessionDep, _get_session, paginated_select +from airflow.api_fastapi.common.db.common import SessionDep, paginated_select from airflow.api_fastapi.common.parameters import ( QueryDagRunRunTypesFilter, QueryDagRunStateFilter, @@ -67,6 +67,7 @@ from airflow.models.serialized_dag import SerializedDagModel from airflow.models.taskinstance import TaskInstance from airflow.models.taskinstancehistory import TaskInstanceHistory +from airflow.utils.session import create_session log = structlog.get_logger(logger_name=__name__) grid_router = AirflowRouter(prefix="/grid", tags=["Grid"]) @@ -426,7 +427,6 @@ def get_node_summaries(): ) def get_grid_ti_summaries_stream( dag_id: str, - session: Annotated[Session, Depends(_get_session)], run_ids: Annotated[list[str] | None, Query()] = None, ) -> StreamingResponse: """ @@ -441,28 +441,34 @@ def get_grid_ti_summaries_stream( """ def _generate() -> Generator[str, None, None]: + + # Each iteration opens and closes its own DB session so the connection is + # released between yields. This prevents a slow client from holding a + # database connection open for the entire stream duration. + # See https://github.com/apache/airflow/issues/65010. serdag_cache: dict = {} for run_id in run_ids or []: - tis = session.execute( - select( - TaskInstance.task_id, - TaskInstance.state, - TaskInstance.dag_version_id, - TaskInstance.start_date, - TaskInstance.end_date, - DagVersion.version_number, - ) - .outerjoin(DagVersion, TaskInstance.dag_version_id == DagVersion.id) - .where(TaskInstance.dag_id == dag_id) - .where(TaskInstance.run_id == run_id) - .order_by(TaskInstance.task_id) - ).all() - if not tis: - continue - version_id = tis[0].dag_version_id - if version_id not in serdag_cache: - serdag_cache[version_id] = _get_serdag(dag_id, version_id, session) - summary = _build_ti_summaries(dag_id, run_id, tis, session, serdag=serdag_cache[version_id]) + with create_session(scoped=False) as session: + tis = session.execute( + select( + TaskInstance.task_id, + TaskInstance.state, + TaskInstance.dag_version_id, + TaskInstance.start_date, + TaskInstance.end_date, + DagVersion.version_number, + ) + .outerjoin(DagVersion, TaskInstance.dag_version_id == DagVersion.id) + .where(TaskInstance.dag_id == dag_id) + .where(TaskInstance.run_id == run_id) + .order_by(TaskInstance.task_id) + ).all() + if not tis: + continue + version_id = tis[0].dag_version_id + if version_id not in serdag_cache: + serdag_cache[version_id] = _get_serdag(dag_id, version_id, session) + summary = _build_ti_summaries(dag_id, run_id, tis, session, serdag=serdag_cache[version_id]) yield GridTISummaries.model_validate(summary).model_dump_json() + "\n" return StreamingResponse(content=_generate(), media_type="application/x-ndjson") diff --git a/airflow-core/tests/unit/api_fastapi/core_api/test_app.py b/airflow-core/tests/unit/api_fastapi/core_api/test_app.py index 75e44245b3924..a30c803f50c85 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/test_app.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/test_app.py @@ -93,9 +93,13 @@ def test_no_streaming_endpoint_uses_function_scoped_depends(self): assert not violations, ( "Streaming endpoints must not use function-scoped dependencies like " - "SessionDep. Use Annotated[Session, Depends(_get_session)] (default " - "request scope) instead — function-scoped cleanup runs before the " - "response body is streamed, leaking database connections.\n" + "SessionDep — function-scoped cleanup runs before the response body " + "is streamed, leaking database connections.\n" + "Do NOT use Annotated[Session, Depends(_get_session)] or other session dependencies " + "either, as this holds the DB connection open for the entire stream " + "duration.\n" + "Instead, use create_session() inside the generator to open/close a " + "connection for each iteration, releasing it between yields.\n" + "\n".join(f" - {v}" for v in violations) ) From 9e3f1e55676fbf3dd9a2c9983fb4b265b8763987 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:50:40 +0200 Subject: [PATCH 083/100] [v3-2-test] fix sdk configuration to use $AIRFLOW_CONFIG env (#64936) (#65200) * fix sdk configuration to use AIRFLOW_CONFIG env * fix logic (cherry picked from commit 293f172148b5f78bb4d821b7919cf04873af38cb) Co-authored-by: Jeongwoo Do <48639483+wjddn279@users.noreply.github.com> --- task-sdk/src/airflow/sdk/configuration.py | 10 +++++-- task-sdk/tests/task_sdk/test_configuration.py | 30 ++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/task-sdk/src/airflow/sdk/configuration.py b/task-sdk/src/airflow/sdk/configuration.py index fba300e4a8477..4e438a2cbf737 100644 --- a/task-sdk/src/airflow/sdk/configuration.py +++ b/task-sdk/src/airflow/sdk/configuration.py @@ -30,6 +30,7 @@ from airflow.sdk._shared.configuration.parser import ( AirflowConfigParser as _SharedAirflowConfigParser, configure_parser_from_configuration_description, + expand_env_var, ) from airflow.sdk.execution_time.secrets import _SERVER_DEFAULT_SECRETS_SEARCH_PATH @@ -99,7 +100,7 @@ def get_sdk_expansion_variables() -> dict[str, Any]: SDK only needs AIRFLOW_HOME for expansion. Core specific variables (FERNET_KEY, JWT_SECRET_KEY, etc.) are not needed in the SDK. """ - airflow_home = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow")) + airflow_home = expand_env_var(os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow"))) return { "AIRFLOW_HOME": airflow_home, } @@ -107,8 +108,11 @@ def get_sdk_expansion_variables() -> dict[str, Any]: def get_airflow_config() -> str: """Get path to airflow.cfg file.""" - airflow_home = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow")) - return os.path.join(airflow_home, "airflow.cfg") + airflow_config_var = os.environ.get("AIRFLOW_CONFIG") + if airflow_config_var is None: + airflow_home: str = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow")) + return os.path.join(expand_env_var(airflow_home), "airflow.cfg") + return expand_env_var(airflow_config_var) class AirflowSDKConfigParser(_SharedAirflowConfigParser): diff --git a/task-sdk/tests/task_sdk/test_configuration.py b/task-sdk/tests/task_sdk/test_configuration.py index 32ecc7ff3a109..cf512fa4418fe 100644 --- a/task-sdk/tests/task_sdk/test_configuration.py +++ b/task-sdk/tests/task_sdk/test_configuration.py @@ -23,7 +23,7 @@ import pytest from airflow.sdk._shared.configuration.exceptions import AirflowConfigException -from airflow.sdk.configuration import conf +from airflow.sdk.configuration import conf, get_airflow_config from airflow.sdk.providers_manager_runtime import ProvidersManagerTaskRuntime from tests_common.test_utils.config import ( @@ -156,3 +156,31 @@ def test_user_config_overrides_provider_values(self): custom_value = "my_custom.celery_executor" with conf_vars({("celery", "celery_app_name"): custom_value}): assert conf.get("celery", "celery_app_name") == custom_value + + +class TestGetAirflowConfig: + """Tests for get_airflow_config respecting AIRFLOW_CONFIG env var.""" + + def test_returns_airflow_config_env_var(self): + """get_airflow_config returns AIRFLOW_CONFIG when set.""" + with mock.patch.dict("os.environ", {"AIRFLOW_CONFIG": "/custom/path/airflow.cfg"}): + assert get_airflow_config() == "/custom/path/airflow.cfg" + + def test_expands_env_var_in_airflow_config(self): + """get_airflow_config expands env vars in AIRFLOW_CONFIG.""" + with mock.patch.dict( + "os.environ", {"AIRFLOW_CONFIG": "$CUSTOM_DIR/airflow.cfg", "CUSTOM_DIR": "/resolved"} + ): + assert get_airflow_config() == "/resolved/airflow.cfg" + + def test_default_fallback_when_airflow_config_not_set(self): + """get_airflow_config returns {AIRFLOW_HOME}/airflow.cfg when AIRFLOW_CONFIG is absent.""" + env = {"AIRFLOW_HOME": "/custom/home"} + with mock.patch.dict("os.environ", env, clear=True): + assert get_airflow_config() == "/custom/home/airflow.cfg" + + def test_expands_env_var_in_airflow_home_fallback(self): + """get_airflow_config expands env vars in AIRFLOW_HOME when AIRFLOW_CONFIG is absent.""" + env = {"AIRFLOW_HOME": "$CUSTOM_DIR/airflow", "CUSTOM_DIR": "/resolved"} + with mock.patch.dict("os.environ", env, clear=True): + assert get_airflow_config() == "/resolved/airflow/airflow.cfg" From 85d1cb155e56a8243dd875df538708b4d482a169 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Tue, 14 Apr 2026 11:57:42 +0200 Subject: [PATCH 084/100] feat: add `write_to_os` writing task logs to opensearch (#64364) (#65201) * feat: restore opensearch provider & add write_to_os feature * test: fix failing CI * test: revert test info command * revise for copilot comments * revert core changes * fix breeze unit test * Update providers/opensearch/provider.yaml * Update providers/opensearch/provider.yaml * update pyproejct toml * fix failing ci --------- (cherry picked from commit 4b0e876b470fcf47933f26898db2bf554c832ab1) Co-authored-by: Owen Leung Co-authored-by: Elad Kalif <45845474+eladkal@users.noreply.github.com> --- .../src/airflow_breeze/global_constants.py | 2 +- .../tests/test_pytest_args_for_test_types.py | 1 + providers/opensearch/docs/index.rst | 4 +- providers/opensearch/docs/logging/index.rst | 22 + providers/opensearch/provider.yaml | 14 + providers/opensearch/pyproject.toml | 2 +- .../airflow/providers/opensearch/__init__.py | 4 +- .../providers/opensearch/get_provider_info.py | 14 + .../opensearch/log/os_task_handler.py | 399 ++++++-- .../providers/opensearch/version_compat.py | 2 + .../opensearch/tests/integration/__init__.py | 17 + .../tests/integration/opensearch/__init__.py | 16 + .../integration/opensearch/log/__init__.py | 16 + .../opensearch/log/test_os_remote_log_io.py | 140 +++ .../tests/unit/opensearch/conftest.py | 49 - .../opensearch/log/test_os_task_handler.py | 913 +++++++++--------- 16 files changed, 1059 insertions(+), 556 deletions(-) create mode 100644 providers/opensearch/tests/integration/__init__.py create mode 100644 providers/opensearch/tests/integration/opensearch/__init__.py create mode 100644 providers/opensearch/tests/integration/opensearch/log/__init__.py create mode 100644 providers/opensearch/tests/integration/opensearch/log/test_os_remote_log_io.py diff --git a/dev/breeze/src/airflow_breeze/global_constants.py b/dev/breeze/src/airflow_breeze/global_constants.py index 0cc426184d51e..1a9c3c69ac513 100644 --- a/dev/breeze/src/airflow_breeze/global_constants.py +++ b/dev/breeze/src/airflow_breeze/global_constants.py @@ -807,7 +807,7 @@ def get_airflow_extras(): { "python-version": "3.10", "airflow-version": "2.11.1", - "remove-providers": "common.messaging edge3 fab git keycloak informatica common.ai", + "remove-providers": "common.messaging edge3 fab git keycloak informatica common.ai opensearch", "run-unit-tests": "true", }, { diff --git a/dev/breeze/tests/test_pytest_args_for_test_types.py b/dev/breeze/tests/test_pytest_args_for_test_types.py index bb7d30f3ef185..b89265b32df2d 100644 --- a/dev/breeze/tests/test_pytest_args_for_test_types.py +++ b/dev/breeze/tests/test_pytest_args_for_test_types.py @@ -70,6 +70,7 @@ def _find_all_integration_folders() -> list[str]: "providers/microsoft/mssql/tests/integration", "providers/mongo/tests/integration", "providers/openlineage/tests/integration", + "providers/opensearch/tests/integration", "providers/qdrant/tests/integration", "providers/redis/tests/integration", "providers/trino/tests/integration", diff --git a/providers/opensearch/docs/index.rst b/providers/opensearch/docs/index.rst index 5b1b5b93d2fb4..b60f5a91f7dfc 100644 --- a/providers/opensearch/docs/index.rst +++ b/providers/opensearch/docs/index.rst @@ -96,12 +96,12 @@ For the minimum Airflow version supported, see ``Requirements`` below. Requirements ------------ -The minimum Apache Airflow version supported by this provider distribution is ``2.11.0``. +The minimum Apache Airflow version supported by this provider distribution is ``3.0.0``. ========================================== ================== PIP package Version required ========================================== ================== -``apache-airflow`` ``>=2.11.0`` +``apache-airflow`` ``>=3.0.0`` ``apache-airflow-providers-common-compat`` ``>=1.12.0`` ``opensearch-py`` ``>=2.2.0`` ========================================== ================== diff --git a/providers/opensearch/docs/logging/index.rst b/providers/opensearch/docs/logging/index.rst index 9e27d8bd66a5b..22c0314223b48 100644 --- a/providers/opensearch/docs/logging/index.rst +++ b/providers/opensearch/docs/logging/index.rst @@ -25,6 +25,8 @@ Available only with Airflow>=3.0 Airflow can be configured to read task logs from Opensearch and optionally write logs to stdout in standard or json format. These logs can later be collected and forwarded to the cluster using tools like fluentd, logstash or others. +Airflow also supports writing logs to OpenSearch directly without requiring additional software like fluentd or logstash. To enable this feature, set ``write_to_os`` and ``json_format`` to ``True`` and ``write_stdout`` to ``False`` in ``airflow.cfg``. + You can choose to have all task logs from workers output to the highest parent level process, instead of the standard file locations. This allows for some additional flexibility in container environments like Kubernetes, where container stdout is already being logged to the host nodes. From there a log shipping tool can be used to forward them along to Opensearch. To use this feature, set the ``write_stdout`` option in ``airflow.cfg``. You can also choose to have the logs output in a JSON format, using the ``json_format`` option. Airflow uses the standard Python logging module and JSON fields are directly extracted from the LogRecord object. To use this feature, set the ``json_fields`` option in ``airflow.cfg``. Add the fields to the comma-delimited string that you want collected for the logs. These fields are from the LogRecord object in the ``logging`` module. `Documentation on different attributes can be found here `_. @@ -52,6 +54,24 @@ To output task logs to stdout in JSON format, the following config could be used write_stdout = True json_format = True +To output task logs to OpenSearch directly, the following config could be used: (set ``delete_local_logs`` to ``True`` if you do not want to retain a local copy of the task log) + +.. code-block:: ini + + [logging] + remote_logging = True + delete_local_logs = False + + [opensearch] + host = + port = + username = + password = + write_stdout = False + json_format = True + write_to_os = True + target_index = [name of the index to store logs] + .. _write-logs-elasticsearch-tls: Writing logs to Opensearch over TLS @@ -60,6 +80,8 @@ Writing logs to Opensearch over TLS To add custom configurations to Opensearch (e.g. turning on ``ssl_verify``, adding a custom self-signed cert, etc.) use the ``opensearch_configs`` setting in your ``airflow.cfg`` +Note that these configurations also apply when you enable writing logs to OpenSearch directly. + .. code-block:: ini [logging] diff --git a/providers/opensearch/provider.yaml b/providers/opensearch/provider.yaml index 1bf5afef339b1..e56b20b6cc403 100644 --- a/providers/opensearch/provider.yaml +++ b/providers/opensearch/provider.yaml @@ -143,6 +143,20 @@ config: type: string example: ~ default: "False" + write_to_os: + description: | + Write the task logs directly to OpenSearch + version_added: 1.9.0 + type: string + example: ~ + default: "False" + target_index: + description: | + Name of the index to write to when direct OpenSearch log writing is enabled + version_added: 1.9.0 + type: string + example: ~ + default: "airflow-logs" json_format: description: | Instead of the default log formatter, write the log lines as JSON diff --git a/providers/opensearch/pyproject.toml b/providers/opensearch/pyproject.toml index 6cf4a15d5057b..cba4573a1affb 100644 --- a/providers/opensearch/pyproject.toml +++ b/providers/opensearch/pyproject.toml @@ -59,7 +59,7 @@ requires-python = ">=3.10" # Make sure to run ``prek update-providers-dependencies --all-files`` # After you modify the dependencies, and rebuild your Breeze CI image with ``breeze ci-image build`` dependencies = [ - "apache-airflow>=2.11.0", + "apache-airflow>=3.0.0", "apache-airflow-providers-common-compat>=1.12.0", "opensearch-py>=2.2.0", ] diff --git a/providers/opensearch/src/airflow/providers/opensearch/__init__.py b/providers/opensearch/src/airflow/providers/opensearch/__init__.py index 1a60a488c212f..899089e9d1a60 100644 --- a/providers/opensearch/src/airflow/providers/opensearch/__init__.py +++ b/providers/opensearch/src/airflow/providers/opensearch/__init__.py @@ -32,8 +32,8 @@ __version__ = "1.8.4" if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse( - "2.11.0" + "3.0.0" ): raise RuntimeError( - f"The package `apache-airflow-providers-opensearch:{__version__}` needs Apache Airflow 2.11.0+" + f"The package `apache-airflow-providers-opensearch:{__version__}` needs Apache Airflow 3.0.0+" ) diff --git a/providers/opensearch/src/airflow/providers/opensearch/get_provider_info.py b/providers/opensearch/src/airflow/providers/opensearch/get_provider_info.py index 99e439416d3d2..70a3fac8ec291 100644 --- a/providers/opensearch/src/airflow/providers/opensearch/get_provider_info.py +++ b/providers/opensearch/src/airflow/providers/opensearch/get_provider_info.py @@ -116,6 +116,20 @@ def get_provider_info(): "example": None, "default": "False", }, + "write_to_os": { + "description": "Write the task logs directly to OpenSearch\n", + "version_added": "1.9.0", + "type": "string", + "example": None, + "default": "False", + }, + "target_index": { + "description": "Name of the index to write to when direct OpenSearch log writing is enabled\n", + "version_added": "1.9.0", + "type": "string", + "example": None, + "default": "airflow-logs", + }, "json_format": { "description": "Instead of the default log formatter, write the log lines as JSON\n", "version_added": "1.5.0", diff --git a/providers/opensearch/src/airflow/providers/opensearch/log/os_task_handler.py b/providers/opensearch/src/airflow/providers/opensearch/log/os_task_handler.py index 05f0ff90cbf77..300739b52e53a 100644 --- a/providers/opensearch/src/airflow/providers/opensearch/log/os_task_handler.py +++ b/providers/opensearch/src/airflow/providers/opensearch/log/os_task_handler.py @@ -18,27 +18,32 @@ from __future__ import annotations import contextlib +import json import logging +import os import sys import time from collections import defaultdict from collections.abc import Callable from datetime import datetime from operator import attrgetter +from pathlib import Path from typing import TYPE_CHECKING, Any, Literal, cast from urllib.parse import urlparse +import attrs import pendulum -from opensearchpy import OpenSearch +from opensearchpy import OpenSearch, helpers from opensearchpy.exceptions import NotFoundError from sqlalchemy import select +import airflow.logging_config as alc from airflow.models import DagRun from airflow.providers.common.compat.module_loading import import_string from airflow.providers.common.compat.sdk import AirflowException, conf from airflow.providers.opensearch.log.os_json_formatter import OpensearchJSONFormatter from airflow.providers.opensearch.log.os_response import Hit, OpensearchResponse -from airflow.providers.opensearch.version_compat import AIRFLOW_V_3_0_PLUS +from airflow.providers.opensearch.version_compat import AIRFLOW_V_3_0_PLUS, AIRFLOW_V_3_2_PLUS from airflow.utils import timezone from airflow.utils.log.file_task_handler import FileTaskHandler from airflow.utils.log.logging_mixin import ExternalLoggingMixin, LoggingMixin @@ -46,7 +51,8 @@ if TYPE_CHECKING: from airflow.models.taskinstance import TaskInstance, TaskInstanceKey - from airflow.utils.log.file_task_handler import LogMetadata + from airflow.sdk.types import RuntimeTaskInstanceProtocol as RuntimeTI + from airflow.utils.log.file_task_handler import LogMessages, LogMetadata, LogSourceInfo if AIRFLOW_V_3_0_PLUS: from airflow.utils.log.file_task_handler import StructuredLogMessage @@ -154,16 +160,88 @@ def get_os_kwargs_from_config() -> dict[str, Any]: return kwargs_dict +def _format_url(host: str) -> str: + """ + Format the given host string to ensure it starts with 'http' and check if it represents a valid URL. + + :params host: The host string to format and check. + """ + parsed_url = urlparse(host) + + if parsed_url.scheme not in ("http", "https"): + host = "http://" + host + parsed_url = urlparse(host) + + if not parsed_url.netloc: + raise ValueError(f"'{host}' is not a valid URL.") + + return host + + +def _create_opensearch_client( + host: str, + port: int | None, + username: str, + password: str, + os_kwargs: dict[str, Any], +) -> OpenSearch: + parsed_url = urlparse(_format_url(host)) + resolved_port = port if port is not None else (parsed_url.port or 9200) + return OpenSearch( + hosts=[{"host": parsed_url.hostname, "port": resolved_port, "scheme": parsed_url.scheme}], + http_auth=(username, password), + **os_kwargs, + ) + + +def _render_log_id( + log_id_template: str, ti: TaskInstance | TaskInstanceKey | RuntimeTI, try_number: int +) -> str: + return log_id_template.format( + dag_id=ti.dag_id, + task_id=ti.task_id, + run_id=getattr(ti, "run_id", ""), + try_number=try_number, + map_index=getattr(ti, "map_index", ""), + ) + + +def _resolve_nested(hit: dict[Any, Any], parent_class=None) -> type[Hit]: + """ + Resolve nested hits from OpenSearch by iteratively navigating the `_nested` field. + + The result is used to fetch the appropriate document class to handle the hit. + """ + doc_class = Hit + nested_field = None + + nested_path: list[str] = [] + nesting = hit["_nested"] + while nesting and "field" in nesting: + nested_path.append(nesting["field"]) + nesting = nesting.get("_nested") + nested_path_str = ".".join(nested_path) + + if hasattr(parent_class, "_index"): + nested_field = parent_class._index.resolve_field(nested_path_str) + + if nested_field is not None: + return nested_field._doc_class + + return doc_class + + class OpensearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMixin): """ - OpensearchTaskHandler is a Python log handler that reads and writes logs to OpenSearch. + OpensearchTaskHandler is a Python log handler that reads logs from OpenSearch. - Like the ElasticsearchTaskHandler, Airflow itself does not handle the indexing of logs. - Instead, logs are flushed to local files, and additional software (e.g., Filebeat, Logstash) - may be required to ship logs to OpenSearch. This handler then enables fetching and displaying - logs from OpenSearch. + Airflow flushes task logs to local files. Additional software setup can then ship those + logs to OpenSearch. On Airflow 3, this task handler also registers a matching + ``OpensearchRemoteLogIO`` so the new remote logging path can read from OpenSearch too. + Airflow can also be configured to write task logs to OpenSearch directly. To enable this + feature, set ``json_format`` and ``write_to_opensearch`` to ``True``. - To efficiently query and sort Elasticsearch results, this handler assumes each + To efficiently query and sort OpenSearch results, this handler assumes each log message has a field `log_id` consists of ti primary keys: `log_id = {dag_id}-{task_id}-{logical_date}-{try_number}` Log messages with specific log_id are sorted based on `offset`, @@ -180,6 +258,8 @@ class OpensearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMixin) :param port: OpenSearch port. :param username: Username for OpenSearch authentication. :param password: Password for OpenSearch authentication. + :param write_to_opensearch: Whether to write logs directly to OpenSearch. + :param target_index: Name of the index to write to when direct OpenSearch writes are enabled. :param host_field: The field name for the host in the logs (default is "host"). :param offset_field: The field name for the log offset (default is "offset"). :param index_patterns: Index pattern or template for storing logs. @@ -202,17 +282,22 @@ def __init__( json_format: bool, json_fields: str, host: str, - port: int, + port: int | None, username: str, password: str, + write_to_opensearch: bool = False, + target_index: str = "airflow-logs", host_field: str = "host", offset_field: str = "offset", index_patterns: str = conf.get("opensearch", "index_patterns", fallback="_all"), index_patterns_callable: str = conf.get("opensearch", "index_patterns_callable", fallback=""), + log_id_template: str = conf.get("opensearch", "log_id_template", fallback="") + or "{dag_id}-{task_id}-{run_id}-{map_index}-{try_number}", os_kwargs: dict | None | Literal["default_os_kwargs"] = "default_os_kwargs", max_bytes: int = 0, backup_count: int = 0, delay: bool = False, + **kwargs, ) -> None: os_kwargs = os_kwargs or {} if os_kwargs == "default_os_kwargs": @@ -225,23 +310,54 @@ def __init__( self.mark_end_on_close = True self.end_of_log_mark = end_of_log_mark.strip() self.write_stdout = write_stdout + self.write_to_opensearch = write_to_opensearch self.json_format = json_format self.json_fields = [label.strip() for label in json_fields.split(",")] self.host = self.format_url(host) self.host_field = host_field self.offset_field = offset_field + self.target_index = target_index self.index_patterns = index_patterns self.index_patterns_callable = index_patterns_callable self.context_set = False - self.client = OpenSearch( - hosts=[{"host": host, "port": port}], - http_auth=(username, password), - **os_kwargs, + self.client = _create_opensearch_client( + self.host, + port, + username, + password, + cast("dict[str, Any]", os_kwargs), ) + self.delete_local_copy = kwargs.get( + "delete_local_copy", conf.getboolean("logging", "delete_local_logs") + ) + self.log_id_template = log_id_template self.formatter: logging.Formatter - self.handler: logging.FileHandler | logging.StreamHandler + self.handler: logging.FileHandler | logging.StreamHandler | None = None self._doc_type_map: dict[Any, Any] = {} self._doc_type: list[Any] = [] + self.io = OpensearchRemoteLogIO( + host=self.host, + port=port, + username=username, + password=password, + write_to_opensearch=self.write_to_opensearch, + target_index=self.target_index, + write_stdout=self.write_stdout, + offset_field=self.offset_field, + host_field=self.host_field, + base_log_folder=base_log_folder, + delete_local_copy=self.delete_local_copy, + json_format=self.json_format, + log_id_template=self.log_id_template, + ) + if AIRFLOW_V_3_0_PLUS: + if AIRFLOW_V_3_2_PLUS: + from airflow.logging_config import _ActiveLoggingConfig, get_remote_task_log + + if get_remote_task_log() is None: + _ActiveLoggingConfig.set(self.io, None) + elif alc.REMOTE_TASK_LOG is None: # type: ignore[attr-defined] + alc.REMOTE_TASK_LOG = self.io # type: ignore[attr-defined] def set_context(self, ti: TaskInstance, *, identifier: str | None = None) -> None: """ @@ -342,6 +458,7 @@ def _clean_date(value: datetime | None) -> str: def _render_log_id(self, ti: TaskInstance | TaskInstanceKey, try_number: int) -> str: from airflow.models.taskinstance import TaskInstanceKey + log_id_template = self.log_id_template with create_session() as session: if isinstance(ti, TaskInstanceKey): ti = _ensure_ti(ti, session) @@ -393,9 +510,9 @@ def _read( offset = metadata["offset"] log_id = self._render_log_id(ti, try_number) - response = self._os_read(log_id, offset, ti) + response = self.io._os_read(log_id, offset, ti) if response is not None and response.hits: - logs_by_host = self._group_logs_by_host(response) + logs_by_host = self.io._group_logs_by_host(response) next_offset = attrgetter(self.offset_field)(response[-1]) else: logs_by_host = None @@ -410,7 +527,7 @@ def _read( # have the log uploaded but will not be stored in elasticsearch. metadata["end_of_log"] = False if logs_by_host: - if any(x[-1].message == self.end_of_log_mark for x in logs_by_host.values()): + if any(self._get_log_message(x[-1]) == self.end_of_log_mark for x in logs_by_host.values()): metadata["end_of_log"] = True cur_ts = pendulum.now() @@ -446,10 +563,6 @@ def _read( # If we hit the end of the log, remove the actual end_of_log message # to prevent it from showing in the UI. - def concat_logs(hits: list[Hit]): - log_range = (len(hits) - 1) if hits[-1].message == self.end_of_log_mark else len(hits) - return "\n".join(self._format_msg(hits[i]) for i in range(log_range)) - if logs_by_host: if AIRFLOW_V_3_0_PLUS: from airflow.utils.log.file_task_handler import StructuredLogMessage @@ -469,9 +582,10 @@ def concat_logs(hits: list[Hit]): for hit in hits ] else: - message = [(host, concat_logs(hits)) for host, hits in logs_by_host.items()] # type: ignore[misc] + message = [(host, self.concat_logs(hits)) for host, hits in logs_by_host.items()] # type: ignore[misc] else: message = [] + metadata["end_of_log"] = True return message, metadata def _os_read(self, log_id: str, offset: int | str, ti: TaskInstance) -> OpensearchResponse | None: @@ -576,7 +690,7 @@ def _get_result(self, hit: dict[Any, Any], parent_class=None) -> Hit: dt = hit.get("_type") if "_nested" in hit: - doc_class = self._resolve_nested(hit, parent_class) + doc_class = _resolve_nested(hit, parent_class) elif dt in self._doc_type_map: doc_class = self._doc_type_map[dt] @@ -594,32 +708,6 @@ def _get_result(self, hit: dict[Any, Any], parent_class=None) -> Hit: callback: type[Hit] | Callable[..., Any] = getattr(doc_class, "from_es", doc_class) return callback(hit) - def _resolve_nested(self, hit: dict[Any, Any], parent_class=None) -> type[Hit]: - """ - Resolve nested hits from Elasticsearch by iteratively navigating the `_nested` field. - - The result is used to fetch the appropriate document class to handle the hit. - - This method can be used with nested Elasticsearch fields which are structured - as dictionaries with "field" and "_nested" keys. - """ - doc_class = Hit - - nested_path: list[str] = [] - nesting = hit["_nested"] - while nesting and "field" in nesting: - nested_path.append(nesting["field"]) - nesting = nesting.get("_nested") - nested_path_str = ".".join(nested_path) - - if hasattr(parent_class, "_index"): - nested_field = parent_class._index.resolve_field(nested_path_str) - - if nested_field is not None: - return nested_field._doc_class - - return doc_class - def _group_logs_by_host(self, response: OpensearchResponse) -> dict[str, list[Hit]]: grouped_logs = defaultdict(list) for hit in response: @@ -638,7 +726,18 @@ def _format_msg(self, hit: Hit): ) # Just a safe-guard to preserve backwards-compatibility - return hit.message + return self._get_log_message(hit) + + def _get_log_message(self, hit: Hit) -> str: + if hasattr(hit, "event"): + return hit.event + if hasattr(hit, "message"): + return hit.message + return "" + + def concat_logs(self, hits: list[Hit]) -> str: + log_range = (len(hits) - 1) if self._get_log_message(hits[-1]) == self.end_of_log_mark else len(hits) + return "\n".join(self._format_msg(hits[i]) for i in range(log_range)) @property def supports_external_link(self) -> bool: @@ -664,18 +763,198 @@ def log_name(self) -> str: @staticmethod def format_url(host: str) -> str: + return _format_url(host) + + +@attrs.define(kw_only=True) +class OpensearchRemoteLogIO(LoggingMixin): # noqa: D101 + json_format: bool = False + write_stdout: bool = False + write_to_opensearch: bool = False + delete_local_copy: bool = False + host: str = "localhost" + port: int | None = 9200 + username: str = "" + password: str = "" + host_field: str = "host" + target_index: str = "airflow-logs" + offset_field: str = "offset" + base_log_folder: Path = attrs.field(converter=Path) + log_id_template: str = ( + conf.get("opensearch", "log_id_template", fallback="") + or "{dag_id}-{task_id}-{run_id}-{map_index}-{try_number}" + ) + + processors = () + + def __attrs_post_init__(self): + self.host = _format_url(self.host) + self.port = self.port if self.port is not None else (urlparse(self.host).port or 9200) + self.client = _create_opensearch_client( + self.host, + self.port, + self.username, + self.password, + get_os_kwargs_from_config(), + ) + self.index_patterns_callable = conf.get("opensearch", "index_patterns_callable", fallback="") + self.PAGE = 0 + self.MAX_LINE_PER_PAGE = 1000 + self.index_patterns = conf.get("opensearch", "index_patterns", fallback="_all") + self._doc_type_map: dict[Any, Any] = {} + self._doc_type: list[Any] = [] + + def upload(self, path: os.PathLike | str, ti: RuntimeTI): + """Emit structured task logs to stdout and/or write them directly to OpenSearch.""" + path = Path(path) + local_loc = path if path.is_absolute() else self.base_log_folder.joinpath(path) + if not local_loc.is_file(): + return + + log_id = _render_log_id(self.log_id_template, ti, ti.try_number) # type: ignore[arg-type] + if self.write_stdout or self.write_to_opensearch: + log_lines = self._parse_raw_log(local_loc.read_text(), log_id) + + if self.write_stdout: + for line in log_lines: + sys.stdout.write(json.dumps(line) + "\n") + sys.stdout.flush() + + if self.write_to_opensearch: + success = self._write_to_opensearch(log_lines) + if success and self.delete_local_copy: + local_loc.unlink(missing_ok=True) + base_dir = self.base_log_folder + parent = local_loc.parent + while parent != base_dir and parent.is_dir(): + if any(parent.iterdir()): + break + with contextlib.suppress(OSError): + parent.rmdir() + parent = parent.parent + + def _parse_raw_log(self, log: str, log_id: str) -> list[dict[str, Any]]: + parsed_logs = [] + offset = 1 + for line in log.split("\n"): + if not line.strip(): + continue + try: + log_dict = json.loads(line) + except json.JSONDecodeError: + self.log.warning("Skipping non-JSON log line: %r", line) + log_dict = {"event": line} + log_dict.update({"log_id": log_id, self.offset_field: offset}) + offset += 1 + parsed_logs.append(log_dict) + return parsed_logs + + def _write_to_opensearch(self, log_lines: list[dict[str, Any]]) -> bool: """ - Format the given host string to ensure it starts with 'http' and check if it represents a valid URL. + Write logs to OpenSearch; return `True` on success and `False` on failure. - :params host: The host string to format and check. + :param log_lines: The parsed log lines to write to OpenSearch. """ - parsed_url = urlparse(host) + bulk_actions = [{"_index": self.target_index, "_source": log} for log in log_lines] + try: + _ = helpers.bulk(self.client, bulk_actions) + return True + except helpers.BulkIndexError as bie: + self.log.exception("Bulk upload failed for %d log(s)", len(bie.errors)) + for error in bie.errors: + self.log.exception(error) + return False + except Exception as e: + self.log.exception("Unable to insert logs into OpenSearch. Reason: %s", str(e)) + return False + + def read(self, _relative_path: str, ti: RuntimeTI) -> tuple[LogSourceInfo, LogMessages]: + log_id = _render_log_id(self.log_id_template, ti, ti.try_number) # type: ignore[arg-type] + self.log.info("Reading log %s from Opensearch", log_id) + response = self._os_read(log_id, 0, ti) + if response is not None and response.hits: + logs_by_host = self._group_logs_by_host(response) + else: + logs_by_host = None - if parsed_url.scheme not in ("http", "https"): - host = "http://" + host - parsed_url = urlparse(host) + if logs_by_host is None: + missing_log_message = ( + f"*** Log {log_id} not found in Opensearch. " + "If your task started recently, please wait a moment and reload this page. " + "Otherwise, the logs for this task instance may have been removed." + ) + return [], [missing_log_message] - if not parsed_url.netloc: - raise ValueError(f"'{host}' is not a valid URL.") + header = list(logs_by_host.keys()) + message = [] + for hits in logs_by_host.values(): + for hit in hits: + message.append(json.dumps(_build_log_fields(hit.to_dict()))) + return header, message - return host + def _os_read(self, log_id: str, offset: int | str, ti: RuntimeTI) -> OpensearchResponse | None: + """Return the logs matching ``log_id`` in OpenSearch.""" + query: dict[Any, Any] = { + "query": { + "bool": { + "filter": [{"range": {self.offset_field: {"gt": int(offset)}}}], + "must": [{"match_phrase": {"log_id": log_id}}], + } + } + } + index_patterns = self._get_index_patterns(ti) + try: + max_log_line = self.client.count(index=index_patterns, body=query)["count"] + except NotFoundError as e: + self.log.exception("The target index pattern %s does not exist", index_patterns) + raise e + + if max_log_line != 0: + try: + res = self.client.search( + index=index_patterns, + body=query, + sort=[self.offset_field], + size=self.MAX_LINE_PER_PAGE, + from_=self.MAX_LINE_PER_PAGE * self.PAGE, + ) + return OpensearchResponse(self, res) + except Exception as err: + self.log.exception("Could not read log with log_id: %s. Exception: %s", log_id, err) + + return None + + def _get_index_patterns(self, ti: RuntimeTI | None) -> str: + if self.index_patterns_callable: + self.log.debug("Using index_patterns_callable: %s", self.index_patterns_callable) + index_pattern_callable_obj = import_string(self.index_patterns_callable) + return index_pattern_callable_obj(ti) + self.log.debug("Using index_patterns: %s", self.index_patterns) + return self.index_patterns + + def _group_logs_by_host(self, response: OpensearchResponse) -> dict[str, list[Hit]]: + grouped_logs = defaultdict(list) + for hit in response: + key = getattr_nested(hit, self.host_field, None) or self.host + grouped_logs[key].append(hit) + return grouped_logs + + def _get_result(self, hit: dict[Any, Any], parent_class=None) -> Hit: + doc_class = Hit + dt = hit.get("_type") + + if "_nested" in hit: + doc_class = _resolve_nested(hit, parent_class) + elif dt in self._doc_type_map: + doc_class = self._doc_type_map[dt] + else: + for doc_type in self._doc_type: + if hasattr(doc_type, "_matches") and doc_type._matches(hit): + doc_class = doc_type + break + + for t in hit.get("inner_hits", ()): + hit["inner_hits"][t] = OpensearchResponse(self, hit["inner_hits"][t], doc_class=doc_class) + + callback: type[Hit] | Callable[..., Any] = getattr(doc_class, "from_es", doc_class) + return callback(hit) diff --git a/providers/opensearch/src/airflow/providers/opensearch/version_compat.py b/providers/opensearch/src/airflow/providers/opensearch/version_compat.py index 613a946fc90b5..e840569a4d8a6 100644 --- a/providers/opensearch/src/airflow/providers/opensearch/version_compat.py +++ b/providers/opensearch/src/airflow/providers/opensearch/version_compat.py @@ -34,8 +34,10 @@ def get_base_airflow_version_tuple() -> tuple[int, int, int]: AIRFLOW_V_3_0_PLUS: bool = get_base_airflow_version_tuple() >= (3, 0, 0) AIRFLOW_V_3_1_PLUS: bool = get_base_airflow_version_tuple() >= (3, 1, 0) +AIRFLOW_V_3_2_PLUS: bool = get_base_airflow_version_tuple() >= (3, 2, 0) __all__ = [ "AIRFLOW_V_3_0_PLUS", "AIRFLOW_V_3_1_PLUS", + "AIRFLOW_V_3_2_PLUS", ] diff --git a/providers/opensearch/tests/integration/__init__.py b/providers/opensearch/tests/integration/__init__.py new file mode 100644 index 0000000000000..5966d6b1d5261 --- /dev/null +++ b/providers/opensearch/tests/integration/__init__.py @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +__path__ = __import__("pkgutil").extend_path(__path__, __name__) diff --git a/providers/opensearch/tests/integration/opensearch/__init__.py b/providers/opensearch/tests/integration/opensearch/__init__.py new file mode 100644 index 0000000000000..13a83393a9124 --- /dev/null +++ b/providers/opensearch/tests/integration/opensearch/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/providers/opensearch/tests/integration/opensearch/log/__init__.py b/providers/opensearch/tests/integration/opensearch/log/__init__.py new file mode 100644 index 0000000000000..13a83393a9124 --- /dev/null +++ b/providers/opensearch/tests/integration/opensearch/log/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/providers/opensearch/tests/integration/opensearch/log/test_os_remote_log_io.py b/providers/opensearch/tests/integration/opensearch/log/test_os_remote_log_io.py new file mode 100644 index 0000000000000..9aef477761888 --- /dev/null +++ b/providers/opensearch/tests/integration/opensearch/log/test_os_remote_log_io.py @@ -0,0 +1,140 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +import dataclasses +import json +import uuid +from unittest.mock import patch + +import pytest + +from airflow.providers.opensearch.log.os_task_handler import OpensearchRemoteLogIO, _render_log_id + +opensearchpy = pytest.importorskip("opensearchpy") + +# The OpenSearch service hostname as defined in scripts/ci/docker-compose/integration-opensearch.yml +OS_HOST = "http://opensearch" + + +@dataclasses.dataclass +class _MockTI: + """Minimal TaskInstance-like object satisfying the RuntimeTI protocol for log ID rendering.""" + + dag_id: str = "integration_test_dag" + task_id: str = "integration_test_task" + run_id: str = "integration_test_run" + try_number: int = 1 + map_index: int = -1 + + +@pytest.mark.integration("opensearch") +class TestOpensearchRemoteLogIOIntegration: + """ + Integration tests for OpensearchRemoteLogIO using the breeze opensearch service. + + These tests require the opensearch integration to be running: + breeze testing providers-integration-tests --integration opensearch + """ + + @pytest.fixture(autouse=True) + def setup(self, tmp_path): + self.target_index = f"airflow-logs-{uuid.uuid4().hex}" + self.opensearch_io = OpensearchRemoteLogIO( + write_to_opensearch=True, + write_stdout=False, + delete_local_copy=False, + host=OS_HOST, + port=9200, + username="", + password="", + base_log_folder=tmp_path, + target_index=self.target_index, + ) + self.opensearch_io.index_patterns = self.target_index + self.opensearch_io.client = opensearchpy.OpenSearch( + hosts=[{"host": "opensearch", "port": 9200, "scheme": "http"}] + ) + + @pytest.fixture + def ti(self): + return _MockTI() + + @pytest.fixture + def tmp_json_log_file(self, tmp_path): + log_file = tmp_path / "1.log" + sample_logs = [ + {"message": "start"}, + {"message": "processing"}, + {"message": "end"}, + ] + log_file.write_text("\n".join(json.dumps(log) for log in sample_logs) + "\n") + return log_file + + @patch( + "airflow.providers.opensearch.log.os_task_handler.TASK_LOG_FIELDS", + ["message"], + ) + def test_upload_and_read(self, tmp_json_log_file, ti): + self.opensearch_io.upload(tmp_json_log_file, ti) + self.opensearch_io.client.indices.refresh(index=self.target_index) + + log_source_info, log_messages = self.opensearch_io.read("", ti) + + assert log_source_info[0] == OS_HOST + assert len(log_messages) == 3 + + expected_messages = ["start", "processing", "end"] + for expected, log_message in zip(expected_messages, log_messages): + log_entry = json.loads(log_message) + assert "event" in log_entry + assert log_entry["event"] == expected + + def test_read_missing_log(self, ti): + self.opensearch_io.client.indices.create(index=self.target_index) + + log_source_info, log_messages = self.opensearch_io.read("", ti) + + assert log_source_info == [] + assert len(log_messages) == 1 + assert "not found in Opensearch" in log_messages[0] + + def test_read_error_detail_integration(self, ti): + error_detail = [ + { + "is_cause": False, + "frames": [{"filename": "/opt/airflow/dags/fail.py", "lineno": 13, "name": "log_and_raise"}], + "exc_type": "RuntimeError", + "exc_value": "Woopsie. Something went wrong.", + } + ] + body = { + "event": "Task failed with exception", + "log_id": _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number), + "offset": 1, + "error_detail": error_detail, + } + self.opensearch_io.client.index(index=self.target_index, body=body) + self.opensearch_io.client.indices.refresh(index=self.target_index) + + log_source_info, log_messages = self.opensearch_io.read("", ti) + + assert log_source_info[0] == OS_HOST + assert len(log_messages) == 1 + log_entry = json.loads(log_messages[0]) + assert "error_detail" in log_entry + assert log_entry["error_detail"] == error_detail diff --git a/providers/opensearch/tests/unit/opensearch/conftest.py b/providers/opensearch/tests/unit/opensearch/conftest.py index d58a4703e76cf..97256d4ac5da8 100644 --- a/providers/opensearch/tests/unit/opensearch/conftest.py +++ b/providers/opensearch/tests/unit/opensearch/conftest.py @@ -49,55 +49,6 @@ def index(self, document: dict, index_name: str, doc_id: int, **kwargs: Any) -> return doc_id -class MockClient: - def count(self, index: Any = None, body: Any = None): - return {"count": 1, "_shards": {"total": 1, "successful": 1, "skipped": 0, "failed": 0}} - - def search(self, index=None, body=None, sort=None, size=None, from_=None): - return self.sample_log_response() - - def sample_log_response(self): - return { - "_shards": {"failed": 0, "skipped": 0, "successful": 7, "total": 7}, - "hits": { - "hits": [ - { - "_id": "jdeZT4kBjAZqZnexVUxk", - "_source": { - "dag_id": "example_bash_operator", - "execution_date": "2023_07_09T07_47_32_000000", - "levelname": "INFO", - "message": "Some Message 1", - "event": "Some Message 1", - "task_id": "run_after_loop", - "try_number": "1", - "offset": 0, - }, - "_type": "_doc", - }, - { - "_id": "qteZT4kBjAZqZnexVUxl", - "_source": { - "dag_id": "example_bash_operator", - "execution_date": "2023_07_09T07_47_32_000000", - "levelname": "INFO", - "message": "Another Some Message 2", - "event": "Another Some Message 2", - "task_id": "run_after_loop", - "try_number": "1", - "offset": 1, - }, - "_type": "_doc", - }, - ], - "max_score": 2.482621, - "total": {"relation": "eq", "value": 36}, - }, - "timed_out": False, - "took": 7, - } - - @pytest.fixture def mock_hook(monkeypatch): monkeypatch.setattr(OpenSearchHook, "search", MockSearch.search) diff --git a/providers/opensearch/tests/unit/opensearch/log/test_os_task_handler.py b/providers/opensearch/tests/unit/opensearch/log/test_os_task_handler.py index 15aba25ae8bce..e66925c7e1066 100644 --- a/providers/opensearch/tests/unit/opensearch/log/test_os_task_handler.py +++ b/providers/opensearch/tests/unit/opensearch/log/test_os_task_handler.py @@ -17,13 +17,12 @@ # under the License. from __future__ import annotations +import dataclasses import json import logging -import os import re -import shutil from io import StringIO -from unittest import mock +from pathlib import Path from unittest.mock import Mock, patch import pendulum @@ -31,9 +30,14 @@ from opensearchpy.exceptions import NotFoundError from airflow.providers.common.compat.sdk import conf +from airflow.providers.opensearch.log.os_json_formatter import OpensearchJSONFormatter from airflow.providers.opensearch.log.os_response import OpensearchResponse from airflow.providers.opensearch.log.os_task_handler import ( + OpensearchRemoteLogIO, OpensearchTaskHandler, + _build_log_fields, + _format_error_detail, + _render_log_id, get_os_kwargs_from_config, getattr_nested, ) @@ -44,11 +48,19 @@ from tests_common.test_utils.config import conf_vars from tests_common.test_utils.db import clear_db_dags, clear_db_runs from tests_common.test_utils.version_compat import AIRFLOW_V_3_0_PLUS -from unit.opensearch.conftest import MockClient opensearchpy = pytest.importorskip("opensearchpy") +@dataclasses.dataclass +class _MockTI: + dag_id: str = "dag_for_testing_os_log_handler" + task_id: str = "task_for_testing_os_log_handler" + run_id: str = "run_for_testing_os_log_handler" + try_number: int = 1 + map_index: int = -1 + + def get_ti(dag_id, task_id, logical_date, create_task_instance): ti = create_task_instance( dag_id=dag_id, @@ -62,6 +74,75 @@ def get_ti(dag_id, task_id, logical_date, create_task_instance): return ti +def _build_os_search_response(*sources: dict, index: str = "test_index", doc_type: str = "_doc") -> dict: + hits = [ + { + "_id": str(i), + "_index": index, + "_score": 1.0, + "_source": source, + "_type": doc_type, + } + for i, source in enumerate(sources, start=1) + ] + return { + "_shards": {"failed": 0, "skipped": 0, "successful": 1, "total": 1}, + "hits": { + "hits": hits, + "max_score": 1.0, + "total": {"relation": "eq", "value": len(hits)}, + }, + "timed_out": False, + "took": 1, + } + + +def _make_os_response(search, *sources: dict) -> OpensearchResponse: + return OpensearchResponse(search, _build_os_search_response(*sources)) + + +def _metadata_from_result(metadatas): + return metadatas if AIRFLOW_V_3_0_PLUS else metadatas[0] + + +def _assert_log_events(logs, metadatas, *, expected_events: list[str], expected_sources: list[str]): + metadata = _metadata_from_result(metadatas) + if AIRFLOW_V_3_0_PLUS: + logs = list(logs) + assert logs[0].event == "::group::Log message source details" + assert logs[0].sources == expected_sources + assert logs[1].event == "::endgroup::" + assert [log.event for log in logs[2:]] == expected_events + else: + assert len(logs) == 1 + assert len(logs[0]) == 1 + assert logs[0][0][0] == expected_sources[0] + assert logs[0][0][1] == "\n".join(expected_events) + return metadata + + +def _assert_no_logs(logs, metadatas): + metadata = _metadata_from_result(metadatas) + if AIRFLOW_V_3_0_PLUS: + assert logs == [] + else: + assert logs == [[]] + return metadata + + +def _assert_missing_log_message(logs): + expected_pattern = r"^\*\*\* Log .* not found in Opensearch.*" + if AIRFLOW_V_3_0_PLUS: + logs = list(logs) + assert len(logs) == 1 + assert logs[0].event is not None + assert re.match(expected_pattern, logs[0].event) is not None + else: + assert len(logs) == 1 + assert len(logs[0]) == 1 + assert re.match(expected_pattern, logs[0][0][1]) is not None + + class TestOpensearchTaskHandler: DAG_ID = "dag_for_testing_os_task_handler" TASK_ID = "task_for_testing_os_log_handler" @@ -70,80 +151,83 @@ class TestOpensearchTaskHandler: JSON_LOG_ID = f"{DAG_ID}-{TASK_ID}-{OpensearchTaskHandler._clean_date(LOGICAL_DATE)}-1" FILENAME_TEMPLATE = "{try_number}.log" - # TODO: Remove when we stop testing for 2.11 compatibility @pytest.fixture(autouse=True) def _use_historical_filename_templates(self): with conf_vars({("core", "use_historical_filename_templates"): "True"}): yield - @pytest.fixture - def ti(self, create_task_instance, create_log_template): - if AIRFLOW_V_3_0_PLUS: - create_log_template(self.FILENAME_TEMPLATE, "{dag_id}-{task_id}-{logical_date}-{try_number}") - else: - create_log_template( - self.FILENAME_TEMPLATE, - "{dag_id}-{task_id}-{execution_date}-{try_number}", - ) - yield get_ti( - dag_id=self.DAG_ID, - task_id=self.TASK_ID, - logical_date=self.LOGICAL_DATE, - create_task_instance=create_task_instance, - ) - clear_db_runs() - clear_db_dags() - - def setup_method(self): - self.local_log_location = "local/log/location" + @pytest.fixture(autouse=True) + def _setup_handler(self, tmp_path): + self.local_log_location = str(tmp_path / "logs") self.end_of_log_mark = "end_of_log\n" self.write_stdout = False self.json_format = False self.json_fields = "asctime,filename,lineno,levelname,message,exc_text" self.host_field = "host" self.offset_field = "offset" - self.username = "admin" - self.password = "admin" - self.host = "localhost" - self.port = 9200 + self.test_message = "Some Message 1" + self.base_log_source = { + "message": self.test_message, + "event": self.test_message, + "log_id": self.LOG_ID, + "offset": 1, + } self.os_task_handler = OpensearchTaskHandler( base_log_folder=self.local_log_location, end_of_log_mark=self.end_of_log_mark, write_stdout=self.write_stdout, - host=self.host, - port=self.port, - username=self.username, - password=self.password, + host="localhost", + port=9200, + username="admin", + password="admin", json_format=self.json_format, json_fields=self.json_fields, host_field=self.host_field, offset_field=self.offset_field, ) - self.os_task_handler.client = MockClient() - - def teardown_method(self): - shutil.rmtree(self.local_log_location.split(os.path.sep)[0], ignore_errors=True) - - def test_os_response(self): - sample_response = self.os_task_handler.client.sample_log_response() - response = OpensearchResponse(self.os_task_handler, sample_response) - logs_by_host = self.os_task_handler._group_logs_by_host(response) - - def concat_logs(lines): - log_range = -1 if lines[-1].message == self.os_task_handler.end_of_log_mark else None - return "\n".join(self.os_task_handler._format_msg(line) for line in lines[:log_range]) - - for hosted_log in logs_by_host.values(): - message = concat_logs(hosted_log) + @pytest.fixture + def ti(self, create_task_instance, create_log_template): + create_log_template( + self.FILENAME_TEMPLATE, + ( + "{dag_id}-{task_id}-{logical_date}-{try_number}" + if AIRFLOW_V_3_0_PLUS + else "{dag_id}-{task_id}-{execution_date}-{try_number}" + ), + ) + yield get_ti( + dag_id=self.DAG_ID, + task_id=self.TASK_ID, + logical_date=self.LOGICAL_DATE, + create_task_instance=create_task_instance, + ) + clear_db_runs() + clear_db_dags() - assert message == "Some Message 1\nAnother Some Message 2" + @pytest.mark.parametrize( + ("host", "expected"), + [ + ("http://localhost", "http://localhost"), + ("https://localhost", "https://localhost"), + ("localhost", "http://localhost"), + ("someurl", "http://someurl"), + ("https://", "ValueError"), + ], + ) + def test_format_url(self, host, expected): + if expected == "ValueError": + with pytest.raises(ValueError, match="'https://' is not a valid URL."): + OpensearchTaskHandler.format_url(host) + else: + assert OpensearchTaskHandler.format_url(host) == expected def test_client(self): + assert isinstance(self.os_task_handler.client, opensearchpy.OpenSearch) assert self.os_task_handler.index_patterns == "_all" def test_client_with_config(self): - config = dict(conf.getsection("opensearch_configs")) + os_conf = dict(conf.getsection("opensearch_configs")) expected_dict = { "http_compress": False, "use_ssl": False, @@ -152,34 +236,32 @@ def test_client_with_config(self): "ssl_show_warn": False, "ca_certs": "", } - assert config == expected_dict - # ensure creating with configs does not fail + assert os_conf == expected_dict OpensearchTaskHandler( base_log_folder=self.local_log_location, end_of_log_mark=self.end_of_log_mark, write_stdout=self.write_stdout, - host=self.host, - port=self.port, - username=self.username, - password=self.password, + host="localhost", + port=9200, + username="admin", + password="admin", json_format=self.json_format, json_fields=self.json_fields, host_field=self.host_field, offset_field=self.offset_field, - os_kwargs=config, + os_kwargs=os_conf, ) def test_client_with_patterns(self): - # ensure creating with index patterns does not fail patterns = "test_*,other_*" handler = OpensearchTaskHandler( base_log_folder=self.local_log_location, end_of_log_mark=self.end_of_log_mark, write_stdout=self.write_stdout, - host=self.host, - port=self.port, - username=self.username, - password=self.password, + host="localhost", + port=9200, + username="admin", + password="admin", json_format=self.json_format, json_fields=self.json_fields, host_field=self.host_field, @@ -189,197 +271,113 @@ def test_client_with_patterns(self): assert handler.index_patterns == patterns @pytest.mark.db_test - def test_read(self, ti): - ts = pendulum.now() - logs, metadatas = self.os_task_handler.read( - ti, 1, {"offset": 0, "last_log_timestamp": str(ts), "end_of_log": False} - ) + @pytest.mark.parametrize("metadata_mode", ["provided", "none", "empty"]) + def test_read(self, ti, metadata_mode): + start_time = pendulum.now() + response = _make_os_response(self.os_task_handler.io, self.base_log_source) - if AIRFLOW_V_3_0_PLUS: - logs = list(logs) - expected_msg = "Some Message 1" - assert logs[0].event == "::group::Log message source details" - assert logs[0].sources == ["http://localhost"] - assert logs[1].event == "::endgroup::" - assert logs[2].event == expected_msg - metadata = metadatas - else: - expected_msg = "Some Message 1\nAnother Some Message 2" - assert len(logs) == 1 - assert len(logs) == len(metadatas) - assert len(logs[0]) == 1 - assert logs[0][0][-1] == expected_msg + with patch.object(self.os_task_handler.io, "_os_read", return_value=response): + if metadata_mode == "provided": + logs, metadatas = self.os_task_handler.read( + ti, + 1, + {"offset": 0, "last_log_timestamp": str(start_time), "end_of_log": False}, + ) + elif metadata_mode == "empty": + logs, metadatas = self.os_task_handler.read(ti, 1, {}) + else: + logs, metadatas = self.os_task_handler.read(ti, 1) - metadata = metadatas[0] + metadata = _assert_log_events( + logs, + metadatas, + expected_events=[self.test_message], + expected_sources=["http://localhost"], + ) assert not metadata["end_of_log"] - assert timezone.parse(metadata["last_log_timestamp"]) > ts + assert metadata["offset"] == "1" + assert timezone.parse(metadata["last_log_timestamp"]) >= start_time @pytest.mark.db_test - def test_read_with_patterns(self, ti): - ts = pendulum.now() - with mock.patch.object(self.os_task_handler, "index_patterns", new="test_*,other_*"): - logs, metadatas = self.os_task_handler.read( - ti, 1, {"offset": 0, "last_log_timestamp": str(ts), "end_of_log": False} - ) - - if AIRFLOW_V_3_0_PLUS: - logs = list(logs) - expected_msg = "Some Message 1" - assert logs[0].event == "::group::Log message source details" - assert logs[0].sources == ["http://localhost"] - assert logs[1].event == "::endgroup::" - assert logs[2].event == expected_msg - metadata = metadatas - else: - expected_msg = "Some Message 1\nAnother Some Message 2" - assert len(logs) == 1 - assert len(logs) == len(metadatas) - assert len(logs[0]) == 1 - assert logs[0][0][-1] == expected_msg - - metadata = metadatas[0] + def test_read_defaults_offset_when_missing_from_metadata(self, ti): + start_time = pendulum.now() + with patch.object(self.os_task_handler.io, "_os_read", return_value=None): + logs, metadatas = self.os_task_handler.read(ti, 1, {"end_of_log": False}) - assert not metadata["end_of_log"] - assert timezone.parse(metadata["last_log_timestamp"]) > ts + metadata = _assert_no_logs(logs, metadatas) + assert metadata["end_of_log"] + assert metadata["offset"] == "0" + assert timezone.parse(metadata["last_log_timestamp"]) >= start_time @pytest.mark.db_test - def test_read_with_patterns_no_match(self, ti): - ts = pendulum.now() - with mock.patch.object(self.os_task_handler, "index_patterns", new="test_other_*,test_another_*"): - with mock.patch.object( - self.os_task_handler.client, - "search", - return_value={ - "_shards": {"failed": 0, "skipped": 0, "successful": 7, "total": 7}, - "hits": {"hits": []}, - "timed_out": False, - "took": 7, - }, - ): - logs, metadatas = self.os_task_handler.read( - ti, - 1, - {"offset": 0, "last_log_timestamp": str(ts), "end_of_log": False}, - ) - if AIRFLOW_V_3_0_PLUS: - assert logs == [] + @pytest.mark.parametrize("seconds", [3, 6]) + def test_read_missing_logs(self, ti, seconds): + start_time = pendulum.now().add(seconds=-seconds) + with patch.object(self.os_task_handler.io, "_os_read", return_value=None): + logs, metadatas = self.os_task_handler.read( + ti, + 1, + {"offset": 0, "last_log_timestamp": str(start_time), "end_of_log": False}, + ) - metadata = metadatas + metadata = _metadata_from_result(metadatas) + if seconds > 5: + _assert_missing_log_message(logs) else: - assert len(logs) == 1 - assert len(logs) == len(metadatas) - assert logs == [[]] - - metadata = metadatas[0] + _assert_no_logs(logs, metadatas) - assert not metadata["end_of_log"] + assert metadata["end_of_log"] assert metadata["offset"] == "0" - # last_log_timestamp won't change if no log lines read. - assert timezone.parse(metadata["last_log_timestamp"]) == ts + assert timezone.parse(metadata["last_log_timestamp"]) == start_time @pytest.mark.db_test - def test_read_with_missing_index(self, ti): - ts = pendulum.now() - with mock.patch.object(self.os_task_handler, "index_patterns", new="nonexistent,test_*"): - with mock.patch.object( - self.os_task_handler.client, - "count", - side_effect=NotFoundError(404, "IndexNotFoundError"), - ): - with pytest.raises(NotFoundError, match=r"IndexNotFoundError"): - self.os_task_handler.read( - ti, - 1, - { - "offset": 0, - "last_log_timestamp": str(ts), - "end_of_log": False, - }, - ) + def test_read_timeout(self, ti): + start_time = pendulum.now().subtract(minutes=5) + with patch.object(self.os_task_handler.io, "_os_read", return_value=None): + logs, metadatas = self.os_task_handler.read( + ti, + 1, + {"offset": 1, "last_log_timestamp": str(start_time), "end_of_log": False}, + ) - @pytest.mark.parametrize("seconds", [3, 6]) - @pytest.mark.db_test - def test_read_missing_logs(self, seconds, create_task_instance): - """ - When the log actually isn't there to be found, we only want to wait for 5 seconds. - In this case we expect to receive a message of the form 'Log {log_id} not found in Opensearch ...' - """ - ti = get_ti( - self.DAG_ID, - self.TASK_ID, - pendulum.instance(self.LOGICAL_DATE).add(days=1), # so logs are not found - create_task_instance=create_task_instance, - ) - ts = pendulum.now().add(seconds=-seconds) - with mock.patch.object( - self.os_task_handler.client, - "search", - return_value={ - "_shards": {"failed": 0, "skipped": 0, "successful": 7, "total": 7}, - "hits": {"hits": []}, - "timed_out": False, - "took": 7, - }, - ): - logs, metadatas = self.os_task_handler.read(ti, 1, {"offset": 0, "last_log_timestamp": str(ts)}) - if AIRFLOW_V_3_0_PLUS: - logs = list(logs) - if seconds > 5: - # we expect a log not found message when checking began more than 5 seconds ago - assert len(logs) == 1 - actual_message = logs[0].event - expected_pattern = r"^\*\*\* Log .* not found in Opensearch.*" - assert re.match(expected_pattern, actual_message) is not None - assert metadatas["end_of_log"] is True - else: - # we've "waited" less than 5 seconds so it should not be "end of log" and should be no log message - assert logs == [] - assert metadatas["end_of_log"] is False - assert metadatas["offset"] == "0" - assert timezone.parse(metadatas["last_log_timestamp"]) == ts - else: - assert len(logs) == 1 - if seconds > 5: - # we expect a log not found message when checking began more than 5 seconds ago - assert len(logs[0]) == 1 - actual_message = logs[0][0][1] - expected_pattern = r"^\*\*\* Log .* not found in Opensearch.*" - assert re.match(expected_pattern, actual_message) is not None - assert metadatas[0]["end_of_log"] is True - else: - # we've "waited" less than 5 seconds so it should not be "end of log" and should be no log message - assert len(logs[0]) == 0 - assert logs == [[]] - assert metadatas[0]["end_of_log"] is False - assert len(logs) == len(metadatas) - assert metadatas[0]["offset"] == "0" - assert timezone.parse(metadatas[0]["last_log_timestamp"]) == ts + metadata = _assert_no_logs(logs, metadatas) + assert metadata["end_of_log"] + assert metadata["offset"] == "1" + assert timezone.parse(metadata["last_log_timestamp"]) == start_time @pytest.mark.db_test - def test_read_with_none_metadata(self, ti): - logs, metadatas = self.os_task_handler.read(ti, 1) - - if AIRFLOW_V_3_0_PLUS: - logs = list(logs) - expected_message = "Some Message 1" - assert logs[0].event == "::group::Log message source details" - assert logs[0].sources == ["http://localhost"] - assert logs[1].event == "::endgroup::" - assert logs[2].event == expected_message - - metadata = metadatas - else: - expected_message = "Some Message 1\nAnother Some Message 2" - assert len(logs) == 1 - assert len(logs) == len(metadatas) - assert len(logs[0]) == 1 - assert logs[0][0][-1] == expected_message + def test_read_with_custom_offset_and_host_fields(self, ti): + self.os_task_handler.host_field = "host.name" + self.os_task_handler.offset_field = "log.offset" + self.os_task_handler.io.host_field = "host.name" + self.os_task_handler.io.offset_field = "log.offset" + response = _make_os_response( + self.os_task_handler.io, + { + "message": self.test_message, + "event": self.test_message, + "log_id": self.LOG_ID, + "log": {"offset": 1}, + "host": {"name": "somehostname"}, + }, + ) - metadata = metadatas[0] + with patch.object(self.os_task_handler.io, "_os_read", return_value=response): + logs, metadatas = self.os_task_handler.read( + ti, + 1, + {"offset": 0, "last_log_timestamp": str(pendulum.now()), "end_of_log": False}, + ) + metadata = _assert_log_events( + logs, + metadatas, + expected_events=[self.test_message], + expected_sources=["somehostname"], + ) + assert metadata["offset"] == "1" assert not metadata["end_of_log"] - assert timezone.parse(metadata["last_log_timestamp"]) < pendulum.now() @pytest.mark.db_test def test_set_context(self, ti): @@ -388,27 +386,29 @@ def test_set_context(self, ti): @pytest.mark.db_test def test_set_context_w_json_format_and_write_stdout(self, ti): - formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") - self.os_task_handler.formatter = formatter + self.os_task_handler.formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + ) self.os_task_handler.write_stdout = True self.os_task_handler.json_format = True + self.os_task_handler.set_context(ti) + assert isinstance(self.os_task_handler.formatter, OpensearchJSONFormatter) + assert isinstance(self.os_task_handler.handler, logging.StreamHandler) + assert self.os_task_handler.context_set + @pytest.mark.db_test def test_close(self, ti): - formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") - self.os_task_handler.formatter = formatter + self.os_task_handler.formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + ) self.os_task_handler.set_context(ti) self.os_task_handler.close() - with open( - os.path.join(self.local_log_location, self.FILENAME_TEMPLATE.format(try_number=1)) - ) as log_file: - # end_of_log_mark may contain characters like '\n' which is needed to - # have the log uploaded but will not be stored in elasticsearch. - # so apply the strip() to log_file.read() - log_line = log_file.read().strip() - assert log_line.endswith(self.end_of_log_mark.strip()) + + log_file = Path(self.local_log_location) / self.FILENAME_TEMPLATE.format(try_number=1) + assert log_file.read_text().strip().endswith(self.end_of_log_mark.strip()) assert self.os_task_handler.closed @pytest.mark.db_test @@ -416,51 +416,34 @@ def test_close_no_mark_end(self, ti): ti.raw = True self.os_task_handler.set_context(ti) self.os_task_handler.close() - with open( - os.path.join(self.local_log_location, self.FILENAME_TEMPLATE.format(try_number=1)) - ) as log_file: - assert self.end_of_log_mark not in log_file.read() - assert self.os_task_handler.closed - @pytest.mark.db_test - def test_close_closed(self, ti): - self.os_task_handler.closed = True - self.os_task_handler.set_context(ti) - self.os_task_handler.close() - with open( - os.path.join(self.local_log_location, self.FILENAME_TEMPLATE.format(try_number=1)) - ) as log_file: - assert len(log_file.read()) == 0 + log_file = Path(self.local_log_location) / self.FILENAME_TEMPLATE.format(try_number=1) + assert self.end_of_log_mark not in log_file.read_text() + assert self.os_task_handler.closed @pytest.mark.db_test def test_close_with_no_handler(self, ti): self.os_task_handler.set_context(ti) self.os_task_handler.handler = None self.os_task_handler.close() - with open( - os.path.join(self.local_log_location, self.FILENAME_TEMPLATE.format(try_number=1)) - ) as log_file: - assert len(log_file.read()) == 0 + + log_file = Path(self.local_log_location) / self.FILENAME_TEMPLATE.format(try_number=1) + assert log_file.read_text() == "" assert self.os_task_handler.closed @pytest.mark.db_test - def test_close_with_no_stream(self, ti): + @pytest.mark.parametrize("stream_state", ["none", "closed"]) + def test_close_reopens_stream(self, ti, stream_state): self.os_task_handler.set_context(ti) - self.os_task_handler.handler.stream = None - self.os_task_handler.close() - with open( - os.path.join(self.local_log_location, self.FILENAME_TEMPLATE.format(try_number=1)) - ) as log_file: - assert self.end_of_log_mark in log_file.read() - assert self.os_task_handler.closed + if stream_state == "none": + self.os_task_handler.handler.stream = None + else: + self.os_task_handler.handler.stream.close() - self.os_task_handler.set_context(ti) - self.os_task_handler.handler.stream.close() self.os_task_handler.close() - with open( - os.path.join(self.local_log_location, self.FILENAME_TEMPLATE.format(try_number=1)) - ) as log_file: - assert self.end_of_log_mark in log_file.read() + + log_file = Path(self.local_log_location) / self.FILENAME_TEMPLATE.format(try_number=1) + assert self.end_of_log_mark in log_file.read_text() assert self.os_task_handler.closed @pytest.mark.db_test @@ -471,21 +454,20 @@ def test_render_log_id(self, ti): assert self.os_task_handler._render_log_id(ti, 1) == self.JSON_LOG_ID def test_clean_date(self): - clean_execution_date = self.os_task_handler._clean_date(datetime(2016, 7, 8, 9, 10, 11, 12)) - assert clean_execution_date == "2016_07_08T09_10_11_000012" + clean_logical_date = OpensearchTaskHandler._clean_date(datetime(2016, 7, 8, 9, 10, 11, 12)) + assert clean_logical_date == "2016_07_08T09_10_11_000012" - @mock.patch("sys.__stdout__", new_callable=StringIO) @pytest.mark.db_test + @patch("sys.__stdout__", new_callable=StringIO) def test_dynamic_offset(self, stdout_mock, ti, time_machine): - # arrange handler = OpensearchTaskHandler( base_log_folder=self.local_log_location, end_of_log_mark=self.end_of_log_mark, write_stdout=True, - host=self.host, - port=self.port, - username=self.username, - password=self.password, + host="localhost", + port=9200, + username="admin", + password="admin", json_format=True, json_fields=self.json_fields, host_field=self.host_field, @@ -493,7 +475,7 @@ def test_dynamic_offset(self, stdout_mock, ti, time_machine): ) handler.formatter = logging.Formatter() - logger = logging.getLogger(__name__) + logger = logging.getLogger("tests.opensearch.dynamic_offset") logger.handlers = [handler] logger.propagate = False @@ -501,17 +483,19 @@ def test_dynamic_offset(self, stdout_mock, ti, time_machine): handler.set_context(ti) t1 = pendulum.local(year=2017, month=1, day=1, hour=1, minute=1, second=15) - t2, t3 = t1 + pendulum.duration(seconds=5), t1 + pendulum.duration(seconds=10) - - # act - time_machine.move_to(t1, tick=False) - ti.log.info("Test") - time_machine.move_to(t2, tick=False) - ti.log.info("Test2") - time_machine.move_to(t3, tick=False) - ti.log.info("Test3") + t2 = t1 + pendulum.duration(seconds=5) + t3 = t1 + pendulum.duration(seconds=10) + + try: + time_machine.move_to(t1, tick=False) + ti.log.info("Test") + time_machine.move_to(t2, tick=False) + ti.log.info("Test2") + time_machine.move_to(t3, tick=False) + ti.log.info("Test3") + finally: + logger.handlers = [] - # assert first_log, second_log, third_log = map(json.loads, stdout_mock.getvalue().strip().splitlines()) assert first_log["offset"] < second_log["offset"] < third_log["offset"] assert first_log["asctime"] == t1.format("YYYY-MM-DDTHH:mm:ss.SSSZZ") @@ -523,81 +507,212 @@ def test_get_index_patterns_with_callable(self): mock_callable = Mock(return_value="callable_index_pattern") mock_import_string.return_value = mock_callable - self.os_task_handler.index_patterns_callable = "path.to.index_pattern_callable" - result = self.os_task_handler._get_index_patterns({}) - - mock_import_string.assert_called_once_with("path.to.index_pattern_callable") - mock_callable.assert_called_once_with({}) - assert result == "callable_index_pattern" - - -def test_safe_attrgetter(): - class A: ... - - a = A() - a.b = "b" - a.c = None - a.x = a - a.x.d = "blah" - assert getattr_nested(a, "b", None) == "b" # regular getattr - assert getattr_nested(a, "x.d", None) == "blah" # nested val - assert getattr_nested(a, "aa", "heya") == "heya" # respects non-none default - assert getattr_nested(a, "c", "heya") is None # respects none value - assert getattr_nested(a, "aa", None) is None # respects none default - - -def test_retrieve_config_keys(): - """ - Tests that the OpensearchTaskHandler retrieves the correct configuration keys from the config file. - * old_parameters are removed - * parameters from config are automatically added - * constructor parameters missing from config are also added - :return: - """ - with conf_vars( - { - ("opensearch_configs", "http_compress"): "False", - ("opensearch_configs", "timeout"): "10", + self.os_task_handler.io.index_patterns_callable = "path.to.index_pattern_callable" + result = self.os_task_handler.io._get_index_patterns({}) + + mock_import_string.assert_called_once_with("path.to.index_pattern_callable") + mock_callable.assert_called_once_with({}) + assert result == "callable_index_pattern" + + +class TestTaskHandlerHelpers: + def test_safe_attrgetter(self): + class A: ... + + a = A() + a.b = "b" + a.c = None + a.x = a + a.x.d = "blah" + assert getattr_nested(a, "b", None) == "b" + assert getattr_nested(a, "x.d", None) == "blah" + assert getattr_nested(a, "aa", "heya") == "heya" + assert getattr_nested(a, "c", "heya") is None + assert getattr_nested(a, "aa", None) is None + + def test_retrieve_config_keys(self): + with conf_vars( + { + ("opensearch_configs", "http_compress"): "False", + ("opensearch_configs", "timeout"): "10", + } + ): + args_from_config = get_os_kwargs_from_config().keys() + assert "verify_certs" in args_from_config + assert "timeout" in args_from_config + assert "http_compress" in args_from_config + assert "self" not in args_from_config + + +class TestOpensearchRemoteLogIO: + @pytest.fixture(autouse=True) + def _setup_tests(self, tmp_path): + self.opensearch_io = OpensearchRemoteLogIO( + write_to_opensearch=True, + write_stdout=True, + delete_local_copy=True, + host="localhost", + port=9200, + username="admin", + password="admin", + base_log_folder=tmp_path, + log_id_template="{dag_id}-{task_id}-{run_id}-{map_index}-{try_number}", + ) + + @pytest.fixture + def ti(self): + return _MockTI() + + @pytest.fixture + def tmp_json_file(self, tmp_path): + file_path = tmp_path / "1.log" + sample_logs = [ + {"message": "start"}, + {"message": "processing"}, + {"message": "end"}, + ] + file_path.write_text("\n".join(json.dumps(log) for log in sample_logs) + "\n") + return file_path + + def test_write_to_stdout(self, tmp_json_file, ti, capsys): + self.opensearch_io.write_to_opensearch = False + self.opensearch_io.upload(tmp_json_file, ti) + + captured = capsys.readouterr() + stdout_lines = captured.out.strip().splitlines() + log_entries = [json.loads(line) for line in stdout_lines] + assert [entry["message"] for entry in log_entries] == ["start", "processing", "end"] + + def test_invalid_task_log_file_path(self, ti): + with ( + patch.object(self.opensearch_io, "_parse_raw_log") as mock_parse, + patch.object(self.opensearch_io, "_write_to_opensearch") as mock_write, + ): + self.opensearch_io.upload(Path("/invalid/path"), ti) + + mock_parse.assert_not_called() + mock_write.assert_not_called() + + def test_write_to_opensearch(self, tmp_json_file, ti): + self.opensearch_io.write_stdout = False + log_id = _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number) + expected_log_lines = self.opensearch_io._parse_raw_log(tmp_json_file.read_text(), log_id) + + with patch.object(self.opensearch_io, "_write_to_opensearch", return_value=True) as mock_write: + self.opensearch_io.upload(tmp_json_file, ti) + + mock_write.assert_called_once_with(expected_log_lines) + + def test_raw_log_contains_log_id_and_offset(self, tmp_json_file, ti): + raw_log = tmp_json_file.read_text() + log_id = _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number) + json_log_lines = self.opensearch_io._parse_raw_log(raw_log, log_id) + + assert len(json_log_lines) == 3 + assert [line["offset"] for line in json_log_lines] == [1, 2, 3] + assert all(line["log_id"] == log_id for line in json_log_lines) + + def test_os_read_builds_expected_query(self, ti): + self.opensearch_io.client = Mock() + self.opensearch_io.client.count.return_value = {"count": 1} + self.opensearch_io.client.search.return_value = _build_os_search_response( + { + "event": "hello", + "log_id": _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number), + "offset": 3, + } + ) + self.opensearch_io.index_patterns = "airflow-logs-*" + log_id = _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number) + query = { + "query": { + "bool": { + "filter": [{"range": {self.opensearch_io.offset_field: {"gt": 2}}}], + "must": [{"match_phrase": {"log_id": log_id}}], + } + } } - ): - args_from_config = get_os_kwargs_from_config().keys() - # verify_certs comes from default config value - assert "verify_certs" in args_from_config - # timeout comes from config provided value - assert "timeout" in args_from_config - # http_compress comes from config value - assert "http_compress" in args_from_config - assert "self" not in args_from_config + response = self.opensearch_io._os_read(log_id, 2, ti) -# --------------------------------------------------------------------------- -# Tests for the error_detail helpers (issue #63736) -# --------------------------------------------------------------------------- + self.opensearch_io.client.count.assert_called_once_with(index="airflow-logs-*", body=query) + self.opensearch_io.client.search.assert_called_once_with( + index="airflow-logs-*", + body=query, + sort=[self.opensearch_io.offset_field], + size=self.opensearch_io.MAX_LINE_PER_PAGE, + from_=0, + ) + assert response is not None + assert response.hits[0].event == "hello" + def test_os_read_returns_none_when_count_is_zero(self, ti): + self.opensearch_io.client = Mock() + self.opensearch_io.client.count.return_value = {"count": 0} -class TestFormatErrorDetail: - """Unit tests for _format_error_detail.""" + log_id = _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number) + response = self.opensearch_io._os_read(log_id, 0, ti) - def test_returns_none_for_empty(self): - from airflow.providers.opensearch.log.os_task_handler import _format_error_detail + assert response is None + self.opensearch_io.client.search.assert_not_called() + + def test_os_read_propagates_missing_index(self, ti): + self.opensearch_io.client = Mock() + self.opensearch_io.client.count.side_effect = NotFoundError( + 404, + "IndexMissingException[[missing] missing]", + ) + + log_id = _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number) + with pytest.raises(NotFoundError): + self.opensearch_io._os_read(log_id, 0, ti) + + def test_os_read_logs_and_returns_none_on_search_error(self, ti): + self.opensearch_io.client = Mock() + self.opensearch_io.client.count.return_value = {"count": 1} + self.opensearch_io.client.search.side_effect = RuntimeError("boom") + + log_id = _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number) + with patch.object(self.opensearch_io.log, "exception") as mock_exception: + response = self.opensearch_io._os_read(log_id, 0, ti) + + assert response is None + mock_exception.assert_called_once() + def test_read_returns_missing_log_message_when_os_read_returns_none(self, ti): + with patch.object(self.opensearch_io, "_os_read", return_value=None): + log_source_info, log_messages = self.opensearch_io.read("", ti) + + log_id = _render_log_id(self.opensearch_io.log_id_template, ti, ti.try_number) + assert log_source_info == [] + assert f"*** Log {log_id} not found in Opensearch" in log_messages[0] + + def test_get_index_patterns_with_callable(self): + with patch("airflow.providers.opensearch.log.os_task_handler.import_string") as mock_import_string: + mock_callable = Mock(return_value="callable_index_pattern") + mock_import_string.return_value = mock_callable + + self.opensearch_io.index_patterns_callable = "path.to.index_pattern_callable" + result = self.opensearch_io._get_index_patterns({}) + + mock_import_string.assert_called_once_with("path.to.index_pattern_callable") + mock_callable.assert_called_once_with({}) + assert result == "callable_index_pattern" + + +class TestFormatErrorDetail: + def test_returns_none_for_empty(self): assert _format_error_detail(None) is None assert _format_error_detail([]) is None def test_returns_string_for_non_list(self): - from airflow.providers.opensearch.log.os_task_handler import _format_error_detail - assert _format_error_detail("raw string") == "raw string" def test_formats_single_exception(self): - from airflow.providers.opensearch.log.os_task_handler import _format_error_detail - error_detail = [ { "is_cause": False, - "frames": [ - {"filename": "/app/task.py", "lineno": 13, "name": "log_and_raise"}, - ], + "frames": [{"filename": "/app/task.py", "lineno": 13, "name": "log_and_raise"}], "exc_type": "RuntimeError", "exc_value": "Something went wrong.", "exceptions": [], @@ -611,8 +726,6 @@ def test_formats_single_exception(self): assert "RuntimeError: Something went wrong." in result def test_formats_chained_exceptions(self): - from airflow.providers.opensearch.log.os_task_handler import _format_error_detail - error_detail = [ { "is_cause": True, @@ -636,8 +749,6 @@ def test_formats_chained_exceptions(self): assert "RuntimeError: wrapped" in result def test_exc_type_without_value(self): - from airflow.providers.opensearch.log.os_task_handler import _format_error_detail - error_detail = [ { "is_cause": False, @@ -651,19 +762,13 @@ def test_exc_type_without_value(self): assert result.endswith("StopIteration") def test_non_dict_items_are_stringified(self): - from airflow.providers.opensearch.log.os_task_handler import _format_error_detail - result = _format_error_detail(["unexpected string item"]) assert result is not None assert "unexpected string item" in result -class TestBuildLogFields: - """Unit tests for _build_log_fields.""" - +class TestBuildStructuredLogFields: def test_filters_to_allowed_fields(self): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - hit = {"event": "hello", "level": "info", "unknown_field": "should be dropped"} result = _build_log_fields(hit) assert "event" in result @@ -671,41 +776,30 @@ def test_filters_to_allowed_fields(self): assert "unknown_field" not in result def test_message_mapped_to_event(self): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - hit = {"message": "plain message", "timestamp": "2024-01-01T00:00:00Z"} fields = _build_log_fields(hit) assert fields["event"] == "plain message" - assert "message" not in fields # Ensure it is popped if used as event + assert "message" not in fields def test_message_preserved_if_event_exists(self): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - hit = {"event": "structured event", "message": "plain message"} fields = _build_log_fields(hit) assert fields["event"] == "structured event" - # message is preserved if it's in TASK_LOG_FIELDS and doesn't collide with event assert fields["message"] == "plain message" def test_levelname_mapped_to_level(self): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - hit = {"event": "msg", "levelname": "ERROR"} result = _build_log_fields(hit) assert result["level"] == "ERROR" assert "levelname" not in result def test_at_timestamp_mapped_to_timestamp(self): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - hit = {"event": "msg", "@timestamp": "2024-01-01T00:00:00Z"} result = _build_log_fields(hit) assert result["timestamp"] == "2024-01-01T00:00:00Z" assert "@timestamp" not in result def test_error_detail_is_kept_as_list(self): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - error_detail = [ { "is_cause": False, @@ -714,74 +808,11 @@ def test_error_detail_is_kept_as_list(self): "exc_value": "Woopsie.", } ] - hit = { - "event": "Task failed with exception", - "error_detail": error_detail, - } + hit = {"event": "Task failed with exception", "error_detail": error_detail} result = _build_log_fields(hit) assert result["error_detail"] == error_detail def test_error_detail_dropped_when_empty(self): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - hit = {"event": "msg", "error_detail": []} result = _build_log_fields(hit) assert "error_detail" not in result - - @pytest.mark.skipif(not AIRFLOW_V_3_0_PLUS, reason="StructuredLogMessage only exists in Airflow 3+") - def test_read_includes_error_detail_in_structured_message(self): - """End-to-end: a hit with error_detail should surface it in the returned StructuredLogMessage.""" - from airflow.providers.opensearch.log.os_task_handler import OpensearchTaskHandler - - local_log_location = "local/log/location" - handler = OpensearchTaskHandler( - base_log_folder=local_log_location, - end_of_log_mark="end_of_log\n", - write_stdout=False, - json_format=False, - json_fields="asctime,filename,lineno,levelname,message,exc_text", - host="localhost", - port=9200, - username="admin", - password="password", - ) - - log_id = "test_dag-test_task-test_run--1-1" - body = { - "event": "Task failed with exception", - "log_id": log_id, - "offset": 1, - "error_detail": [ - { - "is_cause": False, - "frames": [ - {"filename": "/opt/airflow/dags/fail.py", "lineno": 13, "name": "log_and_raise"} - ], - "exc_type": "RuntimeError", - "exc_value": "Woopsie. Something went wrong.", - } - ], - } - - # Instead of firing up an OpenSearch client, we patch the IO and response class - mock_hit_dict = body.copy() - from airflow.providers.opensearch.log.os_response import Hit, OpensearchResponse - - mock_hit = Hit({"_source": mock_hit_dict}) - mock_response = mock.MagicMock(spec=OpensearchResponse) - mock_response.hits = [mock_hit] - mock_response.__iter__ = mock.Mock(return_value=iter([mock_hit])) - mock_response.__bool__ = mock.Mock(return_value=True) - mock_response.__getitem__ = mock.Mock(return_value=mock_hit) - - with mock.patch.object(handler, "_os_read", return_value=mock_response): - with mock.patch.object(handler, "_group_logs_by_host", return_value={"localhost": [mock_hit]}): - from airflow.providers.opensearch.log.os_task_handler import _build_log_fields - from airflow.utils.log.file_task_handler import StructuredLogMessage - - fields = _build_log_fields(mock_hit.to_dict()) - msg = StructuredLogMessage(**fields) - - assert msg.event == "Task failed with exception" - assert hasattr(msg, "error_detail") - assert msg.error_detail == body["error_detail"] From 3bf735795c2421d577f7ac22433db3f0338c00d1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:50:29 +0300 Subject: [PATCH 085/100] [v3-2-test] Fix CI Slack notifications never firing recovery alerts (#65119) (#65164) The artifact lookup for the previous notification state was using 'gh api' with -f parameters, which makes the CLI default to POST instead of GET. The artifacts endpoint returns 404 on POST, so the script always treated each run as the first one with no prior state. That meant the 'all tests passing' recovery notification could never fire, since it requires the previous state to contain failures. Force --method GET on the artifact lookup and add unit tests covering both the GET requirement and the determine_action state machine. (cherry picked from commit 35e002a6005d39ba3de283a72a5f9970f8912184) Co-authored-by: Jarek Potiuk --- scripts/ci/slack_notification_state.py | 5 ++ .../tests/ci/test_slack_notification_state.py | 71 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 scripts/tests/ci/test_slack_notification_state.py diff --git a/scripts/ci/slack_notification_state.py b/scripts/ci/slack_notification_state.py index f6dc0a035c234..3bedf4545b5e4 100644 --- a/scripts/ci/slack_notification_state.py +++ b/scripts/ci/slack_notification_state.py @@ -54,10 +54,15 @@ def download_previous_state(artifact_name: str, repo: str) -> dict | None: """Download previous notification state artifact from GitHub Actions.""" + # `gh api` defaults to POST when -f/-F parameters are passed, which makes + # the artifacts list endpoint return 404. Force GET so the parameters are + # encoded as query string. result = subprocess.run( [ "gh", "api", + "--method", + "GET", f"repos/{repo}/actions/artifacts", "-f", f"name={artifact_name}", diff --git a/scripts/tests/ci/test_slack_notification_state.py b/scripts/tests/ci/test_slack_notification_state.py new file mode 100644 index 0000000000000..6400dd1fdf4c5 --- /dev/null +++ b/scripts/tests/ci/test_slack_notification_state.py @@ -0,0 +1,71 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +import importlib.util +import subprocess +import sys +from pathlib import Path +from unittest.mock import patch + +import pytest + +MODULE_PATH = Path(__file__).resolve().parents[3] / "scripts" / "ci" / "slack_notification_state.py" + + +@pytest.fixture +def slack_state_module(): + module_name = "test_slack_notification_state_module" + sys.modules.pop(module_name, None) + spec = importlib.util.spec_from_file_location(module_name, MODULE_PATH) + assert spec is not None + assert spec.loader is not None + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +class TestDownloadPreviousState: + def test_uses_explicit_get_method(self, slack_state_module): + """`gh api` defaults to POST when -f is passed; we must force GET to avoid 404.""" + completed = subprocess.CompletedProcess(args=[], returncode=0, stdout="null", stderr="") + with patch.object(subprocess, "run", return_value=completed) as mock_run: + slack_state_module.download_previous_state("artifact", "apache/airflow") + args = mock_run.call_args[0][0] + assert "--method" in args + method_index = args.index("--method") + assert args[method_index + 1] == "GET" + + +class TestDetermineAction: + def test_no_failures_no_prev_state(self, slack_state_module): + assert slack_state_module.determine_action([], None) == "skip" + + def test_no_failures_no_prev_failures(self, slack_state_module): + prev = {"failures": [], "last_notified": "2025-01-01T00:00:00+00:00"} + assert slack_state_module.determine_action([], prev) == "skip" + + def test_recovery_when_clear_after_failures(self, slack_state_module): + prev = {"failures": ["job-a"], "last_notified": "2025-01-01T00:00:00+00:00"} + assert slack_state_module.determine_action([], prev) == "notify_recovery" + + def test_notify_new_on_first_failure(self, slack_state_module): + assert slack_state_module.determine_action(["job-a"], None) == "notify_new" + + def test_notify_new_on_changed_failures(self, slack_state_module): + prev = {"failures": ["job-a"], "last_notified": "2025-01-01T00:00:00+00:00"} + assert slack_state_module.determine_action(["job-b"], prev) == "notify_new" From bd4d5de674b7731395c32fecc373e996b23a0336 Mon Sep 17 00:00:00 2001 From: Daniel Seo Date: Tue, 14 Apr 2026 08:49:10 -0400 Subject: [PATCH 086/100] [v3-2-test] Fix backport test for log line number gap fix (#65039) (#65187) * [v3-2-test] UI: Fix log line number gaps caused by group markers (#65039) * Fix log line number gaps caused by group markers (#47888) Group markers (::group:: / ::endgroup::) consumed line number indices but were removed during group processing, leaving gaps in the displayed line numbers (e.g. 0, 2, 3 instead of 0, 1, 2). Pre-scan the log data to assign sequential display line numbers that skip group markers, and pin wrapped line numbers to the top with alignItems flex-start. * fix test --------- (cherry picked from commit 55162a373963947089c8153ad58c127719836625) Co-authored-by: Daniel Seo Co-authored-by: hseo36 * Fix backport test to work with v3-2-test log architecture The cherry-picked test from main used the new flat ParsedLogEntry group rendering (#63467) which doesn't exist on v3-2-test. Rewrite to query line number anchors directly from the DOM. --------- Co-authored-by: hseo36 --- .../ui/src/components/renderStructuredLog.tsx | 2 +- .../src/pages/TaskInstance/Logs/Logs.test.tsx | 21 +++++++++++++++++++ .../src/airflow/ui/src/queries/useLogs.tsx | 16 +++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/components/renderStructuredLog.tsx b/airflow-core/src/airflow/ui/src/components/renderStructuredLog.tsx index f3febe79687be..38b430ebb556f 100644 --- a/airflow-core/src/airflow/ui/src/components/renderStructuredLog.tsx +++ b/airflow-core/src/airflow/ui/src/components/renderStructuredLog.tsx @@ -274,7 +274,7 @@ const renderStructuredLogImpl = ({ } return ( - + { await waitFor(() => expect(screen.queryByText(/Marking task as SUCCESS/iu)).not.toBeVisible()); }, 10_000); + + it("skips group markers when assigning line numbers", async () => { + render( + , + ); + + await waitForLogs(); + + const logContainer = screen.getByTestId("virtual-scroll-container"); + const lineNumbers = [...logContainer.querySelectorAll("a[id]")] + .map((el) => parseInt(el.id, 10)) + .filter((num) => !isNaN(num)) + .sort((numA, numB) => numA - numB); + + expect(lineNumbers.length).toBeGreaterThan(0); + expect(lineNumbers[0]).toBe(0); + expect(new Set(lineNumbers).size).toBe(lineNumbers.length); + lineNumbers.forEach((num, idx) => { + expect(num).toBe(idx); + }); + }, 10_000); }); diff --git a/airflow-core/src/airflow/ui/src/queries/useLogs.tsx b/airflow-core/src/airflow/ui/src/queries/useLogs.tsx index 1a82896741468..50090d5fe5301 100644 --- a/airflow-core/src/airflow/ui/src/queries/useLogs.tsx +++ b/airflow-core/src/airflow/ui/src/queries/useLogs.tsx @@ -75,6 +75,20 @@ const parseLogs = ({ const logLink = taskInstance ? `${getTaskInstanceLink(taskInstance)}?try_number=${tryNumber}` : ""; try { + let lineNumber = 0; + const lineNumbers = data.map((datum) => { + const text = typeof datum === "string" ? datum : datum.event; + + if (text.includes("::group::") || text.includes("::endgroup::")) { + return undefined; + } + const current = lineNumber; + + lineNumber += 1; + + return current; + }); + parsedLines = data .map((datum, index) => { if (typeof datum !== "string" && "logger" in datum) { @@ -86,7 +100,7 @@ const parseLogs = ({ } return renderStructuredLog({ - index, + index: lineNumbers[index] ?? index, logLevelFilters, logLink, logMessage: datum, From 5a13c594a80dce5ee232dcebabd68041ed146f49 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:17:50 +0200 Subject: [PATCH 087/100] [v3-2-test] fix(ui): sync SearchBar value with defaultValue changes (#65054) (#65140) * fix(ui): sync SearchBar value with defaultValue changes * fix: resolve eslint hook dependency * fix(ui): sync SearchBar value with defaultValue changes * fix(ui): sync SearchBar value with defaultValue changes * fix(ui): sync SearchBar value with defaultValue changes (cherry picked from commit 11aba6788e64ddbd77c6e4d92513684fc88c992a) Co-authored-by: Mayank Aggarwal --- .../ui/src/components/SearchBar.test.tsx | 34 +++++++++++++++++++ .../airflow/ui/src/components/SearchBar.tsx | 7 +++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/airflow-core/src/airflow/ui/src/components/SearchBar.test.tsx b/airflow-core/src/airflow/ui/src/components/SearchBar.test.tsx index 2d5be3990bd35..65f3c4f75d278 100644 --- a/airflow-core/src/airflow/ui/src/components/SearchBar.test.tsx +++ b/airflow-core/src/airflow/ui/src/components/SearchBar.test.tsx @@ -81,4 +81,38 @@ describe("Test SearchBar", () => { expect(onChange).toHaveBeenCalledTimes(1); }); + + it("syncs input value when defaultValue changes", async () => { + const onChange = vi.fn(); + const { rerender } = render( + , + { + wrapper: Wrapper, + }, + ); + const input = screen.getByTestId("search-dags"); + + expect((input as HTMLInputElement).value).toBe("initial-search"); + + rerender(); + + await waitFor(() => expect((input as HTMLInputElement).value).toBe("updated-search")); + }); + + it("does not override local typing when defaultValue rerenders unchanged", () => { + const onChange = vi.fn(); + const { rerender } = render( + , + { + wrapper: Wrapper, + }, + ); + const input = screen.getByTestId("search-dags"); + + fireEvent.change(input, { target: { value: "user-typing" } }); + + rerender(); + + expect((input as HTMLInputElement).value).toBe("user-typing"); + }); }); diff --git a/airflow-core/src/airflow/ui/src/components/SearchBar.tsx b/airflow-core/src/airflow/ui/src/components/SearchBar.tsx index 91825004d45ed..f935a847ef591 100644 --- a/airflow-core/src/airflow/ui/src/components/SearchBar.tsx +++ b/airflow-core/src/airflow/ui/src/components/SearchBar.tsx @@ -17,7 +17,7 @@ * under the License. */ import { CloseButton, Input, InputGroup, Kbd, type InputGroupProps } from "@chakra-ui/react"; -import { useState, useRef, type ChangeEvent } from "react"; +import { useEffect, useRef, useState, type ChangeEvent } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { useTranslation } from "react-i18next"; import { FiSearch } from "react-icons/fi"; @@ -46,6 +46,11 @@ export const SearchBar = ({ const [value, setValue] = useState(defaultValue); const metaKey = getMetaKey(); const { t: translate } = useTranslation(["dags"]); + + useEffect(() => { + setValue(defaultValue); + }, [defaultValue]); + const onSearchChange = (event: ChangeEvent) => { setValue(event.target.value); handleSearchChange(event.target.value); From f4f4ce3b7c02998d8688a4e0270a7e5717da9247 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:18:43 +0200 Subject: [PATCH 088/100] [v3-2-test] fix(ui): use fixed menu positioning for dropdowns in connection forms (#65007) (#65085) (#65138) - Add menuPosition="fixed" to FieldDropdown and FieldMultiSelect components - Ensures dropdown menus are fully visible when rendered inside accordion panels - Prevents menu clipping when parent containers have overflow constraints Closes #65007 (cherry picked from commit 5342d3d437c1f9c311594682de659d8226b8a734) Co-authored-by: Tyson Cung <45380903+tysoncung@users.noreply.github.com> Co-authored-by: Tyson Cung --- .../src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx | 1 + .../airflow/ui/src/components/FlexibleForm/FieldMultiSelect.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx index d439dd6032f92..b8cf6ad1068e6 100644 --- a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx +++ b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx @@ -89,6 +89,7 @@ export const FieldDropdown = ({ name, namespace = "default", onUpdate }: Flexibl id={`element_${name}`} isClearable isDisabled={disabled} + menuPosition="fixed" name={`element_${name}`} onChange={handleChange} options={options} diff --git a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldMultiSelect.tsx b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldMultiSelect.tsx index 4654587fb8176..6bc2442708bc4 100644 --- a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldMultiSelect.tsx +++ b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldMultiSelect.tsx @@ -76,6 +76,7 @@ export const FieldMultiSelect = ({ name, namespace = "default", onUpdate }: Flex isClearable isDisabled={disabled} isMulti + menuPosition="fixed" name={`element_${name}`} onChange={handleChange} options={ From c6dd0a4ce7844f3521b71418998fda1e6036442a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:42:09 +0200 Subject: [PATCH 089/100] [v3-2-test] Pin pyarrow>=22.0.0 on Python 3.14 in highest-resolution constraints (#65216) (#65219) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older pyarrow releases do not publish cp314 wheels on PyPI, so uv falls back to building pyarrow from source when resolving the highest versions of provider dependencies on Python 3.14 — which fails. pyarrow 22.0.0 is the first release shipping Python 3.14 wheels, so constrain it for that Python version when generating constraints. (cherry picked from commit cd28a003f5c13d6349ee03310cdec314ecbcc748) Co-authored-by: Jarek Potiuk --- scripts/in_container/run_generate_constraints.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/in_container/run_generate_constraints.py b/scripts/in_container/run_generate_constraints.py index b22ade34305ac..9652128ac3db4 100755 --- a/scripts/in_container/run_generate_constraints.py +++ b/scripts/in_container/run_generate_constraints.py @@ -358,9 +358,13 @@ def generate_constraints_pypi_providers(config_params: ConfigParams) -> None: # # Current exclusions: # - # * no exclusions + # * pyarrow>=22.0.0 on Python 3.14 — older pyarrow releases have no prebuilt wheels for + # Python 3.14 and uv falls back to building from source, which fails. pyarrow 22.0.0 is + # the first release shipping cp314 wheels. # - additional_constraints_for_highest_resolution: list[str] = [] + additional_constraints_for_highest_resolution: list[str] = [ + "pyarrow>=22.0.0; python_version >= '3.14'", + ] result = run_command( cmd=[ From 91cca114dd8b1d6a79e0270b340928079999e996 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:52:49 +0200 Subject: [PATCH 090/100] [v3-2-test] Fix serializer for empty string extra connection (#65014) (#65215) * Fix serializer for empty string extra connection * Update airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py --------- (cherry picked from commit 41bd4cd4427bad33516909910984164dd4cd7c93) Co-authored-by: Pierre Jeambrun Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../api_fastapi/core_api/datamodels/connections.py | 8 ++++---- .../core_api/routes/public/test_connections.py | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py index a44edb5b91b43..0b69c47cfdf3b 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py @@ -53,16 +53,16 @@ def redact_password(cls, v: str | None, field_info: ValidationInfo) -> str | Non @field_validator("extra", mode="before") @classmethod def redact_extra(cls, v: str | None) -> str | None: - if v is None: - return None + if v is None or v == "": + return v try: extra_dict = json.loads(v) redacted_dict = redact(extra_dict) return json.dumps(redacted_dict) except json.JSONDecodeError: # Do not return un-redacted extra because this could cause sensitive information to be exposed. - # This code path should never been hit as ``Connection._validate_extra`` sure that ``extra`` is - # always a valid JSON string. We add this safeguard just in case and to make the coupling + # This code path should never be hit as ``Connection._validate_extra`` makes sure that ``extra`` is + # always a valid JSON string (if truthy). We add this safeguard just in case and to make the coupling # explicit. raise ValueError( "This code path should never happen as persisted Connections (DB layer) should always enforce `extra` as a JSON string." diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py index 1f63247cfa9ab..4ca21b0ff49ea 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py @@ -168,6 +168,19 @@ def test_get_should_respond_200_with_extra(self, test_client, session): assert body["conn_type"] == TEST_CONN_TYPE assert body["extra"] == '{"extra_key": "extra_value"}' + @pytest.mark.parametrize("extra_value", [None, ""]) + def test_get_should_respond_200_with_empty_extra(self, test_client, session, extra_value): + """Empty string or NULL extra should not break serialization (regression test for #64950).""" + self.create_connection() + connection = session.scalars(select(Connection)).first() + connection.extra = extra_value + session.commit() + response = test_client.get(f"/connections/{TEST_CONN_ID}") + assert response.status_code == 200 + body = response.json() + assert body["connection_id"] == TEST_CONN_ID + assert body["extra"] == extra_value + @pytest.mark.enable_redact def test_get_should_respond_200_with_extra_redacted(self, test_client, session): self.create_connection() From ea242328958a71748285f438de4e05bfa5b326fd Mon Sep 17 00:00:00 2001 From: Ephraim Anierobi Date: Tue, 14 Apr 2026 16:00:56 +0100 Subject: [PATCH 091/100] Reduce per-DAG queries during DAG serialization with bulk prefetch (#64929) (#65208) * Reduce per-DAG queries during DAG serialization with bulk prefetch Replaces 3 SELECTs per DAG in write_dag (update interval check, hash comparison, version fetch) with 2 bulk queries via a new _prefetch_dag_write_metadata classmethod. Also fixes DagCode.update_source_code to reuse the caller's session and eagerly loads dag_owner_links to prevent N+1 queries. * fixup! Reduce per-DAG queries during DAG serialization with bulk prefetch * fixup! fixup! Reduce per-DAG queries during DAG serialization with bulk prefetch (cherry picked from commit ef0004035edb27507c6899b11bd24166ce3a08c0) --- .../src/airflow/dag_processing/collection.py | 21 +++- .../src/airflow/models/serialized_dag.py | 102 +++++++++++++++--- .../unit/dag_processing/test_collection.py | 1 + .../tests/unit/models/test_serialized_dag.py | 42 ++++++++ 4 files changed, 146 insertions(+), 20 deletions(-) diff --git a/airflow-core/src/airflow/dag_processing/collection.py b/airflow-core/src/airflow/dag_processing/collection.py index 96f3c89f8623a..06e4900d816e5 100644 --- a/airflow-core/src/airflow/dag_processing/collection.py +++ b/airflow-core/src/airflow/dag_processing/collection.py @@ -53,6 +53,7 @@ from airflow.models.dagrun import DagRun from airflow.models.dagwarning import DagWarningType from airflow.models.errors import ParseImportError +from airflow.models.serialized_dag import SerializedDagModel from airflow.models.trigger import Trigger from airflow.serialization.definitions.assets import ( SerializedAsset, @@ -75,6 +76,7 @@ from sqlalchemy.sql import Select from airflow.models.dagwarning import DagWarning + from airflow.models.serialized_dag import DagWriteMetadata from airflow.typing_compat import Self, Unpack AssetT = TypeVar("AssetT", SerializedAsset, SerializedAssetAlias) @@ -256,7 +258,11 @@ def _update_dag_owner_links(dag_owner_links: dict[str, str], dm: DagModel, *, se def _serialize_dag_capturing_errors( - dag: LazyDeserializedDAG, bundle_name, session: Session, bundle_version: str | None + dag: LazyDeserializedDAG, + bundle_name, + session: Session, + bundle_version: str | None, + _prefetched: DagWriteMetadata | None = None, ): """ Try to serialize the dag to the DB, but make a note of any errors. @@ -264,7 +270,6 @@ def _serialize_dag_capturing_errors( We can't place them directly in import_errors, as this may be retried, and work the next time """ from airflow.models.dagcode import DagCode - from airflow.models.serialized_dag import SerializedDagModel # Updating serialized DAG can not be faster than a minimum interval to reduce database write rate. MIN_SERIALIZED_DAG_UPDATE_INTERVAL = conf.getint( @@ -279,10 +284,11 @@ def _serialize_dag_capturing_errors( bundle_version=bundle_version, min_update_interval=MIN_SERIALIZED_DAG_UPDATE_INTERVAL, session=session, + _prefetched=_prefetched, ) if not dag_was_updated: # Check and update DagCode - DagCode.update_source_code(dag.dag_id, dag.fileloc) + DagCode.update_source_code(dag.dag_id, dag.fileloc, session=session) if "FabAuthManager" in conf.get("core", "auth_manager"): _sync_dag_perms(dag, session=session) @@ -473,6 +479,13 @@ def update_dag_parsing_results_in_db( SerializedDAG.bulk_write_to_db( bundle_name, bundle_version, dags, parse_duration, session=session ) + # Bulk prefetch metadata for all DAGs to avoid the standard per-DAG + # metadata lookups in write_dag. This replaces the update-interval, + # hash, and version queries with 2 bulk queries total; DAGs with + # deadlines may still do an additional lookup for deadline UUID reuse. + prefetched_metadata = SerializedDagModel._prefetch_dag_write_metadata( + [dag.dag_id for dag in dags], session=session + ) # Write Serialized DAGs to DB, capturing errors for dag in dags: serialize_errors.extend( @@ -481,6 +494,7 @@ def update_dag_parsing_results_in_db( bundle_name=bundle_name, bundle_version=bundle_version, session=session, + _prefetched=prefetched_metadata.get(dag.dag_id), ) ) except OperationalError: @@ -526,6 +540,7 @@ def find_orm_dags(self, *, session: Session) -> dict[str, DagModel]: .options(joinedload(DagModel.schedule_asset_references)) .options(joinedload(DagModel.schedule_asset_alias_references)) .options(joinedload(DagModel.task_outlet_asset_references)) + .options(joinedload(DagModel.dag_owner_links)) ), of=DagModel, session=session, diff --git a/airflow-core/src/airflow/models/serialized_dag.py b/airflow-core/src/airflow/models/serialized_dag.py index 23b93f2dae5aa..0aaf295a58ff4 100644 --- a/airflow-core/src/airflow/models/serialized_dag.py +++ b/airflow-core/src/airflow/models/serialized_dag.py @@ -23,7 +23,7 @@ import zlib from collections.abc import Callable, Iterable, Iterator, Sequence from datetime import datetime, timedelta -from typing import TYPE_CHECKING, Any, Literal +from typing import TYPE_CHECKING, Any, Literal, NamedTuple from uuid import UUID import uuid6 @@ -70,6 +70,14 @@ _COMPRESS_SERIALIZED_DAGS = conf.getboolean("core", "compress_serialized_dags", fallback=False) +class DagWriteMetadata(NamedTuple): + """Pre-fetched metadata for write_dag to avoid per-DAG queries.""" + + last_updated: datetime | None + dag_hash: str | None + dag_version: DagVersion | None + + class _DagDependenciesResolver: """Resolver that resolves dag dependencies to include asset id and assets link to asset aliases.""" @@ -508,6 +516,70 @@ def _create_deadline_alert_records( ) serialized_dag.deadline_alerts.append(alert) + @classmethod + def _prefetch_dag_write_metadata( + cls, dag_ids: Iterable[str], *, session: Session + ) -> dict[str, DagWriteMetadata]: + """ + Bulk-fetch metadata needed by write_dag for multiple DAGs in two queries. + + Instead of running 3 SELECTs per DAG in write_dag (update interval check, + hash comparison, version fetch), this fetches all needed data upfront. + + :param dag_ids: DAG IDs to prefetch metadata for + :param session: ORM Session + :returns: dict mapping dag_id to DagWriteMetadata + """ + dag_id_list = list(set(dag_ids)) + if not dag_id_list: + return {} + + # Fetch latest serialized_dag (last_updated, dag_hash) per dag_id + # using a window function to pick the most recent row. + sd_subq = ( + select( + cls.dag_id.label("dag_id"), + cls.last_updated.label("last_updated"), + cls.dag_hash.label("dag_hash"), + func.row_number().over(partition_by=cls.dag_id, order_by=cls.created_at.desc()).label("rn"), + ) + .where(cls.dag_id.in_(dag_id_list)) + .subquery() + ) + sd_rows = session.execute( + select(sd_subq.c.dag_id, sd_subq.c.last_updated, sd_subq.c.dag_hash).where(sd_subq.c.rn == 1) + ).all() + sd_by_dag_id: dict[str, tuple[datetime, str]] = { + row.dag_id: (row.last_updated, row.dag_hash) for row in sd_rows + } + + # Fetch latest DagVersion per dag_id using a window function, + # matching the original write_dag ordering (ORDER BY created_at DESC). + dv_subq = ( + select( + DagVersion.id.label("id"), + DagVersion.dag_id.label("dag_id"), + func.row_number() + .over(partition_by=DagVersion.dag_id, order_by=DagVersion.created_at.desc()) + .label("rn"), + ) + .where(DagVersion.dag_id.in_(dag_id_list)) + .subquery() + ) + dag_versions = session.scalars( + select(DagVersion).join(dv_subq, DagVersion.id == dv_subq.c.id).where(dv_subq.c.rn == 1) + ).all() + dv_by_dag_id: dict[str, DagVersion] = {dv.dag_id: dv for dv in dag_versions} + + return { + dag_id: DagWriteMetadata( + last_updated=sd_by_dag_id[dag_id][0] if dag_id in sd_by_dag_id else None, + dag_hash=sd_by_dag_id[dag_id][1] if dag_id in sd_by_dag_id else None, + dag_version=dv_by_dag_id.get(dag_id), + ) + for dag_id in dag_id_list + } + @classmethod @provide_session def write_dag( @@ -517,6 +589,7 @@ def write_dag( bundle_version: str | None = None, min_update_interval: int | None = None, session: Session = NEW_SESSION, + _prefetched: DagWriteMetadata | None = None, ) -> bool: """ Serialize a DAG and writes it into database. @@ -529,33 +602,28 @@ def write_dag( :param bundle_version: bundle version of the DAG :param min_update_interval: minimal interval in seconds to update serialized DAG :param session: ORM Session + :param _prefetched: Pre-fetched metadata to skip per-DAG queries; used by bulk callers :returns: Boolean indicating if the DAG was written to the DB """ + if _prefetched is None: + _prefetched = cls._prefetch_dag_write_metadata([dag.dag_id], session=session).get( + dag.dag_id, DagWriteMetadata(last_updated=None, dag_hash=None, dag_version=None) + ) + # Checks if (Current Time - Time when the DAG was written to DB) < min_update_interval # If Yes, does nothing # If No or the DAG does not exists, updates / writes Serialized DAG to DB if min_update_interval is not None: - if session.scalar( - select(literal(True)) - .where( - cls.dag_id == dag.dag_id, - (timezone.utcnow() - timedelta(seconds=min_update_interval)) < cls.last_updated, - ) - .select_from(cls) + if ( + _prefetched.last_updated is not None + and (timezone.utcnow() - timedelta(seconds=min_update_interval)) < _prefetched.last_updated ): return False log.debug("Checking if DAG (%s) changed", dag.dag_id) - serialized_dag_hash = session.scalars( - select(cls.dag_hash).where(cls.dag_id == dag.dag_id).order_by(cls.created_at.desc()) - ).first() - dag_version = session.scalar( - select(DagVersion) - .where(DagVersion.dag_id == dag.dag_id) - .order_by(DagVersion.created_at.desc()) - .limit(1) - ) + serialized_dag_hash = _prefetched.dag_hash + dag_version = _prefetched.dag_version if dag.data.get("dag", {}).get("deadline"): # Try to reuse existing deadline UUIDs if the deadline definitions haven't changed. diff --git a/airflow-core/tests/unit/dag_processing/test_collection.py b/airflow-core/tests/unit/dag_processing/test_collection.py index 6a0aef00eaa8e..1792c9b38c0ae 100644 --- a/airflow-core/tests/unit/dag_processing/test_collection.py +++ b/airflow-core/tests/unit/dag_processing/test_collection.py @@ -537,6 +537,7 @@ def test_sync_to_db_is_retried( bundle_version=None, min_update_interval=mock.ANY, session=mock_session, + _prefetched=mock.ANY, ), ] ) diff --git a/airflow-core/tests/unit/models/test_serialized_dag.py b/airflow-core/tests/unit/models/test_serialized_dag.py index de0464dea8c09..2185635590eff 100644 --- a/airflow-core/tests/unit/models/test_serialized_dag.py +++ b/airflow-core/tests/unit/models/test_serialized_dag.py @@ -524,6 +524,48 @@ def test_min_update_interval_is_respected(self, provide_interval, new_task, shou ) assert did_write is should_write + def test_prefetch_dag_write_metadata_multiple_dags(self, dag_maker, session): + """Test that _prefetch_dag_write_metadata returns correct metadata for multiple DAGs.""" + with dag_maker("prefetch_multi_dag1"): + EmptyOperator(task_id="task1") + with dag_maker("prefetch_multi_dag2"): + EmptyOperator(task_id="task1") + + result = SDM._prefetch_dag_write_metadata( + ["prefetch_multi_dag1", "prefetch_multi_dag2"], session=session + ) + + assert len(result) == 2 + for dag_id in ("prefetch_multi_dag1", "prefetch_multi_dag2"): + metadata = result[dag_id] + assert metadata.last_updated is not None + assert metadata.dag_hash is not None + assert metadata.dag_version is not None + assert metadata.dag_version.dag_id == dag_id + + def test_prefetch_dag_write_metadata_returns_latest_version(self, dag_maker, session): + """Test that _prefetch_dag_write_metadata returns the latest DagVersion.""" + with dag_maker("prefetch_version_dag") as dag: + PythonOperator(task_id="task1", python_callable=lambda: None) + # Create a dagrun so that writing a changed DAG creates a new version + dag_maker.create_dagrun(run_id="run1", logical_date=pendulum.datetime(2025, 1, 1)) + + # Modify the DAG (add a task) and write again to create version 2 + PythonOperator(task_id="task2", python_callable=lambda: None, dag=dag) + SDM.write_dag(LazyDeserializedDAG.from_dag(dag), bundle_name="dag_maker") + + assert ( + session.scalar( + select(func.count()).select_from(DagVersion).where(DagVersion.dag_id == dag.dag_id) + ) + == 2 + ) + + result = SDM._prefetch_dag_write_metadata([dag.dag_id], session=session) + metadata = result[dag.dag_id] + assert metadata.dag_version is not None + assert metadata.dag_version.version_number == 2 + def test_new_dag_version_created_when_bundle_name_changes_and_hash_unchanged(self, dag_maker, session): """Test that new dag_version is created if bundle_name changes but DAG is unchanged.""" # Create and write initial DAG From 778c68815f688e41dd0fbb88562f5956c4587ef6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 17:52:50 +0200 Subject: [PATCH 092/100] [v3-2-test] UI: Show deactivated state for stale DAGs (#65214) (#65218) When a DAG becomes stale or deactivated, the UI still shows active-oriented controls like the pause toggle, parse action, and next-run information. This change makes the deactivated state explicit by showing a badge and hiding controls that imply the DAG is still schedulable. - Add reusable DagDeactivatedBadge component - Show badge instead of pause toggle for stale DAGs in header and breadcrumb - Hide next-run stat and parse action for stale DAGs - Add regression test for stale DAG header behavior Fixes #63800 (cherry picked from commit 2d426418c4f0b98d706fbb0e29af8ecb1e5bc8e6) Co-authored-by: Pierre Jeambrun --- .../ui/public/i18n/locales/en/dag.json | 3 + .../ui/src/components/DagDeactivatedBadge.tsx | 26 ++++++++ .../ui/src/layouts/Details/DagBreadcrumb.tsx | 5 +- .../ui/src/layouts/Details/DetailsLayout.tsx | 6 +- .../airflow/ui/src/pages/Dag/Header.test.tsx | 65 +++++++++++++++++++ .../src/airflow/ui/src/pages/Dag/Header.tsx | 36 ++++++---- 6 files changed, 125 insertions(+), 16 deletions(-) create mode 100644 airflow-core/src/airflow/ui/src/components/DagDeactivatedBadge.tsx create mode 100644 airflow-core/src/airflow/ui/src/pages/Dag/Header.test.tsx diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json index 58626c2494248..9477d1f981af3 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json @@ -52,6 +52,9 @@ "buttons": { "advanced": "Advanced", "dagDocs": "Dag Docs" + }, + "status": { + "deactivated": "Deactivated" } }, "logs": { diff --git a/airflow-core/src/airflow/ui/src/components/DagDeactivatedBadge.tsx b/airflow-core/src/airflow/ui/src/components/DagDeactivatedBadge.tsx new file mode 100644 index 0000000000000..ad915b256bee5 --- /dev/null +++ b/airflow-core/src/airflow/ui/src/components/DagDeactivatedBadge.tsx @@ -0,0 +1,26 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { Badge } from "@chakra-ui/react"; +import { useTranslation } from "react-i18next"; + +export const DagDeactivatedBadge = () => { + const { t: translate } = useTranslation("dag"); + + return {translate("header.status.deactivated")}; +}; diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/DagBreadcrumb.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/DagBreadcrumb.tsx index d877b4daa1b9b..822e8d7e663d6 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/DagBreadcrumb.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/DagBreadcrumb.tsx @@ -27,6 +27,7 @@ import { useTaskServiceGetTask, } from "openapi/queries"; import { BreadcrumbStats } from "src/components/BreadcrumbStats"; +import { DagDeactivatedBadge } from "src/components/DagDeactivatedBadge"; import { StateBadge } from "src/components/StateBadge"; import { TogglePause } from "src/components/TogglePause"; import { isStatePending, useAutoRefresh } from "src/utils"; @@ -65,7 +66,9 @@ export const DagBreadcrumb = () => { [ { label: dag?.dag_display_name ?? dagId, - labelExtra: ( + labelExtra: dag?.is_stale ? ( + + ) : ( { const [defaultDagView] = useLocalStorage<"graph" | "grid">(DEFAULT_DAG_VIEW_KEY, "grid"); const panelGroupRef = useRef(null); const [dagView, setDagView] = useLocalStorage<"graph" | "grid">(dagViewKey(dagId), defaultDagView); - const [limit, setLimit] = useLocalStorage(dagRunsLimitKey(dagId), 10); + const [limit, setLimit] = useLocalStorage(dagRunsLimitKey(dagId), 10); const [runAfterGte, setRunAfterGte] = useLocalStorage(runAfterGteKey(dagId), undefined); const [runAfterLte, setRunAfterLte] = useLocalStorage(runAfterLteKey(dagId), undefined); const [runTypeFilter, setRunTypeFilter] = useLocalStorage( @@ -94,9 +94,9 @@ export const DetailsLayout = ({ children, error, isLoading, tabs }: Props) => { undefined, ); - const [showGantt, setShowGantt] = useLocalStorage(showGanttKey(dagId), false); + const [showGantt, setShowGantt] = useLocalStorage(showGanttKey(dagId), false); // Global setting: applies to all Dags (intentionally not scoped to dagId) - const [showVersionIndicatorMode, setShowVersionIndicatorMode] = useLocalStorage( + const [showVersionIndicatorMode, setShowVersionIndicatorMode] = useLocalStorage( `version_indicator_display_mode`, VersionIndicatorOptions.ALL, ); diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Header.test.tsx b/airflow-core/src/airflow/ui/src/pages/Dag/Header.test.tsx new file mode 100644 index 0000000000000..9d68c7b8e851c --- /dev/null +++ b/airflow-core/src/airflow/ui/src/pages/Dag/Header.test.tsx @@ -0,0 +1,65 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import "@testing-library/jest-dom"; +import { render, screen } from "@testing-library/react"; +import type { DAGDetailsResponse } from "openapi-gen/requests/types.gen"; +import { describe, expect, it } from "vitest"; + +import i18n from "src/i18n/config"; +import { MOCK_DAG } from "src/mocks/handlers/dag"; +import { Wrapper } from "src/utils/Wrapper"; + +import { Header } from "./Header"; + +const mockDag = { + ...MOCK_DAG, + active_runs_count: 0, + allowed_run_types: [], + bundle_name: "dags-folder", + bundle_version: "1", + default_args: {}, + fileloc: "/files/dags/stale_dag.py", + is_favorite: false, + is_stale: true, + last_parse_duration: 0.23, + // `null` matches the API response shape for DAGs without version metadata. + // eslint-disable-next-line unicorn/no-null + latest_dag_version: null, + next_dagrun_logical_date: "2024-08-22T00:00:00+00:00", + next_dagrun_run_after: "2024-08-22T19:00:00+00:00", + owner_links: {}, + relative_fileloc: "stale_dag.py", + tags: [], + timetable_partitioned: false, + timetable_summary: "* * * * *", +} as unknown as DAGDetailsResponse; + +describe("Header", () => { + it("shows a deactivated badge and hides stale-only next actions for stale dags", () => { + render( + +
+
, + ); + + expect(screen.getByText(i18n.t("dag:header.status.deactivated"))).toBeInTheDocument(); + expect(screen.queryByText(i18n.t("dag:dagDetails.nextRun"))).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Reparse Dag" })).not.toBeInTheDocument(); + }); +}); diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx b/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx index 6af9129a31641..99acda13f05b5 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx @@ -26,6 +26,7 @@ import { DagIcon } from "src/assets/DagIcon"; import { DeleteDagButton } from "src/components/DagActions/DeleteDagButton"; import { FavoriteDagButton } from "src/components/DagActions/FavoriteDagButton"; import { ParseDagButton } from "src/components/DagActions/ParseDagButton"; +import { DagDeactivatedBadge } from "src/components/DagDeactivatedBadge"; import DagRunInfo from "src/components/DagRunInfo"; import { DagVersion } from "src/components/DagVersion"; import DisplayMarkdownButton from "src/components/DisplayMarkdownButton"; @@ -56,6 +57,21 @@ export const Header = ({ const { t: translate } = useTranslation(["common", "dag"]); // We would still like to show the dagId even if the dag object hasn't loaded yet const { dagId } = useParams(); + const isStale = dag?.is_stale; + + const nextRunStat = isStale + ? [] + : [ + { + label: translate("dagDetails.nextRun"), + value: Boolean(dag?.next_dagrun_run_after) ? ( + + ) : undefined, + }, + ]; const stats = [ { @@ -88,15 +104,7 @@ export const Header = ({ ) : undefined, }, - { - label: translate("dagDetails.nextRun"), - value: Boolean(dag?.next_dagrun_run_after) ? ( - - ) : undefined, - }, + ...nextRunStat, { label: translate("dagDetails.maxActiveRuns"), value: @@ -132,7 +140,7 @@ export const Header = ({ /> )} - + {isStale ? undefined : } ) @@ -140,8 +148,12 @@ export const Header = ({ icon={} stats={stats} subTitle={ - dag !== undefined && ( - + isStale ? ( + + ) : ( + dag !== undefined && ( + + ) ) } title={dag?.dag_display_name ?? dagId} From a17d6b2ef2d2347e818b6e3b3e928b58d3d29e25 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Tue, 14 Apr 2026 17:54:53 +0200 Subject: [PATCH 093/100] [v3-2-test] CI: Upgrade important CI environment (#65213) --- .github/SECURITY.md | 1 + .github/actions/breeze/action.yml | 2 +- .github/actions/install-prek/action.yml | 2 +- .github/workflows/basic-tests.yml | 2 +- .github/workflows/ci-amd-arm.yml | 2 +- .github/workflows/release_dockerhub_image.yml | 2 +- .pre-commit-config.yaml | 4 +- Dockerfile | 2 +- Dockerfile.ci | 2 +- airflow-core/docs/best-practices.rst | 2 +- dev/PROJECT_GUIDELINES.md | 1 + .../adr/0001-record-architecture-decisions.md | 1 + dev/breeze/doc/ci/02_images.md | 2 +- .../commands/release_management_commands.py | 2 +- .../src/airflow_breeze/global_constants.py | 2 +- dev/breeze/uv.lock | 208 +-- devel-common/pyproject.toml | 2 +- pyproject.toml | 2 +- scripts/ci/prek/check_imports_in_providers.py | 2 +- scripts/ci/prek/ruff_format.py | 2 +- scripts/tools/setup_breeze | 2 +- uv.lock | 1426 +++++++++-------- 22 files changed, 843 insertions(+), 830 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 5bb3dfcc04766..7806f1598df72 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -3,6 +3,7 @@ + - [Apache Airflow Security](#apache-airflow-security) - [What should be and should NOT be reported ?](#what-should-be-and-should-not-be-reported-) diff --git a/.github/actions/breeze/action.yml b/.github/actions/breeze/action.yml index cc6005f39554a..57bcb8303cb94 100644 --- a/.github/actions/breeze/action.yml +++ b/.github/actions/breeze/action.yml @@ -24,7 +24,7 @@ inputs: default: "3.10" uv-version: description: 'uv version to use' - default: "0.11.3" # Keep this comment to allow automatic replacement of uv version + default: "0.11.6" # Keep this comment to allow automatic replacement of uv version outputs: host-python-version: description: Python version used in host diff --git a/.github/actions/install-prek/action.yml b/.github/actions/install-prek/action.yml index 7e43c3245f44a..bef445aba5ae2 100644 --- a/.github/actions/install-prek/action.yml +++ b/.github/actions/install-prek/action.yml @@ -24,7 +24,7 @@ inputs: default: "3.10" uv-version: description: 'uv version to use' - default: "0.11.3" # Keep this comment to allow automatic replacement of uv version + default: "0.11.6" # Keep this comment to allow automatic replacement of uv version prek-version: description: 'prek version to use' default: "0.3.8" # Keep this comment to allow automatic replacement of prek version diff --git a/.github/workflows/basic-tests.yml b/.github/workflows/basic-tests.yml index 86360ee6def10..4f34d14055b07 100644 --- a/.github/workflows/basic-tests.yml +++ b/.github/workflows/basic-tests.yml @@ -74,7 +74,7 @@ on: # yamllint disable-line rule:truthy type: string uv-version: description: 'uv version to use' - default: "0.11.3" # Keep this comment to allow automatic replacement of uv version + default: "0.11.6" # Keep this comment to allow automatic replacement of uv version type: string platform: description: 'Platform for the build - linux/amd64 or linux/arm64' diff --git a/.github/workflows/ci-amd-arm.yml b/.github/workflows/ci-amd-arm.yml index c094a6ee82565..0dc738ad3da48 100644 --- a/.github/workflows/ci-amd-arm.yml +++ b/.github/workflows/ci-amd-arm.yml @@ -40,7 +40,7 @@ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_USERNAME: ${{ github.actor }} SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - UV_VERSION: "0.11.3" # Keep this comment to allow automatic replacement of uv version + UV_VERSION: "0.11.6" # Keep this comment to allow automatic replacement of uv version VERBOSE: "true" concurrency: diff --git a/.github/workflows/release_dockerhub_image.yml b/.github/workflows/release_dockerhub_image.yml index 3614f4c7eefb3..5468bd3d12962 100644 --- a/.github/workflows/release_dockerhub_image.yml +++ b/.github/workflows/release_dockerhub_image.yml @@ -58,7 +58,7 @@ jobs: AIRFLOW_VERSION: ${{ github.event.inputs.airflowVersion }} AMD_ONLY: ${{ github.event.inputs.amdOnly }} LIMIT_PYTHON_VERSIONS: ${{ github.event.inputs.limitPythonVersions }} - UV_VERSION: "0.11.3" # Keep this comment to allow automatic replacement of uv version + UV_VERSION: "0.11.6" # Keep this comment to allow automatic replacement of uv version if: contains(fromJSON('[ "ashb", "bugraoz93", diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 625c48d08083f..77033ceadc584 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: - id: check-hooks-apply name: Check if all hooks apply to the repository - repo: https://github.com/thlorenz/doctoc.git - rev: d7815f1f950f8d5ec933fa4f70208bf316bb13f8 # frozen: v2.3.0 + rev: 8c02ba71e7e9c5c90d85f05b676523cb8fd897c6 # frozen: v2.4.0 hooks: - id: doctoc name: Add TOC for Markdown and RST files @@ -448,7 +448,7 @@ repos: types_or: [python, pyi] args: [--fix] require_serial: true - additional_dependencies: ['ruff==0.15.9'] + additional_dependencies: ['ruff==0.15.10'] exclude: ^airflow-core/tests/unit/dags/test_imports\.py$|^performance/tests/test_.*\.py$ - id: ruff-format name: Run 'ruff format' diff --git a/Dockerfile b/Dockerfile index d6c102345e260..a37ea41884d50 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,7 +73,7 @@ ARG PYTHON_LTO="true" # Also use `force pip` label on your PR to swap all places we use `uv` to `pip` ARG AIRFLOW_PIP_VERSION=26.0.1 # ARG AIRFLOW_PIP_VERSION="git+https://github.com/pypa/pip.git@main" -ARG AIRFLOW_UV_VERSION=0.11.3 +ARG AIRFLOW_UV_VERSION=0.11.6 ARG AIRFLOW_USE_UV="false" ARG AIRFLOW_IMAGE_REPOSITORY="https://github.com/apache/airflow" ARG AIRFLOW_IMAGE_README_URL="https://raw.githubusercontent.com/apache/airflow/main/docs/docker-stack/README.md" diff --git a/Dockerfile.ci b/Dockerfile.ci index cf9f7437dc4b0..f1934e0905b33 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -1828,7 +1828,7 @@ COPY --from=scripts common.sh install_packaging_tools.sh install_additional_depe # Also use `force pip` label on your PR to swap all places we use `uv` to `pip` ARG AIRFLOW_PIP_VERSION=26.0.1 # ARG AIRFLOW_PIP_VERSION="git+https://github.com/pypa/pip.git@main" -ARG AIRFLOW_UV_VERSION=0.11.3 +ARG AIRFLOW_UV_VERSION=0.11.6 ARG AIRFLOW_PREK_VERSION="0.3.8" # UV_LINK_MODE=copy is needed since we are using cache mounted from the host diff --git a/airflow-core/docs/best-practices.rst b/airflow-core/docs/best-practices.rst index b0b75b0086aff..f86c87fa910e2 100644 --- a/airflow-core/docs/best-practices.rst +++ b/airflow-core/docs/best-practices.rst @@ -319,7 +319,7 @@ Installing and Using ruff .. code-block:: bash - pip install "ruff>=0.15.9" + pip install "ruff>=0.15.10" 2. **Running ruff**: Execute ``ruff`` to check your Dags for potential issues: diff --git a/dev/PROJECT_GUIDELINES.md b/dev/PROJECT_GUIDELINES.md index 3cd14164d4b13..5f8b787f0f94d 100644 --- a/dev/PROJECT_GUIDELINES.md +++ b/dev/PROJECT_GUIDELINES.md @@ -19,6 +19,7 @@ + - [Adding a Committer or PMC Member](#adding-a-committer-or-pmc-member) - [Airflow Improvement Proposals (AIPs)](#airflow-improvement-proposals-aips) diff --git a/dev/breeze/doc/adr/0001-record-architecture-decisions.md b/dev/breeze/doc/adr/0001-record-architecture-decisions.md index 46002151ec11a..f4fde1b0afcaf 100644 --- a/dev/breeze/doc/adr/0001-record-architecture-decisions.md +++ b/dev/breeze/doc/adr/0001-record-architecture-decisions.md @@ -19,6 +19,7 @@ + - [1. Record architecture decisions](#1-record-architecture-decisions) - [Status](#status) diff --git a/dev/breeze/doc/ci/02_images.md b/dev/breeze/doc/ci/02_images.md index 4a72605d7d52d..318ee00b61842 100644 --- a/dev/breeze/doc/ci/02_images.md +++ b/dev/breeze/doc/ci/02_images.md @@ -443,7 +443,7 @@ can be used for CI images: | `ADDITIONAL_DEV_APT_DEPS` | | Additional apt dev dependencies installed in the first part of the image | | `ADDITIONAL_DEV_APT_ENV` | | Additional env variables defined when installing dev deps | | `AIRFLOW_PIP_VERSION` | `26.0.1` | `pip` version used. | -| `AIRFLOW_UV_VERSION` | `0.11.3` | `uv` version used. | +| `AIRFLOW_UV_VERSION` | `0.11.6` | `uv` version used. | | `AIRFLOW_PREK_VERSION` | `0.3.8` | `prek` version used. | | `AIRFLOW_USE_UV` | `true` | Whether to use UV for installation. | | `PIP_PROGRESS_BAR` | `on` | Progress bar for PIP installation | diff --git a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py index 893f4167ebb0a..65442e2669216 100644 --- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py +++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py @@ -260,7 +260,7 @@ class VersionedFile(NamedTuple): AIRFLOW_PIP_VERSION = "26.0.1" -AIRFLOW_UV_VERSION = "0.11.3" +AIRFLOW_UV_VERSION = "0.11.6" AIRFLOW_USE_UV = False GITPYTHON_VERSION = "3.1.46" RICH_VERSION = "14.3.3" diff --git a/dev/breeze/src/airflow_breeze/global_constants.py b/dev/breeze/src/airflow_breeze/global_constants.py index 1a9c3c69ac513..5a54db1998a45 100644 --- a/dev/breeze/src/airflow_breeze/global_constants.py +++ b/dev/breeze/src/airflow_breeze/global_constants.py @@ -281,7 +281,7 @@ def get_allowed_llm_models() -> list[str]: ALLOWED_INSTALL_MYSQL_CLIENT_TYPES = ["mariadb"] PIP_VERSION = "26.0.1" -UV_VERSION = "0.11.3" +UV_VERSION = "0.11.6" # packages that providers docs REGULAR_DOC_PACKAGES = [ diff --git a/dev/breeze/uv.lock b/dev/breeze/uv.lock index 5bb7dad6abb31..353194ee35dd4 100644 --- a/dev/breeze/uv.lock +++ b/dev/breeze/uv.lock @@ -7,7 +7,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-04T19:45:08.465519Z" +exclude-newer = "2026-04-10T12:24:21.059635824Z" exclude-newer-span = "P4D" [[package]] @@ -264,30 +264,30 @@ wheels = [ [[package]] name = "boto3" -version = "1.42.83" +version = "1.42.87" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/87/1ed88eaa1e814841a37e71fee74c2b74341d14b791c0c6038b7ba914bea1/boto3-1.42.83.tar.gz", hash = "sha256:cc5621e603982cb3145b7f6c9970e02e297a1a0eb94637cc7f7b69d3017640ee", size = 112719, upload-time = "2026-04-03T19:34:21.254Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/f6/3f908a1313a8c8d5bf19f0cae3c372dd757569d75e8e3eee4c57fcd4e286/boto3-1.42.87.tar.gz", hash = "sha256:b5b86a826f8f12c7d38679f35bd0135807a6867a21eb8be6dea7c27aeb14ec14", size = 112793, upload-time = "2026-04-09T19:39:50.194Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/b1/8a066bc8f02937d49783c0b3948ab951d8284e6fde436cab9f359dbd4d93/boto3-1.42.83-py3-none-any.whl", hash = "sha256:544846fdb10585bb7837e409868e8e04c6b372fa04479ba1597ce82cf1242076", size = 140555, upload-time = "2026-04-03T19:34:17.935Z" }, + { url = "https://files.pythonhosted.org/packages/3b/52/69ebde82ce8b47cdee52b2450b2cbf1b3b107e192a3223bf88a567373d85/boto3-1.42.87-py3-none-any.whl", hash = "sha256:15cc1404b3ccbcfe17bd5834d467b1b28d53d9aca44e3798dc44876ac57362e6", size = 140557, upload-time = "2026-04-09T19:39:47.669Z" }, ] [[package]] name = "botocore" -version = "1.42.83" +version = "1.42.87" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4e/01/b46a3f8b6e9362258f78f1890db1a96d4ed73214d6a36420dc158dcfd221/botocore-1.42.83.tar.gz", hash = "sha256:34bc8cb64b17ac17f8901f073fe4fc9572a5cac9393a37b2b3ea372a83b87f4a", size = 15140337, upload-time = "2026-04-03T19:34:08.779Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/59/606c6cb6d42bf8ca3f422c6345401134e56d671385dc2b80fb4b09c51e67/botocore-1.42.87.tar.gz", hash = "sha256:1c6cc9555c1feec50b290a42de70ba6f04826c009562c2c12bb9990d0258482d", size = 15193113, upload-time = "2026-04-09T19:39:37.492Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/97/0d6f50822dc8c1df7f3eadb0bc6822fc0f98f02287c4efc7c7c88fde129a/botocore-1.42.83-py3-none-any.whl", hash = "sha256:ec0c3ecb3772936ed22a3bdda09883b34858933f71004686d460d829bab39d8e", size = 14818388, upload-time = "2026-04-03T19:34:03.333Z" }, + { url = "https://files.pythonhosted.org/packages/ec/1f/94e1b020fd87b52f092fdd111d9800f2411dc113a0957d0d85b7d2c7f247/botocore-1.42.87-py3-none-any.whl", hash = "sha256:32832df27c039cc1a518289afe0f6006296d3df26603b5f66e911457e67f0146", size = 14871982, upload-time = "2026-04-09T19:39:32.847Z" }, ] [[package]] @@ -509,62 +509,62 @@ wheels = [ [[package]] name = "cryptography" -version = "46.0.6" +version = "46.0.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a4/ba/04b1bd4218cbc58dc90ce967106d51582371b898690f3ae0402876cc4f34/cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759", size = 750542, upload-time = "2026-03-25T23:34:53.396Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/47/23/9285e15e3bc57325b0a72e592921983a701efc1ee8f91c06c5f0235d86d9/cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8", size = 7176401, upload-time = "2026-03-25T23:33:22.096Z" }, - { url = "https://files.pythonhosted.org/packages/60/f8/e61f8f13950ab6195b31913b42d39f0f9afc7d93f76710f299b5ec286ae6/cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30", size = 4275275, upload-time = "2026-03-25T23:33:23.844Z" }, - { url = "https://files.pythonhosted.org/packages/19/69/732a736d12c2631e140be2348b4ad3d226302df63ef64d30dfdb8db7ad1c/cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a", size = 4425320, upload-time = "2026-03-25T23:33:25.703Z" }, - { url = "https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175", size = 4278082, upload-time = "2026-03-25T23:33:27.423Z" }, - { url = "https://files.pythonhosted.org/packages/5b/ba/d5e27f8d68c24951b0a484924a84c7cdaed7502bac9f18601cd357f8b1d2/cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463", size = 4926514, upload-time = "2026-03-25T23:33:29.206Z" }, - { url = "https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97", size = 4457766, upload-time = "2026-03-25T23:33:30.834Z" }, - { url = "https://files.pythonhosted.org/packages/01/59/562be1e653accee4fdad92c7a2e88fced26b3fdfce144047519bbebc299e/cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c", size = 3986535, upload-time = "2026-03-25T23:33:33.02Z" }, - { url = "https://files.pythonhosted.org/packages/d6/8b/b1ebfeb788bf4624d36e45ed2662b8bd43a05ff62157093c1539c1288a18/cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507", size = 4277618, upload-time = "2026-03-25T23:33:34.567Z" }, - { url = "https://files.pythonhosted.org/packages/dd/52/a005f8eabdb28df57c20f84c44d397a755782d6ff6d455f05baa2785bd91/cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19", size = 4890802, upload-time = "2026-03-25T23:33:37.034Z" }, - { url = "https://files.pythonhosted.org/packages/ec/4d/8e7d7245c79c617d08724e2efa397737715ca0ec830ecb3c91e547302555/cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738", size = 4457425, upload-time = "2026-03-25T23:33:38.904Z" }, - { url = "https://files.pythonhosted.org/packages/1d/5c/f6c3596a1430cec6f949085f0e1a970638d76f81c3ea56d93d564d04c340/cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c", size = 4405530, upload-time = "2026-03-25T23:33:40.842Z" }, - { url = "https://files.pythonhosted.org/packages/7e/c9/9f9cea13ee2dbde070424e0c4f621c091a91ffcc504ffea5e74f0e1daeff/cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f", size = 4667896, upload-time = "2026-03-25T23:33:42.781Z" }, - { url = "https://files.pythonhosted.org/packages/ad/b5/1895bc0821226f129bc74d00eccfc6a5969e2028f8617c09790bf89c185e/cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2", size = 3026348, upload-time = "2026-03-25T23:33:45.021Z" }, - { url = "https://files.pythonhosted.org/packages/c3/f8/c9bcbf0d3e6ad288b9d9aa0b1dee04b063d19e8c4f871855a03ab3a297ab/cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124", size = 3483896, upload-time = "2026-03-25T23:33:46.649Z" }, - { url = "https://files.pythonhosted.org/packages/01/41/3a578f7fd5c70611c0aacba52cd13cb364a5dee895a5c1d467208a9380b0/cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275", size = 7117147, upload-time = "2026-03-25T23:33:48.249Z" }, - { url = "https://files.pythonhosted.org/packages/fa/87/887f35a6fca9dde90cad08e0de0c89263a8e59b2d2ff904fd9fcd8025b6f/cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4", size = 4266221, upload-time = "2026-03-25T23:33:49.874Z" }, - { url = "https://files.pythonhosted.org/packages/aa/a8/0a90c4f0b0871e0e3d1ed126aed101328a8a57fd9fd17f00fb67e82a51ca/cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b", size = 4408952, upload-time = "2026-03-25T23:33:52.128Z" }, - { url = "https://files.pythonhosted.org/packages/16/0b/b239701eb946523e4e9f329336e4ff32b1247e109cbab32d1a7b61da8ed7/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707", size = 4270141, upload-time = "2026-03-25T23:33:54.11Z" }, - { url = "https://files.pythonhosted.org/packages/0f/a8/976acdd4f0f30df7b25605f4b9d3d89295351665c2091d18224f7ad5cdbf/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361", size = 4904178, upload-time = "2026-03-25T23:33:55.725Z" }, - { url = "https://files.pythonhosted.org/packages/b1/1b/bf0e01a88efd0e59679b69f42d4afd5bced8700bb5e80617b2d63a3741af/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b", size = 4441812, upload-time = "2026-03-25T23:33:57.364Z" }, - { url = "https://files.pythonhosted.org/packages/bb/8b/11df86de2ea389c65aa1806f331cae145f2ed18011f30234cc10ca253de8/cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca", size = 3963923, upload-time = "2026-03-25T23:33:59.361Z" }, - { url = "https://files.pythonhosted.org/packages/91/e0/207fb177c3a9ef6a8108f234208c3e9e76a6aa8cf20d51932916bd43bda0/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013", size = 4269695, upload-time = "2026-03-25T23:34:00.909Z" }, - { url = "https://files.pythonhosted.org/packages/21/5e/19f3260ed1e95bced52ace7501fabcd266df67077eeb382b79c81729d2d3/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4", size = 4869785, upload-time = "2026-03-25T23:34:02.796Z" }, - { url = "https://files.pythonhosted.org/packages/10/38/cd7864d79aa1d92ef6f1a584281433419b955ad5a5ba8d1eb6c872165bcb/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a", size = 4441404, upload-time = "2026-03-25T23:34:04.35Z" }, - { url = "https://files.pythonhosted.org/packages/09/0a/4fe7a8d25fed74419f91835cf5829ade6408fd1963c9eae9c4bce390ecbb/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d", size = 4397549, upload-time = "2026-03-25T23:34:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/5f/a0/7d738944eac6513cd60a8da98b65951f4a3b279b93479a7e8926d9cd730b/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736", size = 4651874, upload-time = "2026-03-25T23:34:07.916Z" }, - { url = "https://files.pythonhosted.org/packages/cb/f1/c2326781ca05208845efca38bf714f76939ae446cd492d7613808badedf1/cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed", size = 3001511, upload-time = "2026-03-25T23:34:09.892Z" }, - { url = "https://files.pythonhosted.org/packages/c9/57/fe4a23eb549ac9d903bd4698ffda13383808ef0876cc912bcb2838799ece/cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4", size = 3471692, upload-time = "2026-03-25T23:34:11.613Z" }, - { url = "https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a", size = 7162776, upload-time = "2026-03-25T23:34:13.308Z" }, - { url = "https://files.pythonhosted.org/packages/49/b3/dc27efd8dcc4bff583b3f01d4a3943cd8b5821777a58b3a6a5f054d61b79/cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8", size = 4270529, upload-time = "2026-03-25T23:34:15.019Z" }, - { url = "https://files.pythonhosted.org/packages/e6/05/e8d0e6eb4f0d83365b3cb0e00eb3c484f7348db0266652ccd84632a3d58d/cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77", size = 4414827, upload-time = "2026-03-25T23:34:16.604Z" }, - { url = "https://files.pythonhosted.org/packages/2f/97/daba0f5d2dc6d855e2dcb70733c812558a7977a55dd4a6722756628c44d1/cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290", size = 4271265, upload-time = "2026-03-25T23:34:18.586Z" }, - { url = "https://files.pythonhosted.org/packages/89/06/fe1fce39a37ac452e58d04b43b0855261dac320a2ebf8f5260dd55b201a9/cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410", size = 4916800, upload-time = "2026-03-25T23:34:20.561Z" }, - { url = "https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d", size = 4448771, upload-time = "2026-03-25T23:34:22.406Z" }, - { url = "https://files.pythonhosted.org/packages/01/b3/0796998056a66d1973fd52ee89dc1bb3b6581960a91ad4ac705f182d398f/cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70", size = 3978333, upload-time = "2026-03-25T23:34:24.281Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3d/db200af5a4ffd08918cd55c08399dc6c9c50b0bc72c00a3246e099d3a849/cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d", size = 4271069, upload-time = "2026-03-25T23:34:25.895Z" }, - { url = "https://files.pythonhosted.org/packages/d7/18/61acfd5b414309d74ee838be321c636fe71815436f53c9f0334bf19064fa/cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa", size = 4878358, upload-time = "2026-03-25T23:34:27.67Z" }, - { url = "https://files.pythonhosted.org/packages/8b/65/5bf43286d566f8171917cae23ac6add941654ccf085d739195a4eacf1674/cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58", size = 4448061, upload-time = "2026-03-25T23:34:29.375Z" }, - { url = "https://files.pythonhosted.org/packages/e0/25/7e49c0fa7205cf3597e525d156a6bce5b5c9de1fd7e8cb01120e459f205a/cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb", size = 4399103, upload-time = "2026-03-25T23:34:32.036Z" }, - { url = "https://files.pythonhosted.org/packages/44/46/466269e833f1c4718d6cd496ffe20c56c9c8d013486ff66b4f69c302a68d/cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72", size = 4659255, upload-time = "2026-03-25T23:34:33.679Z" }, - { url = "https://files.pythonhosted.org/packages/0a/09/ddc5f630cc32287d2c953fc5d32705e63ec73e37308e5120955316f53827/cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c", size = 3010660, upload-time = "2026-03-25T23:34:35.418Z" }, - { url = "https://files.pythonhosted.org/packages/1b/82/ca4893968aeb2709aacfb57a30dec6fa2ab25b10fa9f064b8882ce33f599/cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f", size = 3471160, upload-time = "2026-03-25T23:34:37.191Z" }, - { url = "https://files.pythonhosted.org/packages/2e/84/7ccff00ced5bac74b775ce0beb7d1be4e8637536b522b5df9b73ada42da2/cryptography-46.0.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead", size = 3475444, upload-time = "2026-03-25T23:34:38.944Z" }, - { url = "https://files.pythonhosted.org/packages/bc/1f/4c926f50df7749f000f20eede0c896769509895e2648db5da0ed55db711d/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8", size = 4218227, upload-time = "2026-03-25T23:34:40.871Z" }, - { url = "https://files.pythonhosted.org/packages/c6/65/707be3ffbd5f786028665c3223e86e11c4cda86023adbc56bd72b1b6bab5/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0", size = 4381399, upload-time = "2026-03-25T23:34:42.609Z" }, - { url = "https://files.pythonhosted.org/packages/f3/6d/73557ed0ef7d73d04d9aba745d2c8e95218213687ee5e76b7d236a5030fc/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b", size = 4217595, upload-time = "2026-03-25T23:34:44.205Z" }, - { url = "https://files.pythonhosted.org/packages/9e/c5/e1594c4eec66a567c3ac4400008108a415808be2ce13dcb9a9045c92f1a0/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a", size = 4380912, upload-time = "2026-03-25T23:34:46.328Z" }, - { url = "https://files.pythonhosted.org/packages/1a/89/843b53614b47f97fe1abc13f9a86efa5ec9e275292c457af1d4a60dc80e0/cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e", size = 3409955, upload-time = "2026-03-25T23:34:48.465Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/47/93/ac8f3d5ff04d54bc814e961a43ae5b0b146154c89c61b47bb07557679b18/cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5", size = 750652, upload-time = "2026-04-08T01:57:54.692Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/5d/4a8f770695d73be252331e60e526291e3df0c9b27556a90a6b47bccca4c2/cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4", size = 7179869, upload-time = "2026-04-08T01:56:17.157Z" }, + { url = "https://files.pythonhosted.org/packages/5f/45/6d80dc379b0bbc1f9d1e429f42e4cb9e1d319c7a8201beffd967c516ea01/cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325", size = 4275492, upload-time = "2026-04-08T01:56:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/1765afe9f572e239c3469f2cb429f3ba7b31878c893b246b4b2994ffe2fe/cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308", size = 4426670, upload-time = "2026-04-08T01:56:21.415Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3e/af9246aaf23cd4ee060699adab1e47ced3f5f7e7a8ffdd339f817b446462/cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77", size = 4280275, upload-time = "2026-04-08T01:56:23.539Z" }, + { url = "https://files.pythonhosted.org/packages/0f/54/6bbbfc5efe86f9d71041827b793c24811a017c6ac0fd12883e4caa86b8ed/cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1", size = 4928402, upload-time = "2026-04-08T01:56:25.624Z" }, + { url = "https://files.pythonhosted.org/packages/2d/cf/054b9d8220f81509939599c8bdbc0c408dbd2bdd41688616a20731371fe0/cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef", size = 4459985, upload-time = "2026-04-08T01:56:27.309Z" }, + { url = "https://files.pythonhosted.org/packages/f9/46/4e4e9c6040fb01c7467d47217d2f882daddeb8828f7df800cb806d8a2288/cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de", size = 3990652, upload-time = "2026-04-08T01:56:29.095Z" }, + { url = "https://files.pythonhosted.org/packages/36/5f/313586c3be5a2fbe87e4c9a254207b860155a8e1f3cca99f9910008e7d08/cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83", size = 4279805, upload-time = "2026-04-08T01:56:30.928Z" }, + { url = "https://files.pythonhosted.org/packages/69/33/60dfc4595f334a2082749673386a4d05e4f0cf4df8248e63b2c3437585f2/cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb", size = 4892883, upload-time = "2026-04-08T01:56:32.614Z" }, + { url = "https://files.pythonhosted.org/packages/c7/0b/333ddab4270c4f5b972f980adef4faa66951a4aaf646ca067af597f15563/cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b", size = 4459756, upload-time = "2026-04-08T01:56:34.306Z" }, + { url = "https://files.pythonhosted.org/packages/d2/14/633913398b43b75f1234834170947957c6b623d1701ffc7a9600da907e89/cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85", size = 4410244, upload-time = "2026-04-08T01:56:35.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/f2/19ceb3b3dc14009373432af0c13f46aa08e3ce334ec6eff13492e1812ccd/cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e", size = 4674868, upload-time = "2026-04-08T01:56:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/1a/bb/a5c213c19ee94b15dfccc48f363738633a493812687f5567addbcbba9f6f/cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457", size = 3026504, upload-time = "2026-04-08T01:56:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/2b/02/7788f9fefa1d060ca68717c3901ae7fffa21ee087a90b7f23c7a603c32ae/cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b", size = 3488363, upload-time = "2026-04-08T01:56:41.893Z" }, + { url = "https://files.pythonhosted.org/packages/7b/56/15619b210e689c5403bb0540e4cb7dbf11a6bf42e483b7644e471a2812b3/cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842", size = 7119671, upload-time = "2026-04-08T01:56:44Z" }, + { url = "https://files.pythonhosted.org/packages/74/66/e3ce040721b0b5599e175ba91ab08884c75928fbeb74597dd10ef13505d2/cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c", size = 4268551, upload-time = "2026-04-08T01:56:46.071Z" }, + { url = "https://files.pythonhosted.org/packages/03/11/5e395f961d6868269835dee1bafec6a1ac176505a167f68b7d8818431068/cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902", size = 4408887, upload-time = "2026-04-08T01:56:47.718Z" }, + { url = "https://files.pythonhosted.org/packages/40/53/8ed1cf4c3b9c8e611e7122fb56f1c32d09e1fff0f1d77e78d9ff7c82653e/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d", size = 4271354, upload-time = "2026-04-08T01:56:49.312Z" }, + { url = "https://files.pythonhosted.org/packages/50/46/cf71e26025c2e767c5609162c866a78e8a2915bbcfa408b7ca495c6140c4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022", size = 4905845, upload-time = "2026-04-08T01:56:50.916Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ea/01276740375bac6249d0a971ebdf6b4dc9ead0ee0a34ef3b5a88c1a9b0d4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce", size = 4444641, upload-time = "2026-04-08T01:56:52.882Z" }, + { url = "https://files.pythonhosted.org/packages/3d/4c/7d258f169ae71230f25d9f3d06caabcff8c3baf0978e2b7d65e0acac3827/cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f", size = 3967749, upload-time = "2026-04-08T01:56:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/2ea0767cad19e71b3530e4cad9605d0b5e338b6a1e72c37c9c1ceb86c333/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99", size = 4270942, upload-time = "2026-04-08T01:56:56.416Z" }, + { url = "https://files.pythonhosted.org/packages/41/3d/fe14df95a83319af25717677e956567a105bb6ab25641acaa093db79975d/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1", size = 4871079, upload-time = "2026-04-08T01:56:58.31Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/4a479e0f36f8f378d397f4eab4c850b4ffb79a2f0d58704b8fa0703ddc11/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2", size = 4443999, upload-time = "2026-04-08T01:57:00.508Z" }, + { url = "https://files.pythonhosted.org/packages/28/17/b59a741645822ec6d04732b43c5d35e4ef58be7bfa84a81e5ae6f05a1d33/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e", size = 4399191, upload-time = "2026-04-08T01:57:02.654Z" }, + { url = "https://files.pythonhosted.org/packages/59/6a/bb2e166d6d0e0955f1e9ff70f10ec4b2824c9cfcdb4da772c7dd69cc7d80/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee", size = 4655782, upload-time = "2026-04-08T01:57:04.592Z" }, + { url = "https://files.pythonhosted.org/packages/95/b6/3da51d48415bcb63b00dc17c2eff3a651b7c4fed484308d0f19b30e8cb2c/cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298", size = 3002227, upload-time = "2026-04-08T01:57:06.91Z" }, + { url = "https://files.pythonhosted.org/packages/32/a8/9f0e4ed57ec9cebe506e58db11ae472972ecb0c659e4d52bbaee80ca340a/cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb", size = 3475332, upload-time = "2026-04-08T01:57:08.807Z" }, + { url = "https://files.pythonhosted.org/packages/a7/7f/cd42fc3614386bc0c12f0cb3c4ae1fc2bbca5c9662dfed031514911d513d/cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4", size = 7165618, upload-time = "2026-04-08T01:57:10.645Z" }, + { url = "https://files.pythonhosted.org/packages/a5/d0/36a49f0262d2319139d2829f773f1b97ef8aef7f97e6e5bd21455e5a8fb5/cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7", size = 4270628, upload-time = "2026-04-08T01:57:12.885Z" }, + { url = "https://files.pythonhosted.org/packages/8a/6c/1a42450f464dda6ffbe578a911f773e54dd48c10f9895a23a7e88b3e7db5/cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832", size = 4415405, upload-time = "2026-04-08T01:57:14.923Z" }, + { url = "https://files.pythonhosted.org/packages/9a/92/4ed714dbe93a066dc1f4b4581a464d2d7dbec9046f7c8b7016f5286329e2/cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163", size = 4272715, upload-time = "2026-04-08T01:57:16.638Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e6/a26b84096eddd51494bba19111f8fffe976f6a09f132706f8f1bf03f51f7/cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2", size = 4918400, upload-time = "2026-04-08T01:57:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/c7/08/ffd537b605568a148543ac3c2b239708ae0bd635064bab41359252ef88ed/cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067", size = 4450634, upload-time = "2026-04-08T01:57:21.185Z" }, + { url = "https://files.pythonhosted.org/packages/16/01/0cd51dd86ab5b9befe0d031e276510491976c3a80e9f6e31810cce46c4ad/cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0", size = 3985233, upload-time = "2026-04-08T01:57:22.862Z" }, + { url = "https://files.pythonhosted.org/packages/92/49/819d6ed3a7d9349c2939f81b500a738cb733ab62fbecdbc1e38e83d45e12/cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba", size = 4271955, upload-time = "2026-04-08T01:57:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/80/07/ad9b3c56ebb95ed2473d46df0847357e01583f4c52a85754d1a55e29e4d0/cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006", size = 4879888, upload-time = "2026-04-08T01:57:26.88Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c7/201d3d58f30c4c2bdbe9b03844c291feb77c20511cc3586daf7edc12a47b/cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0", size = 4449961, upload-time = "2026-04-08T01:57:29.068Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ef/649750cbf96f3033c3c976e112265c33906f8e462291a33d77f90356548c/cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85", size = 4401696, upload-time = "2026-04-08T01:57:31.029Z" }, + { url = "https://files.pythonhosted.org/packages/41/52/a8908dcb1a389a459a29008c29966c1d552588d4ae6d43f3a1a4512e0ebe/cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e", size = 4664256, upload-time = "2026-04-08T01:57:33.144Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fa/f0ab06238e899cc3fb332623f337a7364f36f4bb3f2534c2bb95a35b132c/cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246", size = 3013001, upload-time = "2026-04-08T01:57:34.933Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f1/00ce3bde3ca542d1acd8f8cfa38e446840945aa6363f9b74746394b14127/cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3", size = 3472985, upload-time = "2026-04-08T01:57:36.714Z" }, + { url = "https://files.pythonhosted.org/packages/63/0c/dca8abb64e7ca4f6b2978769f6fea5ad06686a190cec381f0a796fdcaaba/cryptography-46.0.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f", size = 3476879, upload-time = "2026-04-08T01:57:38.664Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/075aac6a84b7c271578d81a2f9968acb6e273002408729f2ddff517fed4a/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15", size = 4219700, upload-time = "2026-04-08T01:57:40.625Z" }, + { url = "https://files.pythonhosted.org/packages/6c/7b/1c55db7242b5e5612b29fc7a630e91ee7a6e3c8e7bf5406d22e206875fbd/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455", size = 4385982, upload-time = "2026-04-08T01:57:42.725Z" }, + { url = "https://files.pythonhosted.org/packages/cb/da/9870eec4b69c63ef5925bf7d8342b7e13bc2ee3d47791461c4e49ca212f4/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65", size = 4219115, upload-time = "2026-04-08T01:57:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/72/05aa5832b82dd341969e9a734d1812a6aadb088d9eb6f0430fc337cc5a8f/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968", size = 4385479, upload-time = "2026-04-08T01:57:46.86Z" }, + { url = "https://files.pythonhosted.org/packages/20/2a/1b016902351a523aa2bd446b50a5bc1175d7a7d1cf90fe2ef904f9b84ebc/cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4", size = 3412829, upload-time = "2026-04-08T01:57:48.874Z" }, ] [[package]] @@ -666,7 +666,7 @@ wheels = [ [[package]] name = "google-api-core" -version = "2.30.2" +version = "2.30.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, @@ -675,14 +675,14 @@ dependencies = [ { name = "protobuf" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1a/2e/83ca41eb400eb228f9279ec14ed66f6475218b59af4c6daec2d5a509fe83/google_api_core-2.30.2.tar.gz", hash = "sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9", size = 176862, upload-time = "2026-04-02T21:23:44.876Z" } +sdist = { url = "https://files.pythonhosted.org/packages/16/ce/502a57fb0ec752026d24df1280b162294b22a0afb98a326084f9a979138b/google_api_core-2.30.3.tar.gz", hash = "sha256:e601a37f148585319b26db36e219df68c5d07b6382cff2d580e83404e44d641b", size = 177001, upload-time = "2026-04-10T00:41:28.035Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl", hash = "sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594", size = 173236, upload-time = "2026-04-02T21:23:06.395Z" }, + { url = "https://files.pythonhosted.org/packages/03/15/e56f351cf6ef1cfea58e6ac226a7318ed1deb2218c4b3cc9bd9e4b786c5a/google_api_core-2.30.3-py3-none-any.whl", hash = "sha256:a85761ba72c444dad5d611c2220633480b2b6be2521eca69cca2dbb3ffd6bfe8", size = 173274, upload-time = "2026-04-09T22:57:16.198Z" }, ] [[package]] name = "google-api-python-client" -version = "2.193.0" +version = "2.194.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -691,22 +691,22 @@ dependencies = [ { name = "httplib2" }, { name = "uritemplate" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/90/f4/e14b6815d3b1885328dd209676a3a4c704882743ac94e18ef0093894f5c8/google_api_python_client-2.193.0.tar.gz", hash = "sha256:8f88d16e89d11341e0a8b199cafde0fb7e6b44260dffb88d451577cbd1bb5d33", size = 14281006, upload-time = "2026-03-17T18:25:29.415Z" } +sdist = { url = "https://files.pythonhosted.org/packages/60/ab/e83af0eb043e4ccc49571ca7a6a49984e9d00f4e9e6e6f1238d60bc84dce/google_api_python_client-2.194.0.tar.gz", hash = "sha256:db92647bd1a90f40b79c9618461553c2b20b6a43ce7395fa6de07132dc14f023", size = 14443469, upload-time = "2026-04-08T23:07:35.757Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f0/6d/fe75167797790a56d17799b75e1129bb93f7ff061efc7b36e9731bd4be2b/google_api_python_client-2.193.0-py3-none-any.whl", hash = "sha256:c42aa324b822109901cfecab5dc4fc3915d35a7b376835233c916c70610322db", size = 14856490, upload-time = "2026-03-17T18:25:26.608Z" }, + { url = "https://files.pythonhosted.org/packages/b0/34/5a624e49f179aa5b0cb87b2ce8093960299030ff40423bfbde09360eb908/google_api_python_client-2.194.0-py3-none-any.whl", hash = "sha256:61eaaac3b8fc8fdf11c08af87abc3d1342d1b37319cc1b57405f86ef7697e717", size = 15016514, upload-time = "2026-04-08T23:07:33.093Z" }, ] [[package]] name = "google-auth" -version = "2.49.1" +version = "2.49.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/80/6a696a07d3d3b0a92488933532f03dbefa4a24ab80fb231395b9a2a1be77/google_auth-2.49.1.tar.gz", hash = "sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64", size = 333825, upload-time = "2026-03-12T19:30:58.135Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c6/fc/e925290a1ad95c975c459e2df070fac2b90954e13a0370ac505dff78cb99/google_auth-2.49.2.tar.gz", hash = "sha256:c1ae38500e73065dcae57355adb6278cf8b5c8e391994ae9cbadbcb9631ab409", size = 333958, upload-time = "2026-04-10T00:41:21.888Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl", hash = "sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7", size = 240737, upload-time = "2026-03-12T19:30:53.159Z" }, + { url = "https://files.pythonhosted.org/packages/73/76/d241a5c927433420507215df6cac1b1fa4ac0ba7a794df42a84326c68da8/google_auth-2.49.2-py3-none-any.whl", hash = "sha256:c2720924dfc82dedb962c9f52cabb2ab16714fd0a6a707e40561d217574ed6d5", size = 240638, upload-time = "2026-04-10T00:41:14.501Z" }, ] [[package]] @@ -1122,11 +1122,11 @@ wheels = [ [[package]] name = "more-itertools" -version = "11.0.1" +version = "11.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/24/e0acc4bf54cba50c1d432c70a72a3df96db4a321b2c4c68432a60759044f/more_itertools-11.0.1.tar.gz", hash = "sha256:fefaf25b7ab08f0b45fa9f1892cae93b9fc0089ef034d39213bce15f1cc9e199", size = 144739, upload-time = "2026-04-02T16:17:45.061Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/f7/139d22fef48ac78127d18e01d80cf1be40236ae489769d17f35c3d425293/more_itertools-11.0.2.tar.gz", hash = "sha256:392a9e1e362cbc106a2457d37cabf9b36e5e12efd4ebff1654630e76597df804", size = 144659, upload-time = "2026-04-09T15:01:33.297Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/f4/5e52c7319b8087acef603ed6e50dc325c02eaa999355414830468611f13c/more_itertools-11.0.1-py3-none-any.whl", hash = "sha256:eaf287826069452a8f61026c597eae2428b2d1ba2859083abbf240b46842ce6d", size = 72182, upload-time = "2026-04-02T16:17:43.724Z" }, + { url = "https://files.pythonhosted.org/packages/cb/98/6af411189d9413534c3eb691182bff1f5c6d44ed2f93f2edfe52a1bbceb8/more_itertools-11.0.2-py3-none-any.whl", hash = "sha256:6e35b35f818b01f691643c6c611bc0902f2e92b46c18fffa77ae1e7c46e912e4", size = 71939, upload-time = "2026-04-09T15:01:32.21Z" }, ] [[package]] @@ -1222,11 +1222,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.9.4" +version = "4.9.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/19/56/8d4c30c8a1d07013911a8fdbd8f89440ef9f08d07a1b50ab8ca8be5a20f9/platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", size = 28737, upload-time = "2026-03-05T18:34:13.271Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868", size = 21216, upload-time = "2026-03-05T18:34:12.172Z" }, + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, ] [[package]] @@ -1453,7 +1453,7 @@ wheels = [ [[package]] name = "pytest" -version = "9.0.2" +version = "9.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1464,9 +1464,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, + { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, ] [[package]] @@ -1496,15 +1496,15 @@ wheels = [ [[package]] name = "python-discovery" -version = "1.2.1" +version = "1.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/88/815e53084c5079a59df912825a279f41dd2e0df82281770eadc732f5352c/python_discovery-1.2.1.tar.gz", hash = "sha256:180c4d114bff1c32462537eac5d6a332b768242b76b69c0259c7d14b1b680c9e", size = 58457, upload-time = "2026-03-26T22:30:44.496Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872, upload-time = "2026-04-07T17:28:49.249Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl", hash = "sha256:b6a957b24c1cd79252484d3566d1b49527581d46e789aaf43181005e56201502", size = 31674, upload-time = "2026-03-26T22:30:43.396Z" }, + { url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894, upload-time = "2026-04-07T17:28:48.09Z" }, ] [[package]] @@ -2082,33 +2082,33 @@ wheels = [ [[package]] name = "uv" -version = "0.11.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/ed/f11c558e8d2e02fba6057dacd9e92a71557359a80bd5355452310b89f40f/uv-0.11.3.tar.gz", hash = "sha256:6a6fcaf1fec28bbbdf0dfc5a0a6e34be4cea08c6287334b08c24cf187300f20d", size = 4027684, upload-time = "2026-04-01T21:47:22.096Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/93/4f04c49fd6046a18293de341d795ded3b9cbd95db261d687e26db0f11d1e/uv-0.11.3-py3-none-linux_armv6l.whl", hash = "sha256:deb533e780e8181e0859c68c84f546620072cd1bd827b38058cb86ebfba9bb7d", size = 23337334, upload-time = "2026-04-01T21:46:47.545Z" }, - { url = "https://files.pythonhosted.org/packages/7a/4b/c44fd3fbc80ac2f81e2ad025d235c820aac95b228076da85be3f5d509781/uv-0.11.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d2b3b0fa1693880ca354755c216ae1c65dd938a4f1a24374d0c3f4b9538e0ee6", size = 22940169, upload-time = "2026-04-01T21:47:32.72Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c7/7d01be259a47d42fa9e80adcb7a829d81e7c376aa8fa1b714f31d7dfc226/uv-0.11.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:71f5d0b9e73daa5d8a7e2db3fa2e22a4537d24bb4fe78130db797280280d4edc", size = 21473579, upload-time = "2026-04-01T21:47:25.063Z" }, - { url = "https://files.pythonhosted.org/packages/9a/71/fffcd890290a4639a3799cf3f3e87947c10d1b0de19eba3cf837cb418dd8/uv-0.11.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:55ba578752f29a3f2b22879b22a162edad1454e3216f3ca4694fdbd4093a6822", size = 23132691, upload-time = "2026-04-01T21:47:44.587Z" }, - { url = "https://files.pythonhosted.org/packages/d1/7b/1ac9e1f753a19b6252434f0bbe96efdcc335cd74677f4c6f431a7c916114/uv-0.11.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:3b1fe09d5e1d8e19459cd28d7825a3b66ef147b98328345bad6e17b87c4fea48", size = 22955764, upload-time = "2026-04-01T21:46:51.721Z" }, - { url = "https://files.pythonhosted.org/packages/ff/51/1a6010a681a3c3e0a8ec99737ba2d0452194dc372a5349a9267873261c02/uv-0.11.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:088165b9eed981d2c2a58566cc75dd052d613e47c65e2416842d07308f793a6f", size = 22966245, upload-time = "2026-04-01T21:47:07.403Z" }, - { url = "https://files.pythonhosted.org/packages/38/74/1a1b0712daead7e85f56d620afe96fe166a04b615524c14027b4edd39b82/uv-0.11.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef0ae8ee2988928092616401ec7f473612b8e9589fe1567452c45dbc56840f85", size = 24623370, upload-time = "2026-04-01T21:47:03.59Z" }, - { url = "https://files.pythonhosted.org/packages/b6/62/5c3aa5e7bd2744810e50ad72a5951386ec84a513e109b1b5cb7ec442f3b6/uv-0.11.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6708827ecb846d00c5512a7e4dc751c2e27b92e9bd55a0be390561ac68930c32", size = 25142735, upload-time = "2026-04-01T21:46:55.756Z" }, - { url = "https://files.pythonhosted.org/packages/88/ab/6266a04980e0877af5518762adfe23a0c1ab0b801ae3099a2e7b74e34411/uv-0.11.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8df030ea7563e99c09854e1bc82ab743dfa2d0ba18976e6861979cb40d04dba7", size = 24512083, upload-time = "2026-04-01T21:46:43.531Z" }, - { url = "https://files.pythonhosted.org/packages/4e/be/7c66d350f833eb437f9aa0875655cc05e07b441e3f4a770f8bced56133f7/uv-0.11.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fde893b5ab9f6997fe357138e794bac09d144328052519fbbe2e6f72145e457", size = 24589293, upload-time = "2026-04-01T21:47:11.379Z" }, - { url = "https://files.pythonhosted.org/packages/18/4f/22ada41564a8c8c36653fc86f89faae4c54a4cdd5817bda53764a3eb352d/uv-0.11.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:45006bcd9e8718248a23ab81448a5beb46a72a9dd508e3212d6f3b8c63aeb88a", size = 23214854, upload-time = "2026-04-01T21:46:59.491Z" }, - { url = "https://files.pythonhosted.org/packages/aa/18/8669840657fea9fd668739dec89643afe1061c023c1488228b02f79a2399/uv-0.11.3-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:089b9d338a64463956b6fee456f03f73c9a916479bdb29009600781dc1e1d2a7", size = 23914434, upload-time = "2026-04-01T21:47:29.164Z" }, - { url = "https://files.pythonhosted.org/packages/08/0d/c59f24b3a1ae5f377aa6fd9653562a0968ea6be946fe35761871a0072919/uv-0.11.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3ff461335888336467402cc5cb792c911df95dd0b52e369182cfa4c902bb21f4", size = 23971481, upload-time = "2026-04-01T21:47:48.551Z" }, - { url = "https://files.pythonhosted.org/packages/66/7d/f83ed79921310ef216ed6d73fcd3822dff4b66749054fb97e09b7bd5901e/uv-0.11.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:a62e29277efd39c35caf4a0fe739c4ebeb14d4ce4f02271f3f74271d608061ff", size = 23784797, upload-time = "2026-04-01T21:47:40.588Z" }, - { url = "https://files.pythonhosted.org/packages/35/19/3ff3539c44ca7dc2aa87b021d4a153ba6a72866daa19bf91c289e4318f95/uv-0.11.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:ebccdcdebd2b288925f0f7c18c39705dc783175952eacaf94912b01d3b381b86", size = 24794606, upload-time = "2026-04-01T21:47:36.814Z" }, - { url = "https://files.pythonhosted.org/packages/79/e5/e676454bb7cc5dcf5c4637ed3ef0ff97309d84a149b832a4dea53f04c0ab/uv-0.11.3-py3-none-win32.whl", hash = "sha256:794aae3bab141eafbe37c51dc5dd0139658a755a6fa9cc74d2dbd7c71dcc4826", size = 22573432, upload-time = "2026-04-01T21:47:15.143Z" }, - { url = "https://files.pythonhosted.org/packages/ff/a0/95d22d524bd3b4708043d65035f02fc9656e5fb6e0aaef73510313b1641b/uv-0.11.3-py3-none-win_amd64.whl", hash = "sha256:68fda574f2e5e7536a2b747dcea88329a71aad7222317e8f4717d0af8f99fbd4", size = 24969508, upload-time = "2026-04-01T21:47:19.515Z" }, - { url = "https://files.pythonhosted.org/packages/f8/6d/3f0b90a06e8c4594e11f813651756d6896de6dd4461f554fd7e4984a1c4f/uv-0.11.3-py3-none-win_arm64.whl", hash = "sha256:92ffc4d521ab2c4738ef05d8ef26f2750e26d31f3ad5611cdfefc52445be9ace", size = 23488911, upload-time = "2026-04-01T21:47:52.427Z" }, +version = "0.11.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/f3/8aceeab67ea69805293ab290e7ca8cc1b61a064d28b8a35c76d8eba063dd/uv-0.11.6.tar.gz", hash = "sha256:e3b21b7e80024c95ff339fcd147ac6fc3dd98d3613c9d45d3a1f4fd1057f127b", size = 4073298, upload-time = "2026-04-09T12:09:01.738Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/fe/4b61a3d5ad9d02e8a4405026ccd43593d7044598e0fa47d892d4dafe44c9/uv-0.11.6-py3-none-linux_armv6l.whl", hash = "sha256:ada04dcf89ddea5b69d27ac9cdc5ef575a82f90a209a1392e930de504b2321d6", size = 23780079, upload-time = "2026-04-09T12:08:56.609Z" }, + { url = "https://files.pythonhosted.org/packages/52/db/d27519a9e1a5ffee9d71af1a811ad0e19ce7ab9ae815453bef39dd479389/uv-0.11.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5be013888420f96879c6e0d3081e7bcf51b539b034a01777041934457dfbedf3", size = 23214721, upload-time = "2026-04-09T12:09:32.228Z" }, + { url = "https://files.pythonhosted.org/packages/a6/8f/4399fa8b882bd7e0efffc829f73ab24d117d490a93e6bc7104a50282b854/uv-0.11.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ffa5dc1cbb52bdce3b8447e83d1601a57ad4da6b523d77d4b47366db8b1ceb18", size = 21750109, upload-time = "2026-04-09T12:09:24.357Z" }, + { url = "https://files.pythonhosted.org/packages/32/07/5a12944c31c3dda253632da7a363edddb869ed47839d4d92a2dc5f546c93/uv-0.11.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:bfb107b4dade1d2c9e572992b06992d51dd5f2136eb8ceee9e62dd124289e825", size = 23551146, upload-time = "2026-04-09T12:09:10.439Z" }, + { url = "https://files.pythonhosted.org/packages/79/5b/2ec8b0af80acd1016ed596baf205ddc77b19ece288473b01926c4a9cf6db/uv-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:9e2fe7ce12161d8016b7deb1eaad7905a76ff7afec13383333ca75e0c4b5425d", size = 23331192, upload-time = "2026-04-09T12:09:34.792Z" }, + { url = "https://files.pythonhosted.org/packages/62/7d/eea35935f2112b21c296a3e42645f3e4b1aa8bcd34dcf13345fbd55134b7/uv-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ed9c6f70c25e8dfeedddf4eddaf14d353f5e6b0eb43da9a14d3a1033d51d915", size = 23337686, upload-time = "2026-04-09T12:09:18.522Z" }, + { url = "https://files.pythonhosted.org/packages/21/47/2584f5ab618f6ebe9bdefb2f765f2ca8540e9d739667606a916b35449eec/uv-0.11.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d68a013e609cebf82077cbeeb0809ed5e205257814273bfd31e02fc0353bbfc2", size = 25008139, upload-time = "2026-04-09T12:09:03.983Z" }, + { url = "https://files.pythonhosted.org/packages/95/81/497ae5c1d36355b56b97dc59f550c7e89d0291c163a3f203c6f341dff195/uv-0.11.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93f736dddca03dae732c6fdea177328d3bc4bf137c75248f3d433c57416a4311", size = 25712458, upload-time = "2026-04-09T12:09:07.598Z" }, + { url = "https://files.pythonhosted.org/packages/3c/1c/74083238e4fab2672b63575b9008f1ea418b02a714bcfcf017f4f6a309b6/uv-0.11.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e96a66abe53fced0e3389008b8d2eff8278cfa8bb545d75631ae8ceb9c929aba", size = 24915507, upload-time = "2026-04-09T12:08:50.892Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ee/e14fe10ba455a823ed18233f12de6699a601890905420b5c504abf115116/uv-0.11.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b096311b2743b228df911a19532b3f18fa420bf9530547aecd6a8e04bbfaccd", size = 24971011, upload-time = "2026-04-09T12:08:54.016Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/7b9c83eaadf98e343317ff6384a7227a4855afd02cdaf9696bcc71ee6155/uv-0.11.6-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:904d537b4a6e798015b4a64ff5622023bd4601b43b6cd1e5f423d63471f5e948", size = 23640234, upload-time = "2026-04-09T12:09:15.735Z" }, + { url = "https://files.pythonhosted.org/packages/d6/51/75ccdd23e76ff1703b70eb82881cd5b4d2a954c9679f8ef7e0136ef2cfab/uv-0.11.6-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:4ed8150c26b5e319381d75ae2ce6aba1e9c65888f4850f4e3b3fa839953c90a5", size = 24452664, upload-time = "2026-04-09T12:09:26.875Z" }, + { url = "https://files.pythonhosted.org/packages/4d/86/ace80fe47d8d48b5e3b5aee0b6eb1a49deaacc2313782870250b3faa36f5/uv-0.11.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1c9218c8d4ac35ca6e617fb0951cc0ab2d907c91a6aea2617de0a5494cf162c0", size = 24494599, upload-time = "2026-04-09T12:09:37.368Z" }, + { url = "https://files.pythonhosted.org/packages/05/2d/4b642669b56648194f026de79bc992cbfc3ac2318b0a8d435f3c284934e8/uv-0.11.6-py3-none-musllinux_1_1_i686.whl", hash = "sha256:9e211c83cc890c569b86a4183fcf5f8b6f0c7adc33a839b699a98d30f1310d3a", size = 24159150, upload-time = "2026-04-09T12:09:13.17Z" }, + { url = "https://files.pythonhosted.org/packages/ae/24/7eecd76fe983a74fed1fc700a14882e70c4e857f1d562a9f2303d4286c12/uv-0.11.6-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d2a1d2089afdf117ad19a4c1dd36b8189c00ae1ad4135d3bfbfced82342595cf", size = 25164324, upload-time = "2026-04-09T12:08:59.56Z" }, + { url = "https://files.pythonhosted.org/packages/27/e0/bbd4ba7c2e5067bbba617d87d306ec146889edaeeaa2081d3e122178ca08/uv-0.11.6-py3-none-win32.whl", hash = "sha256:6e8344f38fa29f85dcfd3e62dc35a700d2448f8e90381077ef393438dcd5012e", size = 22865693, upload-time = "2026-04-09T12:09:21.415Z" }, + { url = "https://files.pythonhosted.org/packages/a5/33/1983ce113c538a856f2d620d16e39691962ecceef091a84086c5785e32e5/uv-0.11.6-py3-none-win_amd64.whl", hash = "sha256:a28bea69c1186303d1200f155c7a28c449f8a4431e458fcf89360cc7ef546e40", size = 25371258, upload-time = "2026-04-09T12:09:40.52Z" }, + { url = "https://files.pythonhosted.org/packages/35/01/be0873f44b9c9bc250fcbf263367fcfc1f59feab996355bcb6b52fff080d/uv-0.11.6-py3-none-win_arm64.whl", hash = "sha256:a78f6d64b9950e24061bc7ec7f15ff8089ad7f5a976e7b65fcadce58fe02f613", size = 23869585, upload-time = "2026-04-09T12:09:29.425Z" }, ] [[package]] name = "virtualenv" -version = "21.2.0" +version = "21.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, @@ -2117,9 +2117,9 @@ dependencies = [ { name = "python-discovery" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/92/58199fe10049f9703c2666e809c4f686c54ef0a68b0f6afccf518c0b1eb9/virtualenv-21.2.0.tar.gz", hash = "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098", size = 5840618, upload-time = "2026-03-09T17:24:38.013Z" } +sdist = { url = "https://files.pythonhosted.org/packages/97/c5/aff062c66b42e2183201a7ace10c6b2e959a9a16525c8e8ca8e59410d27a/virtualenv-21.2.1.tar.gz", hash = "sha256:b66ffe81301766c0d5e2208fc3576652c59d44e7b731fc5f5ed701c9b537fa78", size = 5844770, upload-time = "2026-04-09T18:47:11.482Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/59/7d02447a55b2e55755011a647479041bc92a82e143f96a8195cb33bd0a1c/virtualenv-21.2.0-py3-none-any.whl", hash = "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f", size = 5825084, upload-time = "2026-03-09T17:24:35.378Z" }, + { url = "https://files.pythonhosted.org/packages/20/0e/f083a76cb590e60dff3868779558eefefb8dfb7c9ed020babc7aa014ccbf/virtualenv-21.2.1-py3-none-any.whl", hash = "sha256:bd16b49c53562b28cf1a3ad2f36edb805ad71301dee70ddc449e5c88a9f919a2", size = 5828326, upload-time = "2026-04-09T18:47:09.331Z" }, ] [[package]] diff --git a/devel-common/pyproject.toml b/devel-common/pyproject.toml index a841183a5f98b..22cbf0a13ae4e 100644 --- a/devel-common/pyproject.toml +++ b/devel-common/pyproject.toml @@ -35,7 +35,7 @@ dependencies = [ "kgb>=7.2.0", "requests_mock>=1.11.0", "rich>=13.6.0", - "ruff==0.15.9", + "ruff==0.15.10", "semver>=3.0.2", "typer-slim>=0.15.1", "time-machine[dateutil]>=3.0.0", diff --git a/pyproject.toml b/pyproject.toml index 53971c76fbcc6..fa61502104363 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -543,7 +543,7 @@ apache-airflow = "airflow.__main__:main" "apache-airflow-providers-amazon[s3fs]", ] "uv" = [ - "uv>=0.11.3", + "uv>=0.11.6", ] [project.urls] diff --git a/scripts/ci/prek/check_imports_in_providers.py b/scripts/ci/prek/check_imports_in_providers.py index 9c291a4e50796..39da0dbb9447f 100755 --- a/scripts/ci/prek/check_imports_in_providers.py +++ b/scripts/ci/prek/check_imports_in_providers.py @@ -19,7 +19,7 @@ # requires-python = ">=3.10,<3.11" # dependencies = [ # "rich>=13.6.0", -# "ruff==0.15.9", +# "ruff==0.15.10", # ] # /// from __future__ import annotations diff --git a/scripts/ci/prek/ruff_format.py b/scripts/ci/prek/ruff_format.py index 17f16a94007e9..0d04d41baef99 100755 --- a/scripts/ci/prek/ruff_format.py +++ b/scripts/ci/prek/ruff_format.py @@ -18,7 +18,7 @@ # /// script # requires-python = ">=3.10,<3.11" # dependencies = [ -# "ruff==0.15.9", +# "ruff==0.15.10", # ] # /// diff --git a/scripts/tools/setup_breeze b/scripts/tools/setup_breeze index a7ffca0b3986b..eac0b72f3384f 100755 --- a/scripts/tools/setup_breeze +++ b/scripts/tools/setup_breeze @@ -27,7 +27,7 @@ COLOR_YELLOW=$'\e[33m' COLOR_BLUE=$'\e[34m' COLOR_RESET=$'\e[0m' -UV_VERSION="0.11.3" +UV_VERSION="0.11.6" function manual_instructions() { echo diff --git a/uv.lock b/uv.lock index 3f1d70bd12119..092ffc33ec78e 100644 --- a/uv.lock +++ b/uv.lock @@ -12,7 +12,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-04T19:45:35.830966Z" +exclude-newer = "2026-04-10T12:24:23.8467168Z" exclude-newer-span = "P4D" [manifest] @@ -177,86 +177,86 @@ wheels = [ [[package]] name = "adbc-driver-manager" -version = "1.10.0" +version = "1.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9e/77/b6ffd112a67d133810d0027e9de4408a6e63e0e1c438f5866cc28eb3c213/adbc_driver_manager-1.10.0.tar.gz", hash = "sha256:f04407cf2f99bfde13dea0e136d87219c8a16678d43e322744dbd84cdd8eaac2", size = 208204, upload-time = "2026-01-09T07:13:45.803Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0e/95eae266a8d97f2f222e6db9047dc4c1fab6a3e1d5e6bd9c8efb29881ec4/adbc_driver_manager-1.10.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b82d7ffab5ad4c892e2f3201cc3781db3f87ef0c5ce1938715fb39a5dc6671b0", size = 532926, upload-time = "2026-01-09T07:11:52.672Z" }, - { url = "https://files.pythonhosted.org/packages/bc/7c/c7234fe0e25ccd0fe23d8fa1e3f2682d407f49916e845e15869d262fc648/adbc_driver_manager-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e124ad209bc7112d0c0778fcc2e727c4fdf733188403129a82c10e563e89252b", size = 513090, upload-time = "2026-01-09T07:11:54.807Z" }, - { url = "https://files.pythonhosted.org/packages/8d/81/6fb0075c67d1039e82960ab9d039da00ef3149b872a067d2e83ea9bb9956/adbc_driver_manager-1.10.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0abafd6b7d8ef5ba9c33fa92a1c5c329bfb89a68fb12e88ca62a4e32d822f257", size = 3039894, upload-time = "2026-01-09T07:11:56.892Z" }, - { url = "https://files.pythonhosted.org/packages/8a/43/10e2abe7c600545fcf5b684b04073b36c87ed879a4bbc8fcd4f6f329c302/adbc_driver_manager-1.10.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ceca0800974137d2373cfb3aa4862af4b9361a2e5b94808b52df63c3f34a14eb", size = 3053785, upload-time = "2026-01-09T07:11:59.051Z" }, - { url = "https://files.pythonhosted.org/packages/ee/dd/8f0fe60d49fe0b7bd9eb0b76268d662f95b31a8c623fc7cef40ad9488d0f/adbc_driver_manager-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:23504672daeafabe03d4e07038754910f55f6845ef260f2249d9d8942ab16866", size = 714987, upload-time = "2026-01-09T07:12:00.771Z" }, - { url = "https://files.pythonhosted.org/packages/bd/23/eaea050e76a1f65749be243a68514d67e13ab896c47cbf9e652da0ba9c10/adbc_driver_manager-1.10.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:715a33d750af09e1c03fde1783490c816e08a786f151ac79269659da1d2cc4e0", size = 533268, upload-time = "2026-01-09T07:12:02.401Z" }, - { url = "https://files.pythonhosted.org/packages/4b/37/b81d64da4b1a032df0798bbf8c2e3abf875f9dd319598308d2efebe06523/adbc_driver_manager-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd40c9b20be54c55b3ce64cabd5f35f29a61886574d990a1d5b5bdd7f81a7b6", size = 513190, upload-time = "2026-01-09T07:12:04.025Z" }, - { url = "https://files.pythonhosted.org/packages/2b/2a/a03cd7d4eb81c478566a38e6a657b83171e61e84f6aa0c0f9b49ae9d498c/adbc_driver_manager-1.10.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:595ab4a8ec2ddb338c70f3c31481a41830ad9e2d8c1a1884184023303098bc92", size = 3111408, upload-time = "2026-01-09T07:12:06.421Z" }, - { url = "https://files.pythonhosted.org/packages/97/67/b9309e5351d4ff02720719c6ca01716ded33075fa486157db409bc5f47be/adbc_driver_manager-1.10.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:92fdf3247aef506583e79b3b583c1bf93f28c70e771281a41843aba63c61f732", size = 3124914, upload-time = "2026-01-09T07:12:08.274Z" }, - { url = "https://files.pythonhosted.org/packages/41/1d/228041cc7ee30e51556d991d5f30981bfbf0c2d2a91c83f34ace2a2a9d2c/adbc_driver_manager-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:7c5becb5a81fae563a10d82b570c4e1c7a8994c5b110ddaaae6afa9fd52a17b6", size = 716182, upload-time = "2026-01-09T07:12:09.766Z" }, - { url = "https://files.pythonhosted.org/packages/3f/54/deedd6a3fd222ed80ee3441371fdfbd315014a090fe7faf068b1463af7ec/adbc_driver_manager-1.10.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:0f8133130271aff2744a5f706bdb7ec91aab14c19d6db45edd9ccd70e08d778b", size = 532164, upload-time = "2026-01-09T07:12:11.698Z" }, - { url = "https://files.pythonhosted.org/packages/d7/05/0d65aa46491924beff32507aa39956eea68522095b2d67af0ad0461730df/adbc_driver_manager-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a8862ed1825df0bbaf9ab4353addd06e1dc4d53f708fb1f4be1fb86e1d91d3f4", size = 509565, upload-time = "2026-01-09T07:12:13.756Z" }, - { url = "https://files.pythonhosted.org/packages/ec/a1/60cf47f45d09db6d2d0a83fb58307cccf0d6e3f63f007ee5f5b1ef893471/adbc_driver_manager-1.10.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24fca9fd6435ad4cfa1f3e125add6b964bb8be2102b518cf2e096e317cbc66bd", size = 3100269, upload-time = "2026-01-09T07:12:16.035Z" }, - { url = "https://files.pythonhosted.org/packages/93/32/6ca400dc7aaf885d823b37884e40832ccf970df043f5d2817f5eb651f3bc/adbc_driver_manager-1.10.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b112890d3c214380857852eaac40d09e66bd77ce3b75406094f2e48452e57bbd", size = 3130371, upload-time = "2026-01-09T07:12:18.295Z" }, - { url = "https://files.pythonhosted.org/packages/92/0f/629132ae0f317755d22138df0c23ce448c98f2848bdf06e846d72ea0e10e/adbc_driver_manager-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:189d78787d4d77a25f946b9b96139320d53e24ecb43f39a7fb21873c5f9ce874", size = 706573, upload-time = "2026-01-09T07:12:20.003Z" }, - { url = "https://files.pythonhosted.org/packages/ab/da/121d46b2ddf87f7589ca52ca92585b12618ab8493d9980546e42976b1225/adbc_driver_manager-1.10.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:dfba1775474e2ecf8af7486fccd6471811f2e5d02c2dc25c0e3e955a7e9a0e15", size = 529587, upload-time = "2026-01-09T07:12:21.546Z" }, - { url = "https://files.pythonhosted.org/packages/d8/9c/6f9929b53cd578bef06b8d000e0ab829b982bcf5b22a6c99acfbad2aab34/adbc_driver_manager-1.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:94cc8b279c90c66f60a499996651340c17eb40d2fd7ad22e1fe73969ab4db1ee", size = 507669, upload-time = "2026-01-09T07:12:22.88Z" }, - { url = "https://files.pythonhosted.org/packages/52/7b/2c076500e60cac3c2761eeecc82afed42af22d3a65cf3cd8d8034ffd75ad/adbc_driver_manager-1.10.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ae24386989dfa055a09c800d13d5278d5d0399aee2548f071f414e6b8af63fc8", size = 3093831, upload-time = "2026-01-09T07:12:25.15Z" }, - { url = "https://files.pythonhosted.org/packages/ac/7d/3e131221995aef7edfd4dd0b09f14b7e51772d28eb362a0e6c3b8301a22a/adbc_driver_manager-1.10.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:97e06da4235dabbd29244c8bd83f769c8995c25abed5d0c2ee2d95ec76d48b8a", size = 3116517, upload-time = "2026-01-09T07:12:26.902Z" }, - { url = "https://files.pythonhosted.org/packages/97/c2/2ed6c856dd56bbc0a45aaab67f6b1f0a846296f20d5ad625a3c5e7084e4f/adbc_driver_manager-1.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:564a95617bda8907a0ad0a8bc8fea0c2cf951cea747c0d750a4b1740c828b1ef", size = 705122, upload-time = "2026-01-09T07:12:35.999Z" }, - { url = "https://files.pythonhosted.org/packages/36/f5/0e6518feac552081f523dbd886670ebb8210b065bdf97ea1e6af7113f1b5/adbc_driver_manager-1.10.0-cp313-cp313t-macosx_10_15_x86_64.whl", hash = "sha256:fcb5fc9dbf737341eaa28ca2c529c8432dc24aa282cad5a68fc31e5ddd9373fe", size = 546640, upload-time = "2026-01-09T07:12:28.115Z" }, - { url = "https://files.pythonhosted.org/packages/ed/40/e79cce0101eaf482519d39d69811983f084aeb4f2c1d76f9e98301f41f39/adbc_driver_manager-1.10.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fd42acb06a5bb5683b583ebad320f31f9e403f5395e6272e44aab0e379349aeb", size = 526724, upload-time = "2026-01-09T07:12:29.637Z" }, - { url = "https://files.pythonhosted.org/packages/fc/b6/5149308e6a5f38f4995ee4d0d809ed57f7d2c86eb0c358eff3445cf64fca/adbc_driver_manager-1.10.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e05838151ce926f38b2cfe016a2007af9e20148fb7bfa9025524a319f1f0aca", size = 3149413, upload-time = "2026-01-09T07:12:31.814Z" }, - { url = "https://files.pythonhosted.org/packages/74/92/ab9b0f3e90b9140f48dc812b81be3ec54191908281f78c2142094098633e/adbc_driver_manager-1.10.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:71d78d7dec6b0a69023408931c13c326f3226d6977526c605afde417f883e0ed", size = 3137409, upload-time = "2026-01-09T07:12:33.845Z" }, - { url = "https://files.pythonhosted.org/packages/5d/1a/3d3e1da53e7a06fdbe9d3a4baf3fb603a8c44d38b7898c7cf2fdd39f5b0b/adbc_driver_manager-1.10.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7ae144f60c1167c049af3fe7ee9231502b49eb6b7eed3c0f441e001cef841c8c", size = 530253, upload-time = "2026-01-09T07:12:37.73Z" }, - { url = "https://files.pythonhosted.org/packages/16/07/67239506bfe9e52904e97f4908911393a751430bce123ccd35e947564f08/adbc_driver_manager-1.10.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e0ef746fe4579238f690bd5907c631f7c2e79a6e681c79871bf30f4552de0203", size = 510023, upload-time = "2026-01-09T07:12:40.172Z" }, - { url = "https://files.pythonhosted.org/packages/4e/c6/2a480611bc4959fc8227f941a76a2deb3c43900a1e94588fde04bdf43ca2/adbc_driver_manager-1.10.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8404b88bbce61c0133fa1cd3fa292cef631d36811028d9fd297c1abc1c6f357f", size = 3084610, upload-time = "2026-01-09T07:12:42.563Z" }, - { url = "https://files.pythonhosted.org/packages/94/83/dd3adedf868d5a1a35268f3fa9a4c497083e3464d1919b2486eda60561e5/adbc_driver_manager-1.10.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:13123311a6ef468a211a4c8b48bbb60bbbf56283ad56d403bdffb2b087d70e0c", size = 3099721, upload-time = "2026-01-09T07:12:44.824Z" }, - { url = "https://files.pythonhosted.org/packages/ef/1c/787c51fac725e5763e79ce4e22a4b067a8ad97330d915501a89c7e5bfded/adbc_driver_manager-1.10.0-cp314-cp314-win_amd64.whl", hash = "sha256:0ccb5a1e387ed68ac044b7de674185e2f14cffe636294a453e55f22b70bdc709", size = 723075, upload-time = "2026-01-09T07:12:55.237Z" }, - { url = "https://files.pythonhosted.org/packages/4c/56/b103f90a2cedc61dc17065dfcfc6d3f4ab0ebac4c6ad739334be03daaf89/adbc_driver_manager-1.10.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:fb2d02dfdeb2f8c63f168ca04c48395545a56b91b70027b42913dfa48401bcca", size = 547043, upload-time = "2026-01-09T07:12:46.199Z" }, - { url = "https://files.pythonhosted.org/packages/4e/58/ae2ac9dee3fae5c4fe8a04513c8386257aa3e6e332a1e2697f4f11525b01/adbc_driver_manager-1.10.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d1af42749bb377341e2d4ae5f2d7884e61607f69dd0ba555251917d7e570af6a", size = 527444, upload-time = "2026-01-09T07:12:47.895Z" }, - { url = "https://files.pythonhosted.org/packages/3c/25/5d44c86e150664a6a2d1cd9ad1f79e80ad7953783342c5ac81b70d9d1513/adbc_driver_manager-1.10.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e2119add50c528601a1089fe6da63d7d3e41c611db85ced053a70fc1b9b100d", size = 3149149, upload-time = "2026-01-09T07:12:49.923Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ec/e835243c6590397f7c8e4041effeec7e5929f54aa28456364c1fb10e3c11/adbc_driver_manager-1.10.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8d26bc156f0b7d8429572e7ea52830f73049de1626ae44778a915f5a88fd591b", size = 3139215, upload-time = "2026-01-09T07:12:52.046Z" }, - { url = "https://files.pythonhosted.org/packages/8c/32/5925fbaa8368ca943e6776c9d08b5b9e5e093069f7c84b74c690bfbde734/adbc_driver_manager-1.10.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c9233443ad140ba12ddc719a4e8dab485e6bbdc9ebbd3babbc88d5b50133960c", size = 763620, upload-time = "2026-01-09T07:12:53.315Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/e9/5e/50aab18cb501e42d3aca3cd2cc26c6637094fcaf5b6576e350c444188f1f/adbc_driver_manager-1.11.0.tar.gz", hash = "sha256:c64aaabeb5810109ab3d2961008f1b014e9f2d87b3df4416c2a080a40237af50", size = 233059, upload-time = "2026-04-07T00:17:28.263Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/f2/a9f606fd4cc12fa55b3638cbe2d19bdb5d3b4b77fd2df95ed9929177b4c9/adbc_driver_manager-1.11.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:1c257ac94ff890ded228f94a241a393c4edb38657e822003ce0c71c5a85fc944", size = 612120, upload-time = "2026-04-07T00:15:23.539Z" }, + { url = "https://files.pythonhosted.org/packages/c6/c4/59a3680112d0403a27d4104330a03608dafdb125a69690084b3ee2747726/adbc_driver_manager-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b01effe3a2b23e0c6354e47642f792c89858671813e2b516f4c6b2cc75c9cf5", size = 589349, upload-time = "2026-04-07T00:15:26.684Z" }, + { url = "https://files.pythonhosted.org/packages/c0/bd/0559f9ea4c7ca6027e762d4527aacec11410cad1fdd336528d6365a41eef/adbc_driver_manager-1.11.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72dd3d4c591c7783911055aaee62bb518d8a4b2e726d2424dc051d3976f92dd6", size = 4608535, upload-time = "2026-04-07T00:15:29.649Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e1f5a84893ea0ac12c9b78d5d2fe4da4cb7c659706d304070ba9f7d84986/adbc_driver_manager-1.11.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4b70c4e94edeaa2f04e58dc70e1a0d8570b400a366ab0b1e7c1b607216ffe6cb", size = 4679329, upload-time = "2026-04-07T00:15:32.179Z" }, + { url = "https://files.pythonhosted.org/packages/de/15/88cf7f41feb68ac363488fd90a0e81b5d2e33e5fa190d3b9b554baa39ceb/adbc_driver_manager-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:7b40f8333a978760ec47037a03e4bd5e4d47f564ff78be9112b204c2acf88ddd", size = 780919, upload-time = "2026-04-07T00:15:33.993Z" }, + { url = "https://files.pythonhosted.org/packages/9b/71/799196cd1daeb485391b4362f024f0e3fa72d8f37f8d7401b1add12ad956/adbc_driver_manager-1.11.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:3eb5d6dd94d14e9f1abd340b0bc04bde6d16d692f598ada5ceef3186c6a90eaf", size = 612276, upload-time = "2026-04-07T00:15:36.033Z" }, + { url = "https://files.pythonhosted.org/packages/55/0c/576105c33c14118330331554ef843c3b0aab8f0f399f074e58c67a108b55/adbc_driver_manager-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07469c219d79645a6b2f3df0b8c176c0abbaf7d2b20725e15531735972f65db1", size = 589471, upload-time = "2026-04-07T00:15:37.591Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/70349ab02699d48629438c129ee58fc74574766b6c4f09d61e4182d58cba/adbc_driver_manager-1.11.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8863a841ac362c26217e9ed69d1d1eb7add881c452382676c3fd4f19b562186c", size = 4676297, upload-time = "2026-04-07T00:15:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/8f/ca/adb9a7a11996d6c06d0c9832d2df61fec7e637b000ebae3c9fdf46662f97/adbc_driver_manager-1.11.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4641430ca41c1b570083aeb7771766fa51d963ac5a4bb11b208b51b96ed7f58", size = 4749828, upload-time = "2026-04-07T00:15:41.757Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ea/f6707768929d21d0464879803417bc450be0986256bc76669cabe608f8da/adbc_driver_manager-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:c6efa733bf219582bf0f9402f7a8034b113555b1edf178e4743caa69a736ddc5", size = 781821, upload-time = "2026-04-07T00:15:43.3Z" }, + { url = "https://files.pythonhosted.org/packages/55/42/424980ae511ccb779ab31f80890e29294bf8f1ace23b2a4a37baa3a11aca/adbc_driver_manager-1.11.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:08d3008cd6fee3d27b6265864b134902baacf00cd441dc750fb738615290004f", size = 610890, upload-time = "2026-04-07T00:15:45.138Z" }, + { url = "https://files.pythonhosted.org/packages/f1/66/5522e19e7f8c653a9031806175539479a4854d52a92acf449f703dc424cf/adbc_driver_manager-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:08f0a6e8030676b7fda5ffe095c33a819a15114541089b8d0fa8281d2dee2079", size = 585005, upload-time = "2026-04-07T00:15:47.094Z" }, + { url = "https://files.pythonhosted.org/packages/cc/78/106987c8abe88feeb6c0e6e837549a77aebfd0ecb7dfbdcad953d7e8f66e/adbc_driver_manager-1.11.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb33beabe3a697a54ffcc9593b94705688f33b64741a17f7bdd37690f85a0ecf", size = 4687350, upload-time = "2026-04-07T00:15:49.743Z" }, + { url = "https://files.pythonhosted.org/packages/eb/bf/c203675aeaf204cbeb21b6da8d9d1a28ba78c180aa6fa7bc31a7386a7ee6/adbc_driver_manager-1.11.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dba5306b90932e8af5e4a71756eec2f717f5fe283b1ad7cc7fb094fe4ef3f0f9", size = 4769988, upload-time = "2026-04-07T00:15:51.939Z" }, + { url = "https://files.pythonhosted.org/packages/7d/84/b31be789afede9e7bdaffab74effe7aef5d2ac3068ef2694f36b5b7dd334/adbc_driver_manager-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5e9962e6e737e1c028cacb38c08141a8730f5c90cd397537413012ece901cc5", size = 772321, upload-time = "2026-04-07T00:15:54.365Z" }, + { url = "https://files.pythonhosted.org/packages/57/a4/a5e1a49b88bc248a6489fd5221369aca0df06761b858af926e702f36abb7/adbc_driver_manager-1.11.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:300b07f4c1113b113e18dddcb9d96dd8b84f09fa35f8e4e3e8a2f112f291142c", size = 608355, upload-time = "2026-04-07T00:15:55.907Z" }, + { url = "https://files.pythonhosted.org/packages/30/38/21bf51455d170199981462ecb8765153d1340dcff3f696910f44fe0535e5/adbc_driver_manager-1.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f577be7c4730a43bae08f88105317d7e1d519d02a94aaa98da694358084a4735", size = 582871, upload-time = "2026-04-07T00:15:57.605Z" }, + { url = "https://files.pythonhosted.org/packages/4c/aa/40bdf0f612bd88eb2fdad70e1cd3f88b8619a0ec66c312acd61170f61837/adbc_driver_manager-1.11.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c980f81730752cdb98881357c238e87110e1810e4a69c7627c2211bd576b6230", size = 4670178, upload-time = "2026-04-07T00:15:59.516Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/8dcb40ed4f4ce3ccd1bda988e8d8bd37984ba223a339433d336502966697/adbc_driver_manager-1.11.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cbc93830500a2f0db7b32501a4f88678fac14b9a9921d94d919439a5b65099e6", size = 4746822, upload-time = "2026-04-07T00:16:02.437Z" }, + { url = "https://files.pythonhosted.org/packages/07/b9/df5ac9db38ce4b683d19d94fb8a296d48306b1712d93f38ef25d7c36c253/adbc_driver_manager-1.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c27cff12cdf074d9052bf8c4775ed1904053189a70497fa7b5746f0dbe326d8", size = 771492, upload-time = "2026-04-07T00:16:15.651Z" }, + { url = "https://files.pythonhosted.org/packages/8f/af/4e050e6dbb0dfed99d631351bc47b6520d073529ac619bbecb5ad4adf015/adbc_driver_manager-1.11.0-cp313-cp313t-macosx_10_15_x86_64.whl", hash = "sha256:d8fdeb10ea464dce88feffe23f35cc37a44ac6bad4e90e793416a3c60afb354f", size = 625664, upload-time = "2026-04-07T00:16:04.311Z" }, + { url = "https://files.pythonhosted.org/packages/47/f8/a009ecc7f889feb9cf3546bfb4e998ac88399eb06e2c75dd7d2972384bf7/adbc_driver_manager-1.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cc565ed5d9f8c7974bbaff60c30c8330dae5a903592618a303291db4227b3d54", size = 603642, upload-time = "2026-04-07T00:16:06.758Z" }, + { url = "https://files.pythonhosted.org/packages/53/c4/15af4bf5a3bfb76eead95a8cd5e1117098e64d046c3bb6eea0f502266523/adbc_driver_manager-1.11.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9523ca4e8943aa7b43958762bc9d1cb0b5355cd84855359a91c54a4bae9a75df", size = 4733746, upload-time = "2026-04-07T00:16:09.5Z" }, + { url = "https://files.pythonhosted.org/packages/40/72/dd76e63f8e787f2c313354e51152750f802061e21b4511e1bd9db467eca1/adbc_driver_manager-1.11.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54dc142fc8065e13c6347fb3f2acb48430e3cab6863f27276a2b53594cc055b5", size = 4773869, upload-time = "2026-04-07T00:16:13.438Z" }, + { url = "https://files.pythonhosted.org/packages/73/98/7a94f2aa7dbf470d4933a059bd66ee830fcea64422f95513dc9ab5fab910/adbc_driver_manager-1.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f6fcd6fe4f82f8f2fc83948ed2b0b549d0831253d449f5734603cc03850e4f47", size = 609370, upload-time = "2026-04-07T00:16:18.336Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/bd62e3094a07bb5a3eebd4e185953df02e1b3582091872457899a1a12d74/adbc_driver_manager-1.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4b4293fc88d0683b6ea9fe1b7d7498c5ae9b4f53a93369c760cfa753a22039c0", size = 585560, upload-time = "2026-04-07T00:16:20.566Z" }, + { url = "https://files.pythonhosted.org/packages/19/6c/4aabac7ed4d5944f544b7cf7881d50fe4b34eac908605291b633a53be875/adbc_driver_manager-1.11.0-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a2d6d1971ce104e41e3969afee8d5782ebcb06bf496606aa4eed2005fbead43", size = 4668783, upload-time = "2026-04-07T00:16:23.798Z" }, + { url = "https://files.pythonhosted.org/packages/47/67/3bf52e5ec427b0b88cbaa8e059b6c79851db0742db712a5f58a0e3f666be/adbc_driver_manager-1.11.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24ef0e33bab3b0480e85d954f88664b578ea045efdc644681c5a487982818e5f", size = 4735326, upload-time = "2026-04-07T00:16:27.348Z" }, + { url = "https://files.pythonhosted.org/packages/33/64/5247eb91f9902e7111bf7a75c1af4da7a1818e31a26a754d97d0f0df7dcb/adbc_driver_manager-1.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:830efd3f212a6360ad66c09fd95171a26a1006a51c893f72238dfb50e0f35e13", size = 789628, upload-time = "2026-04-07T00:16:42.101Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/9186febf1a550f7d8935aa9842bffbe3ff9848de2bdef066acd6a86f5bf8/adbc_driver_manager-1.11.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b5e97d4cb3f5a798e18c802dd1f3d1bf7b77d763cdc707ac295907bf223d1ae8", size = 626086, upload-time = "2026-04-07T00:16:29.184Z" }, + { url = "https://files.pythonhosted.org/packages/11/53/6e988bfbf8292cbf59b663e1e3ba6efe94f703c74061f8c0d2b182963899/adbc_driver_manager-1.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2e4e155cae12667aa383750d879e177ada3ab0c351f8306d96e33fbe6949f6f4", size = 604608, upload-time = "2026-04-07T00:16:31.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/d6/e9cb77e9840b12382da49cc22a93c224d9607969b76b0062bf6114119f61/adbc_driver_manager-1.11.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfb736661f95eb8fc185a4b9951b2e61734633c7448e8d3d937e93ef1d9e5c08", size = 4738703, upload-time = "2026-04-07T00:16:34.416Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/c1b800c313e4e2cb7bec4a5334d4c89329eb021317c9fb3e3794a49e02d0/adbc_driver_manager-1.11.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e87a6f2b70baf21d3c52b280a17e2e8516197a4670b9a080a07dd255f2ab6e9d", size = 4778585, upload-time = "2026-04-07T00:16:37.775Z" }, + { url = "https://files.pythonhosted.org/packages/04/3d/dc32f50d0ad1d748461422c7a6cad2a49b778aa4fdcbebe08e38789d7898/adbc_driver_manager-1.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b853e613c6c8afbe7a3fcea0098c88b935a4d1e1b046813aed1fe7363c7b8fc7", size = 830178, upload-time = "2026-04-07T00:16:40.247Z" }, ] [[package]] name = "adbc-driver-postgresql" -version = "1.10.0" +version = "1.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "adbc-driver-manager", marker = "python_full_version < '3.13'" }, { name = "importlib-resources", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/14/15/bb1d0458fb79bec75d6392d695f3dd58e3100789e6605a69e2b0e30ba1b5/adbc_driver_postgresql-1.10.0.tar.gz", hash = "sha256:4687d41180a31f6e6081dfb85cbe4b1611498d6b5c462f34ed3b7e68d20ed90d", size = 20747, upload-time = "2026-01-09T07:13:47.118Z" } +sdist = { url = "https://files.pythonhosted.org/packages/68/10/2962c25035887cd03af3b348eac3302493936f45048c220021a802d07f12/adbc_driver_postgresql-1.11.0.tar.gz", hash = "sha256:f5688b8648ac7a86d8b89340231bb3686ac5df56ee95d1ca0b875dad5d52b48a", size = 32328, upload-time = "2026-04-07T00:17:29.232Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/f8/7105475d6749f709223e363dca59cf751593cbdd815acc5939e7236367f4/adbc_driver_postgresql-1.10.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:e59af997b2be409b27a1feee89f702cd7f528c2c4ae0696b41e25f46fda2db27", size = 2991224, upload-time = "2026-01-09T07:12:57.311Z" }, - { url = "https://files.pythonhosted.org/packages/44/72/5ce2a53b6d4d2bb533d3250d6f3a32e6171a82f74c712583c04bf9dabf15/adbc_driver_postgresql-1.10.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4fa0f647498687d937646be234b5eeb464ddff503e0233351a127703fd8783ec", size = 3271094, upload-time = "2026-01-09T07:13:00.273Z" }, - { url = "https://files.pythonhosted.org/packages/3e/87/a997e82262f58ccc5340898f623dec8b8b80d40db48ab7b7575efd92bb6e/adbc_driver_postgresql-1.10.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e9a0f0097b33574eff87fccbf17713b8c5c0d9f6fed9c081e074989b8b4ad5cc", size = 3757195, upload-time = "2026-01-09T07:13:02.267Z" }, - { url = "https://files.pythonhosted.org/packages/76/f7/2ca5bd4d8d4edcd8721adeba20690806cf6186d9a3de217b2c5f44530c3c/adbc_driver_postgresql-1.10.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a2efec61f5ba966e503081b7f058516745e95e0d965bfd9ecfcae2f6d2d4a178", size = 3431159, upload-time = "2026-01-09T07:13:04.281Z" }, - { url = "https://files.pythonhosted.org/packages/ce/a8/17129f60d0de09947f12dbeb25a107bef7cc265ea4f5fd5d88ed02ba58ce/adbc_driver_postgresql-1.10.0-py3-none-win_amd64.whl", hash = "sha256:81c285c08cf28faae36791f5c790a16b1d87cdee9037af874e4dcf747c21a8e2", size = 3020799, upload-time = "2026-01-09T07:13:06.104Z" }, + { url = "https://files.pythonhosted.org/packages/79/c7/c90e2faea8f2eac9bbdf89ab3c6bad78e4d0361043cc59b63a37da143a55/adbc_driver_postgresql-1.11.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:c54e3119998c845d895ff548c2181c73313e9a52616c61a8cd918d8b4d5279ea", size = 3046985, upload-time = "2026-04-07T00:16:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/93/63/eb2ea42f7451a898e11847a0b949baa06cbe212a4de09e4c62e1bf9af448/adbc_driver_postgresql-1.11.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9678d10d7597f775efd59f74cadd0c63fc40671ee52b65e289019ae8b5a2adf0", size = 3337180, upload-time = "2026-04-07T00:16:47.015Z" }, + { url = "https://files.pythonhosted.org/packages/f0/32/63e4b41f0e4cb36a61ed62edd151ea71c4cc555b2dd554a068812c8dae52/adbc_driver_postgresql-1.11.0-py3-none-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03cca73acc3840c9751305cef86aa5a9971fe2374a7aabaf1704b3582b351518", size = 3800773, upload-time = "2026-04-07T00:16:48.977Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f8/93c681d2ccd5b0e70db58998b0f61a7bf52ccf6b9e199d5055c49ef37959/adbc_driver_postgresql-1.11.0-py3-none-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5904ed3da009fe1361ddf6d5c1a61c8963a6d1dfeda0e96bd4445e028f37216", size = 3489464, upload-time = "2026-04-07T00:16:51.305Z" }, + { url = "https://files.pythonhosted.org/packages/a7/47/dd2322a40537ee9e22aa9937c70614ca29e9259d1b8b17441b92fbb49d5c/adbc_driver_postgresql-1.11.0-py3-none-win_amd64.whl", hash = "sha256:95c13b3203615b816a258db91c375785750cb82395b985f16c0dc6af88b932e3", size = 3067900, upload-time = "2026-04-07T00:16:53.08Z" }, ] [[package]] name = "adbc-driver-sqlite" -version = "1.10.0" +version = "1.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "adbc-driver-manager", marker = "python_full_version < '3.13'" }, { name = "importlib-resources", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/72/34/f4924d98a340835988f135303c7e562f7a388308a3fbb949f357bcb94b04/adbc_driver_sqlite-1.10.0.tar.gz", hash = "sha256:064ed5f1372578d2063cd920514cd2597c6a6db3b0163c2116e373faeedffec6", size = 18298, upload-time = "2026-01-09T07:13:49.001Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/dd/8a5f4908aa4bdec64dcd672734fa314d692517458ce169591639d0123fe1/adbc_driver_sqlite-1.11.0.tar.gz", hash = "sha256:a4c6b4962610f7cd67cd754c42dd74e18a2c11fabeec9488c5501d73ae62dc62", size = 28885, upload-time = "2026-04-07T00:17:31.325Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d0/e7b0632d3098a209a4700cf75e69dcecfea8e4de369b2b07431a10195234/adbc_driver_sqlite-1.10.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:ebef54331c006a42adbe0510ae0f9b3a37fd5e1819214e875fe36a72ce7bf883", size = 1051483, upload-time = "2026-01-09T07:13:34.252Z" }, - { url = "https://files.pythonhosted.org/packages/c8/a5/968f2031dd97b7907ccfd90b28de3629ce7f31cfd8041e1f509cb1e30a28/adbc_driver_sqlite-1.10.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1de3fb50a3a4bcad1b097d3805b41681226a5c35ccc625637a8dfb87fc4123c1", size = 1030203, upload-time = "2026-01-09T07:13:36.149Z" }, - { url = "https://files.pythonhosted.org/packages/c0/f0/71d53fc347b3a598c3f1f562aad7be1e4548c55c06ebda7c6e1ae04f7695/adbc_driver_sqlite-1.10.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1f8fa45ca274502e145a0fd43af5253f508fe2c17e82857a898392abeb577588", size = 1139328, upload-time = "2026-01-09T07:13:37.837Z" }, - { url = "https://files.pythonhosted.org/packages/bc/88/7f900b29099764307d1c9816c30b05d0076df120a7ca57c759b3a7a5e82b/adbc_driver_sqlite-1.10.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:435cbf57c42e6c57762f6998041a8129ddf7a3f0b407712cbb62d46e0729a450", size = 1158802, upload-time = "2026-01-09T07:13:40.612Z" }, - { url = "https://files.pythonhosted.org/packages/91/46/bea7cfb4b0779ff67a40833c652b15e702c9e5d1232aff96e577211eb60d/adbc_driver_sqlite-1.10.0-py3-none-win_amd64.whl", hash = "sha256:c6adfb5a934cd1573076fdd71b03492140c8563b6a0d9d2d46c7e718e736b3e0", size = 960435, upload-time = "2026-01-09T07:13:42.333Z" }, + { url = "https://files.pythonhosted.org/packages/fe/5b/f03b0b654abb679066da022d064b083752d3df6b4e0c9e8f451a1aa82f75/adbc_driver_sqlite-1.11.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:d227ab10a56b0b5f106d9f85f3f8bce8b75c2b34a28ad962b71e8a3a0b6dc0ed", size = 1414587, upload-time = "2026-04-07T00:17:16.744Z" }, + { url = "https://files.pythonhosted.org/packages/bd/f4/26da6de1ff772bfc95c2257a0d9e7b7d1d3525e5170f6d67d715138e6690/adbc_driver_sqlite-1.11.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:98fd35e14c85e44eeffae1ef9a56466169719ad7bd15e314c2ff88c342e50d9d", size = 1362696, upload-time = "2026-04-07T00:17:18.821Z" }, + { url = "https://files.pythonhosted.org/packages/52/aa/ab2373cdac52ebcf42fd6cc80f9cdb7b98416ff15f6cd340aa4cceaf970e/adbc_driver_sqlite-1.11.0-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:9c28401c31d775d5506ed1188b73de9f7ed1a292927157f2171c7dca67f6cb9e", size = 1501255, upload-time = "2026-04-07T00:17:20.862Z" }, + { url = "https://files.pythonhosted.org/packages/09/05/a2dec7d6e4300f3c81b75d727007a146977f018765c8b0607ed49b28e0dd/adbc_driver_sqlite-1.11.0-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:2bcab0cfe9380c1691cf995430f8b0b56bf8b9875d8fd9d69a5aecf2b72159e6", size = 1550696, upload-time = "2026-04-07T00:17:22.833Z" }, + { url = "https://files.pythonhosted.org/packages/0a/35/d189ce413bdeda6dae71eaa1effd96ec0a2f82ef0a1693e20a36a7082504/adbc_driver_sqlite-1.11.0-py3-none-win_amd64.whl", hash = "sha256:e41246c5bf929bb5d768227606eb10add420171134ae6ba7928136376f5842fd", size = 1378169, upload-time = "2026-04-07T00:17:24.783Z" }, ] [[package]] name = "adlfs" -version = "2026.2.0" +version = "2026.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "azure-core" }, @@ -265,9 +265,9 @@ dependencies = [ { name = "azure-storage-blob", extra = ["aio"] }, { name = "fsspec" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d9/39/5d7bde68327d9f6b9d73353664f4b247e194130b0ebcd4ca2d0e101fbd57/adlfs-2026.2.0.tar.gz", hash = "sha256:7661330ef67d99e55d15750cadef5a604a82e1513787039be830efc5b53ba533", size = 54018, upload-time = "2026-02-09T18:46:49.876Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/51/c766cea8a00f84f224aa672ea0f20e4f24091eb90ce56104accd003c7405/adlfs-2026.4.0.tar.gz", hash = "sha256:84c6f0fc28403629ef6d6d90f0d1a35a3302179f65ce4686c939a42ad0496d8d", size = 54730, upload-time = "2026-04-09T17:35:54.837Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/95/123783625038056187f5bc9036d5249e52751e5dcc685e3f201a0a5d40ba/adlfs-2026.2.0-py3-none-any.whl", hash = "sha256:995fc9acc2ff8d794af15b36c604ab8dc02fe2301a973ce2df0f5b246d13e439", size = 45681, upload-time = "2026-02-09T18:46:48.362Z" }, + { url = "https://files.pythonhosted.org/packages/71/45/6e6061498d2cd7fecfcaa6e17c2057bfcac3578c656b9646c343c7021c6e/adlfs-2026.4.0-py3-none-any.whl", hash = "sha256:a12a420583ae2d86d1b02902db147b7da5cf3e6eef40ee53024756a781d5d84f", size = 46249, upload-time = "2026-04-09T17:35:53.891Z" }, ] [[package]] @@ -281,7 +281,7 @@ wheels = [ [[package]] name = "aiobotocore" -version = "3.3.0" +version = "3.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -293,9 +293,9 @@ dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/9f/a0568deaf008f4a7e3d57a7f80f1537df894df0e49bd4a790bb22f9a2d8e/aiobotocore-3.3.0.tar.gz", hash = "sha256:9abc21d91edd6c9c2e4a07e11bdfcbb159f0b9116ab2a0a5a349113533a18fb2", size = 122940, upload-time = "2026-03-18T09:58:49.077Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/50/a48ed11b15f926ce3dbb33e7fb0f25af17dbb99bcb7ae3b30c763723eca7/aiobotocore-3.4.0.tar.gz", hash = "sha256:a918b5cb903f81feba7e26835aed4b5e6bb2d0149d7f42bb2dd7d8089e3d9000", size = 122360, upload-time = "2026-04-07T06:12:24.884Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/16/54/a295bd8d7ac900c339b2c7024ed0ff9538afb60e92eb0979b8bb49deb20e/aiobotocore-3.3.0-py3-none-any.whl", hash = "sha256:9125ab2b63740dfe3b66b8d5a90d13aed9587b850aa53225ef214a04a1aa7fdc", size = 87817, upload-time = "2026-03-18T09:58:47.466Z" }, + { url = "https://files.pythonhosted.org/packages/df/d8/ce9386e6d76ea79e61dee15e62aa48cff6be69e89246b0ac4a11857cb02c/aiobotocore-3.4.0-py3-none-any.whl", hash = "sha256:26290eb6830ea92d8a6f5f90b56e9f5cedd6d126074d5db63b195e281d982465", size = 88018, upload-time = "2026-04-07T06:12:22.684Z" }, ] [[package]] @@ -700,7 +700,7 @@ wheels = [ [[package]] name = "anthropic" -version = "0.89.0" +version = "0.93.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -712,9 +712,9 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/af/862e216dd6c5e9bc02fb374eeaaa19017c51b90ddfa5692668a3811947bd/anthropic-0.89.0.tar.gz", hash = "sha256:f3d75b8ccef4b35f3702639519e461eba437d4bcdfabb69378c65a02ab7bda66", size = 596758, upload-time = "2026-04-03T18:57:01.348Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/70/2429d6f7c2516db99fb342c3ad89575ab3e0cd31d3d2f6cba5fdf5e9c65b/anthropic-0.93.0.tar.gz", hash = "sha256:fea8376f7d5cdf99d5e8e85a48fe7a7bd8ab307cdfee4b1e8283a18b1c0ce1b5", size = 654155, upload-time = "2026-04-09T18:13:53.522Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/22/ba/9f973f22abb512d5d17428a76e4ecbc8d49b9dd1b5a1152576d48c24dc1d/anthropic-0.89.0-py3-none-any.whl", hash = "sha256:c6d23854af798f2471ca3bc653cca394d392cc272fe803d3da9d63575b8445f0", size = 478847, upload-time = "2026-04-03T18:56:59.54Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7b/5b2c11902707c49c7a99418eb027ed3eb63876193fee5c80b5c878e3a673/anthropic-0.93.0-py3-none-any.whl", hash = "sha256:2c20b2ce6d305564c66a6cbaedddee8efdd3b9753098bf314093fcf4c662d04c", size = 627482, upload-time = "2026-04-09T18:13:51.606Z" }, ] [[package]] @@ -1481,7 +1481,7 @@ requires-dist = [ { name = "cloudpickle", marker = "extra == 'cloudpickle'", specifier = ">=2.2.1" }, { name = "python-ldap", marker = "extra == 'ldap'", specifier = ">=3.4.4" }, { name = "sentry-sdk", marker = "extra == 'sentry'", specifier = ">=2.30.0" }, - { name = "uv", marker = "extra == 'uv'", specifier = ">=0.11.3" }, + { name = "uv", marker = "extra == 'uv'", specifier = ">=0.11.6" }, ] provides-extras = ["all-core", "async", "graphviz", "gunicorn", "kerberos", "memray", "otel", "statsd", "all-task-sdk", "airbyte", "alibaba", "amazon", "apache-cassandra", "apache-drill", "apache-druid", "apache-flink", "apache-hdfs", "apache-hive", "apache-iceberg", "apache-impala", "apache-kafka", "apache-kylin", "apache-livy", "apache-pig", "apache-pinot", "apache-spark", "apache-tinkerpop", "apprise", "arangodb", "asana", "atlassian-jira", "celery", "cloudant", "cncf-kubernetes", "cohere", "common-ai", "common-compat", "common-io", "common-messaging", "common-sql", "databricks", "datadog", "dbt-cloud", "dingding", "discord", "docker", "edge3", "elasticsearch", "exasol", "fab", "facebook", "ftp", "git", "github", "google", "grpc", "hashicorp", "http", "imap", "influxdb", "informatica", "jdbc", "jenkins", "keycloak", "microsoft-azure", "microsoft-mssql", "microsoft-psrp", "microsoft-winrm", "mongo", "mysql", "neo4j", "odbc", "openai", "openfaas", "openlineage", "opensearch", "opsgenie", "oracle", "pagerduty", "papermill", "pgvector", "pinecone", "postgres", "presto", "qdrant", "redis", "salesforce", "samba", "segment", "sendgrid", "sftp", "singularity", "slack", "smtp", "snowflake", "sqlite", "ssh", "standard", "tableau", "telegram", "teradata", "trino", "vertica", "weaviate", "yandex", "ydb", "zendesk", "all", "aiobotocore", "apache-atlas", "apache-webhdfs", "amazon-aws-auth", "cloudpickle", "github-enterprise", "google-auth", "ldap", "pandas", "polars", "rabbitmq", "sentry", "s3fs", "uv"] @@ -2294,7 +2294,7 @@ requires-dist = [ { name = "rich", specifier = ">=13.6.0" }, { name = "rich-click", marker = "extra == 'devscripts'", specifier = ">=1.9.7" }, { name = "rich-click", marker = "extra == 'docs'", specifier = ">=1.9.7" }, - { name = "ruff", specifier = "==0.15.9" }, + { name = "ruff", specifier = "==0.15.10" }, { name = "semver", specifier = ">=3.0.2" }, { name = "semver", marker = "extra == 'devscripts'", specifier = ">=3.0.2" }, { name = "setuptools", marker = "extra == 'docs'", specifier = "<82.0.0" }, @@ -8438,7 +8438,7 @@ wheels = [ [[package]] name = "aws-sam-translator" -version = "1.108.0" +version = "1.109.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, @@ -8446,9 +8446,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/51/2f/9283feaa243e18f1e28490ae053c1bd1d7c8855d412cb84b37ea4926681e/aws_sam_translator-1.108.0.tar.gz", hash = "sha256:8a21be119caaa64cf85e01b5e0fde804abe117b36fcce934bc1b74f3ccdc2488", size = 362147, upload-time = "2026-03-17T23:58:12.645Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/09/f62aa8d076f6ba85080ec6291e61af345e9be0daf8a4094101555e054ec7/aws_sam_translator-1.109.0.tar.gz", hash = "sha256:0c5e60223ae8434ce0c6bdb9a491d69ba3ec97e15c0d825d3803f7806382d804", size = 369016, upload-time = "2026-04-08T23:34:32.535Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/f9/536c46d176dea4e4dd04daa3f44cb9fed15074ee0917ecf2dc1d6154da80/aws_sam_translator-1.108.0-py3-none-any.whl", hash = "sha256:03130421e641bb57ba7978e7db9e49acb32ecb09a87777dca3c28e44b3ea49db", size = 422108, upload-time = "2026-03-17T23:58:10.92Z" }, + { url = "https://files.pythonhosted.org/packages/89/29/db13205af6bbebdc8dae9dd603ef97ee10a23cd8a3e26d9de728948b2e33/aws_sam_translator-1.109.0-py3-none-any.whl", hash = "sha256:9a6376e7c6d4fee173342b8b557035a8e3ec36e795e175e870411c8e4238873d", size = 432447, upload-time = "2026-04-08T23:34:30.881Z" }, ] [[package]] @@ -9228,30 +9228,30 @@ wheels = [ [[package]] name = "boto3" -version = "1.42.70" +version = "1.42.84" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/7c/d7a533916d1afc9e17f8594203a85799d42f7c5751464fbdb25ead8db9d2/boto3-1.42.70.tar.gz", hash = "sha256:d060b0d83d2832e403671b9a895e73c3b025df8bb5896d89e401b0678705aac4", size = 112808, upload-time = "2026-03-17T19:43:22.445Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/89/2d647bd717da55a8cc68602b197f53a5fa36fb95a2f9e76c4aff11a9cfd1/boto3-1.42.84.tar.gz", hash = "sha256:6a84b3293a5d8b3adf827a54588e7dcffcf0a85410d7dadca615544f97d27579", size = 112816, upload-time = "2026-04-06T19:39:07.585Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/a1/128e3676fb9b4fd965a93554e5e07045975ee6bd6e9fdb536cdffa32e99e/boto3-1.42.70-py3-none-any.whl", hash = "sha256:18a108c4d5df89a200b3949de0d39c0879b100c455e3229ea38275dd392db0f4", size = 140554, upload-time = "2026-03-17T19:43:20.406Z" }, + { url = "https://files.pythonhosted.org/packages/2d/31/cdf4326841613d1d181a77b3038a988800fb3373ca50de1639fba9fa87de/boto3-1.42.84-py3-none-any.whl", hash = "sha256:4d03ad3211832484037337292586f71f48707141288d9ac23049c04204f4ab03", size = 140555, upload-time = "2026-04-06T19:39:06.009Z" }, ] [[package]] name = "botocore" -version = "1.42.70" +version = "1.42.84" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/54/b80e1fcee4f732e0e9314bbb8679be9d5690caa1566c4a4cd14e9724d2dd/botocore-1.42.70.tar.gz", hash = "sha256:9ee17553b7febd1a0c1253b3b62ab5d79607eb6163c8fb943470a8893c31d4fa", size = 14997068, upload-time = "2026-03-17T19:43:10.678Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/b7/1c03423843fb0d1795b686511c00ee63fed1234c2400f469aeedfd42212f/botocore-1.42.84.tar.gz", hash = "sha256:234064604c80d9272a5e9f6b3566d260bcaa053a5e05246db90d7eca1c2cf44b", size = 15148615, upload-time = "2026-04-06T19:38:56.673Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/51/08f32aea872253173f513ba68122f4300966290677c8e59887b4ffd5d957/botocore-1.42.70-py3-none-any.whl", hash = "sha256:54ed9d25f05f810efd22b0dfda0bb9178df3ad8952b2e4359e05156c9321bd3c", size = 14671393, upload-time = "2026-03-17T19:43:06.777Z" }, + { url = "https://files.pythonhosted.org/packages/e3/37/0c0c90361c8a1b9e6c75222ca24ae12996a298c0e18822a72ab229c37207/botocore-1.42.84-py3-none-any.whl", hash = "sha256:15f3fe07dfa6545e46a60c4b049fe2bdf63803c595ae4a4eec90e8f8172764f3", size = 14827061, upload-time = "2026-04-06T19:38:53.613Z" }, ] [[package]] @@ -9730,7 +9730,7 @@ wheels = [ [[package]] name = "cohere" -version = "5.21.1" +version = "6.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastavro" }, @@ -9742,9 +9742,9 @@ dependencies = [ { name = "types-requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d2/75/4c346f6e2322e545f8452692304bd4eca15a2a0209ab9af6a0d1a7810b67/cohere-5.21.1.tar.gz", hash = "sha256:e5ade4423b928b01ff2038980e1b62b2a5bb412c8ab83e30882753b810a5509f", size = 191272, upload-time = "2026-03-26T15:09:27.857Z" } +sdist = { url = "https://files.pythonhosted.org/packages/85/e2/d38ef3a50a0b2bc75868df26ad0590ace76669559bd13c0f0edf412ca4c6/cohere-6.0.0.tar.gz", hash = "sha256:d08319957bc6f61c3c07f129299773868c0c6796786c9bb940ac8dcfcebbb3d5", size = 194128, upload-time = "2026-04-08T22:32:52.005Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/50/5538f02ec6d10fbb84f29c1b18c68ff2a03d7877926a80275efdf8755a9f/cohere-5.21.1-py3-none-any.whl", hash = "sha256:f15592ec60d8cf12f01563db94ec28c388c61269d9617f23c2d6d910e505344e", size = 334262, upload-time = "2026-03-26T15:09:26.284Z" }, + { url = "https://files.pythonhosted.org/packages/f7/47/c0c384af63cd628430ca99391676b3df724407fa44d2bc66df87577d50fc/cohere-6.0.0-py3-none-any.whl", hash = "sha256:08c3dc4e8adc52b781163e5e91be73005f376375dd02f0d8c5efca3df426b366", size = 337923, upload-time = "2026-04-08T22:32:50.317Z" }, ] [[package]] @@ -9975,62 +9975,62 @@ wheels = [ [[package]] name = "cryptography" -version = "46.0.6" +version = "46.0.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a4/ba/04b1bd4218cbc58dc90ce967106d51582371b898690f3ae0402876cc4f34/cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759", size = 750542, upload-time = "2026-03-25T23:34:53.396Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/47/23/9285e15e3bc57325b0a72e592921983a701efc1ee8f91c06c5f0235d86d9/cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8", size = 7176401, upload-time = "2026-03-25T23:33:22.096Z" }, - { url = "https://files.pythonhosted.org/packages/60/f8/e61f8f13950ab6195b31913b42d39f0f9afc7d93f76710f299b5ec286ae6/cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30", size = 4275275, upload-time = "2026-03-25T23:33:23.844Z" }, - { url = "https://files.pythonhosted.org/packages/19/69/732a736d12c2631e140be2348b4ad3d226302df63ef64d30dfdb8db7ad1c/cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a", size = 4425320, upload-time = "2026-03-25T23:33:25.703Z" }, - { url = "https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175", size = 4278082, upload-time = "2026-03-25T23:33:27.423Z" }, - { url = "https://files.pythonhosted.org/packages/5b/ba/d5e27f8d68c24951b0a484924a84c7cdaed7502bac9f18601cd357f8b1d2/cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463", size = 4926514, upload-time = "2026-03-25T23:33:29.206Z" }, - { url = "https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97", size = 4457766, upload-time = "2026-03-25T23:33:30.834Z" }, - { url = "https://files.pythonhosted.org/packages/01/59/562be1e653accee4fdad92c7a2e88fced26b3fdfce144047519bbebc299e/cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c", size = 3986535, upload-time = "2026-03-25T23:33:33.02Z" }, - { url = "https://files.pythonhosted.org/packages/d6/8b/b1ebfeb788bf4624d36e45ed2662b8bd43a05ff62157093c1539c1288a18/cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507", size = 4277618, upload-time = "2026-03-25T23:33:34.567Z" }, - { url = "https://files.pythonhosted.org/packages/dd/52/a005f8eabdb28df57c20f84c44d397a755782d6ff6d455f05baa2785bd91/cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19", size = 4890802, upload-time = "2026-03-25T23:33:37.034Z" }, - { url = "https://files.pythonhosted.org/packages/ec/4d/8e7d7245c79c617d08724e2efa397737715ca0ec830ecb3c91e547302555/cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738", size = 4457425, upload-time = "2026-03-25T23:33:38.904Z" }, - { url = "https://files.pythonhosted.org/packages/1d/5c/f6c3596a1430cec6f949085f0e1a970638d76f81c3ea56d93d564d04c340/cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c", size = 4405530, upload-time = "2026-03-25T23:33:40.842Z" }, - { url = "https://files.pythonhosted.org/packages/7e/c9/9f9cea13ee2dbde070424e0c4f621c091a91ffcc504ffea5e74f0e1daeff/cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f", size = 4667896, upload-time = "2026-03-25T23:33:42.781Z" }, - { url = "https://files.pythonhosted.org/packages/ad/b5/1895bc0821226f129bc74d00eccfc6a5969e2028f8617c09790bf89c185e/cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2", size = 3026348, upload-time = "2026-03-25T23:33:45.021Z" }, - { url = "https://files.pythonhosted.org/packages/c3/f8/c9bcbf0d3e6ad288b9d9aa0b1dee04b063d19e8c4f871855a03ab3a297ab/cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124", size = 3483896, upload-time = "2026-03-25T23:33:46.649Z" }, - { url = "https://files.pythonhosted.org/packages/01/41/3a578f7fd5c70611c0aacba52cd13cb364a5dee895a5c1d467208a9380b0/cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275", size = 7117147, upload-time = "2026-03-25T23:33:48.249Z" }, - { url = "https://files.pythonhosted.org/packages/fa/87/887f35a6fca9dde90cad08e0de0c89263a8e59b2d2ff904fd9fcd8025b6f/cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4", size = 4266221, upload-time = "2026-03-25T23:33:49.874Z" }, - { url = "https://files.pythonhosted.org/packages/aa/a8/0a90c4f0b0871e0e3d1ed126aed101328a8a57fd9fd17f00fb67e82a51ca/cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b", size = 4408952, upload-time = "2026-03-25T23:33:52.128Z" }, - { url = "https://files.pythonhosted.org/packages/16/0b/b239701eb946523e4e9f329336e4ff32b1247e109cbab32d1a7b61da8ed7/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707", size = 4270141, upload-time = "2026-03-25T23:33:54.11Z" }, - { url = "https://files.pythonhosted.org/packages/0f/a8/976acdd4f0f30df7b25605f4b9d3d89295351665c2091d18224f7ad5cdbf/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361", size = 4904178, upload-time = "2026-03-25T23:33:55.725Z" }, - { url = "https://files.pythonhosted.org/packages/b1/1b/bf0e01a88efd0e59679b69f42d4afd5bced8700bb5e80617b2d63a3741af/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b", size = 4441812, upload-time = "2026-03-25T23:33:57.364Z" }, - { url = "https://files.pythonhosted.org/packages/bb/8b/11df86de2ea389c65aa1806f331cae145f2ed18011f30234cc10ca253de8/cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca", size = 3963923, upload-time = "2026-03-25T23:33:59.361Z" }, - { url = "https://files.pythonhosted.org/packages/91/e0/207fb177c3a9ef6a8108f234208c3e9e76a6aa8cf20d51932916bd43bda0/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013", size = 4269695, upload-time = "2026-03-25T23:34:00.909Z" }, - { url = "https://files.pythonhosted.org/packages/21/5e/19f3260ed1e95bced52ace7501fabcd266df67077eeb382b79c81729d2d3/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4", size = 4869785, upload-time = "2026-03-25T23:34:02.796Z" }, - { url = "https://files.pythonhosted.org/packages/10/38/cd7864d79aa1d92ef6f1a584281433419b955ad5a5ba8d1eb6c872165bcb/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a", size = 4441404, upload-time = "2026-03-25T23:34:04.35Z" }, - { url = "https://files.pythonhosted.org/packages/09/0a/4fe7a8d25fed74419f91835cf5829ade6408fd1963c9eae9c4bce390ecbb/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d", size = 4397549, upload-time = "2026-03-25T23:34:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/5f/a0/7d738944eac6513cd60a8da98b65951f4a3b279b93479a7e8926d9cd730b/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736", size = 4651874, upload-time = "2026-03-25T23:34:07.916Z" }, - { url = "https://files.pythonhosted.org/packages/cb/f1/c2326781ca05208845efca38bf714f76939ae446cd492d7613808badedf1/cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed", size = 3001511, upload-time = "2026-03-25T23:34:09.892Z" }, - { url = "https://files.pythonhosted.org/packages/c9/57/fe4a23eb549ac9d903bd4698ffda13383808ef0876cc912bcb2838799ece/cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4", size = 3471692, upload-time = "2026-03-25T23:34:11.613Z" }, - { url = "https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a", size = 7162776, upload-time = "2026-03-25T23:34:13.308Z" }, - { url = "https://files.pythonhosted.org/packages/49/b3/dc27efd8dcc4bff583b3f01d4a3943cd8b5821777a58b3a6a5f054d61b79/cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8", size = 4270529, upload-time = "2026-03-25T23:34:15.019Z" }, - { url = "https://files.pythonhosted.org/packages/e6/05/e8d0e6eb4f0d83365b3cb0e00eb3c484f7348db0266652ccd84632a3d58d/cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77", size = 4414827, upload-time = "2026-03-25T23:34:16.604Z" }, - { url = "https://files.pythonhosted.org/packages/2f/97/daba0f5d2dc6d855e2dcb70733c812558a7977a55dd4a6722756628c44d1/cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290", size = 4271265, upload-time = "2026-03-25T23:34:18.586Z" }, - { url = "https://files.pythonhosted.org/packages/89/06/fe1fce39a37ac452e58d04b43b0855261dac320a2ebf8f5260dd55b201a9/cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410", size = 4916800, upload-time = "2026-03-25T23:34:20.561Z" }, - { url = "https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d", size = 4448771, upload-time = "2026-03-25T23:34:22.406Z" }, - { url = "https://files.pythonhosted.org/packages/01/b3/0796998056a66d1973fd52ee89dc1bb3b6581960a91ad4ac705f182d398f/cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70", size = 3978333, upload-time = "2026-03-25T23:34:24.281Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3d/db200af5a4ffd08918cd55c08399dc6c9c50b0bc72c00a3246e099d3a849/cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d", size = 4271069, upload-time = "2026-03-25T23:34:25.895Z" }, - { url = "https://files.pythonhosted.org/packages/d7/18/61acfd5b414309d74ee838be321c636fe71815436f53c9f0334bf19064fa/cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa", size = 4878358, upload-time = "2026-03-25T23:34:27.67Z" }, - { url = "https://files.pythonhosted.org/packages/8b/65/5bf43286d566f8171917cae23ac6add941654ccf085d739195a4eacf1674/cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58", size = 4448061, upload-time = "2026-03-25T23:34:29.375Z" }, - { url = "https://files.pythonhosted.org/packages/e0/25/7e49c0fa7205cf3597e525d156a6bce5b5c9de1fd7e8cb01120e459f205a/cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb", size = 4399103, upload-time = "2026-03-25T23:34:32.036Z" }, - { url = "https://files.pythonhosted.org/packages/44/46/466269e833f1c4718d6cd496ffe20c56c9c8d013486ff66b4f69c302a68d/cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72", size = 4659255, upload-time = "2026-03-25T23:34:33.679Z" }, - { url = "https://files.pythonhosted.org/packages/0a/09/ddc5f630cc32287d2c953fc5d32705e63ec73e37308e5120955316f53827/cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c", size = 3010660, upload-time = "2026-03-25T23:34:35.418Z" }, - { url = "https://files.pythonhosted.org/packages/1b/82/ca4893968aeb2709aacfb57a30dec6fa2ab25b10fa9f064b8882ce33f599/cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f", size = 3471160, upload-time = "2026-03-25T23:34:37.191Z" }, - { url = "https://files.pythonhosted.org/packages/2e/84/7ccff00ced5bac74b775ce0beb7d1be4e8637536b522b5df9b73ada42da2/cryptography-46.0.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead", size = 3475444, upload-time = "2026-03-25T23:34:38.944Z" }, - { url = "https://files.pythonhosted.org/packages/bc/1f/4c926f50df7749f000f20eede0c896769509895e2648db5da0ed55db711d/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8", size = 4218227, upload-time = "2026-03-25T23:34:40.871Z" }, - { url = "https://files.pythonhosted.org/packages/c6/65/707be3ffbd5f786028665c3223e86e11c4cda86023adbc56bd72b1b6bab5/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0", size = 4381399, upload-time = "2026-03-25T23:34:42.609Z" }, - { url = "https://files.pythonhosted.org/packages/f3/6d/73557ed0ef7d73d04d9aba745d2c8e95218213687ee5e76b7d236a5030fc/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b", size = 4217595, upload-time = "2026-03-25T23:34:44.205Z" }, - { url = "https://files.pythonhosted.org/packages/9e/c5/e1594c4eec66a567c3ac4400008108a415808be2ce13dcb9a9045c92f1a0/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a", size = 4380912, upload-time = "2026-03-25T23:34:46.328Z" }, - { url = "https://files.pythonhosted.org/packages/1a/89/843b53614b47f97fe1abc13f9a86efa5ec9e275292c457af1d4a60dc80e0/cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e", size = 3409955, upload-time = "2026-03-25T23:34:48.465Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/47/93/ac8f3d5ff04d54bc814e961a43ae5b0b146154c89c61b47bb07557679b18/cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5", size = 750652, upload-time = "2026-04-08T01:57:54.692Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/5d/4a8f770695d73be252331e60e526291e3df0c9b27556a90a6b47bccca4c2/cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4", size = 7179869, upload-time = "2026-04-08T01:56:17.157Z" }, + { url = "https://files.pythonhosted.org/packages/5f/45/6d80dc379b0bbc1f9d1e429f42e4cb9e1d319c7a8201beffd967c516ea01/cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325", size = 4275492, upload-time = "2026-04-08T01:56:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/1765afe9f572e239c3469f2cb429f3ba7b31878c893b246b4b2994ffe2fe/cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308", size = 4426670, upload-time = "2026-04-08T01:56:21.415Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3e/af9246aaf23cd4ee060699adab1e47ced3f5f7e7a8ffdd339f817b446462/cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77", size = 4280275, upload-time = "2026-04-08T01:56:23.539Z" }, + { url = "https://files.pythonhosted.org/packages/0f/54/6bbbfc5efe86f9d71041827b793c24811a017c6ac0fd12883e4caa86b8ed/cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1", size = 4928402, upload-time = "2026-04-08T01:56:25.624Z" }, + { url = "https://files.pythonhosted.org/packages/2d/cf/054b9d8220f81509939599c8bdbc0c408dbd2bdd41688616a20731371fe0/cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef", size = 4459985, upload-time = "2026-04-08T01:56:27.309Z" }, + { url = "https://files.pythonhosted.org/packages/f9/46/4e4e9c6040fb01c7467d47217d2f882daddeb8828f7df800cb806d8a2288/cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de", size = 3990652, upload-time = "2026-04-08T01:56:29.095Z" }, + { url = "https://files.pythonhosted.org/packages/36/5f/313586c3be5a2fbe87e4c9a254207b860155a8e1f3cca99f9910008e7d08/cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83", size = 4279805, upload-time = "2026-04-08T01:56:30.928Z" }, + { url = "https://files.pythonhosted.org/packages/69/33/60dfc4595f334a2082749673386a4d05e4f0cf4df8248e63b2c3437585f2/cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb", size = 4892883, upload-time = "2026-04-08T01:56:32.614Z" }, + { url = "https://files.pythonhosted.org/packages/c7/0b/333ddab4270c4f5b972f980adef4faa66951a4aaf646ca067af597f15563/cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b", size = 4459756, upload-time = "2026-04-08T01:56:34.306Z" }, + { url = "https://files.pythonhosted.org/packages/d2/14/633913398b43b75f1234834170947957c6b623d1701ffc7a9600da907e89/cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85", size = 4410244, upload-time = "2026-04-08T01:56:35.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/f2/19ceb3b3dc14009373432af0c13f46aa08e3ce334ec6eff13492e1812ccd/cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e", size = 4674868, upload-time = "2026-04-08T01:56:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/1a/bb/a5c213c19ee94b15dfccc48f363738633a493812687f5567addbcbba9f6f/cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457", size = 3026504, upload-time = "2026-04-08T01:56:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/2b/02/7788f9fefa1d060ca68717c3901ae7fffa21ee087a90b7f23c7a603c32ae/cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b", size = 3488363, upload-time = "2026-04-08T01:56:41.893Z" }, + { url = "https://files.pythonhosted.org/packages/7b/56/15619b210e689c5403bb0540e4cb7dbf11a6bf42e483b7644e471a2812b3/cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842", size = 7119671, upload-time = "2026-04-08T01:56:44Z" }, + { url = "https://files.pythonhosted.org/packages/74/66/e3ce040721b0b5599e175ba91ab08884c75928fbeb74597dd10ef13505d2/cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c", size = 4268551, upload-time = "2026-04-08T01:56:46.071Z" }, + { url = "https://files.pythonhosted.org/packages/03/11/5e395f961d6868269835dee1bafec6a1ac176505a167f68b7d8818431068/cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902", size = 4408887, upload-time = "2026-04-08T01:56:47.718Z" }, + { url = "https://files.pythonhosted.org/packages/40/53/8ed1cf4c3b9c8e611e7122fb56f1c32d09e1fff0f1d77e78d9ff7c82653e/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d", size = 4271354, upload-time = "2026-04-08T01:56:49.312Z" }, + { url = "https://files.pythonhosted.org/packages/50/46/cf71e26025c2e767c5609162c866a78e8a2915bbcfa408b7ca495c6140c4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022", size = 4905845, upload-time = "2026-04-08T01:56:50.916Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ea/01276740375bac6249d0a971ebdf6b4dc9ead0ee0a34ef3b5a88c1a9b0d4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce", size = 4444641, upload-time = "2026-04-08T01:56:52.882Z" }, + { url = "https://files.pythonhosted.org/packages/3d/4c/7d258f169ae71230f25d9f3d06caabcff8c3baf0978e2b7d65e0acac3827/cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f", size = 3967749, upload-time = "2026-04-08T01:56:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/2ea0767cad19e71b3530e4cad9605d0b5e338b6a1e72c37c9c1ceb86c333/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99", size = 4270942, upload-time = "2026-04-08T01:56:56.416Z" }, + { url = "https://files.pythonhosted.org/packages/41/3d/fe14df95a83319af25717677e956567a105bb6ab25641acaa093db79975d/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1", size = 4871079, upload-time = "2026-04-08T01:56:58.31Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/4a479e0f36f8f378d397f4eab4c850b4ffb79a2f0d58704b8fa0703ddc11/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2", size = 4443999, upload-time = "2026-04-08T01:57:00.508Z" }, + { url = "https://files.pythonhosted.org/packages/28/17/b59a741645822ec6d04732b43c5d35e4ef58be7bfa84a81e5ae6f05a1d33/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e", size = 4399191, upload-time = "2026-04-08T01:57:02.654Z" }, + { url = "https://files.pythonhosted.org/packages/59/6a/bb2e166d6d0e0955f1e9ff70f10ec4b2824c9cfcdb4da772c7dd69cc7d80/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee", size = 4655782, upload-time = "2026-04-08T01:57:04.592Z" }, + { url = "https://files.pythonhosted.org/packages/95/b6/3da51d48415bcb63b00dc17c2eff3a651b7c4fed484308d0f19b30e8cb2c/cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298", size = 3002227, upload-time = "2026-04-08T01:57:06.91Z" }, + { url = "https://files.pythonhosted.org/packages/32/a8/9f0e4ed57ec9cebe506e58db11ae472972ecb0c659e4d52bbaee80ca340a/cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb", size = 3475332, upload-time = "2026-04-08T01:57:08.807Z" }, + { url = "https://files.pythonhosted.org/packages/a7/7f/cd42fc3614386bc0c12f0cb3c4ae1fc2bbca5c9662dfed031514911d513d/cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4", size = 7165618, upload-time = "2026-04-08T01:57:10.645Z" }, + { url = "https://files.pythonhosted.org/packages/a5/d0/36a49f0262d2319139d2829f773f1b97ef8aef7f97e6e5bd21455e5a8fb5/cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7", size = 4270628, upload-time = "2026-04-08T01:57:12.885Z" }, + { url = "https://files.pythonhosted.org/packages/8a/6c/1a42450f464dda6ffbe578a911f773e54dd48c10f9895a23a7e88b3e7db5/cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832", size = 4415405, upload-time = "2026-04-08T01:57:14.923Z" }, + { url = "https://files.pythonhosted.org/packages/9a/92/4ed714dbe93a066dc1f4b4581a464d2d7dbec9046f7c8b7016f5286329e2/cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163", size = 4272715, upload-time = "2026-04-08T01:57:16.638Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e6/a26b84096eddd51494bba19111f8fffe976f6a09f132706f8f1bf03f51f7/cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2", size = 4918400, upload-time = "2026-04-08T01:57:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/c7/08/ffd537b605568a148543ac3c2b239708ae0bd635064bab41359252ef88ed/cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067", size = 4450634, upload-time = "2026-04-08T01:57:21.185Z" }, + { url = "https://files.pythonhosted.org/packages/16/01/0cd51dd86ab5b9befe0d031e276510491976c3a80e9f6e31810cce46c4ad/cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0", size = 3985233, upload-time = "2026-04-08T01:57:22.862Z" }, + { url = "https://files.pythonhosted.org/packages/92/49/819d6ed3a7d9349c2939f81b500a738cb733ab62fbecdbc1e38e83d45e12/cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba", size = 4271955, upload-time = "2026-04-08T01:57:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/80/07/ad9b3c56ebb95ed2473d46df0847357e01583f4c52a85754d1a55e29e4d0/cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006", size = 4879888, upload-time = "2026-04-08T01:57:26.88Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c7/201d3d58f30c4c2bdbe9b03844c291feb77c20511cc3586daf7edc12a47b/cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0", size = 4449961, upload-time = "2026-04-08T01:57:29.068Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ef/649750cbf96f3033c3c976e112265c33906f8e462291a33d77f90356548c/cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85", size = 4401696, upload-time = "2026-04-08T01:57:31.029Z" }, + { url = "https://files.pythonhosted.org/packages/41/52/a8908dcb1a389a459a29008c29966c1d552588d4ae6d43f3a1a4512e0ebe/cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e", size = 4664256, upload-time = "2026-04-08T01:57:33.144Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fa/f0ab06238e899cc3fb332623f337a7364f36f4bb3f2534c2bb95a35b132c/cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246", size = 3013001, upload-time = "2026-04-08T01:57:34.933Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f1/00ce3bde3ca542d1acd8f8cfa38e446840945aa6363f9b74746394b14127/cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3", size = 3472985, upload-time = "2026-04-08T01:57:36.714Z" }, + { url = "https://files.pythonhosted.org/packages/63/0c/dca8abb64e7ca4f6b2978769f6fea5ad06686a190cec381f0a796fdcaaba/cryptography-46.0.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f", size = 3476879, upload-time = "2026-04-08T01:57:38.664Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/075aac6a84b7c271578d81a2f9968acb6e273002408729f2ddff517fed4a/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15", size = 4219700, upload-time = "2026-04-08T01:57:40.625Z" }, + { url = "https://files.pythonhosted.org/packages/6c/7b/1c55db7242b5e5612b29fc7a630e91ee7a6e3c8e7bf5406d22e206875fbd/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455", size = 4385982, upload-time = "2026-04-08T01:57:42.725Z" }, + { url = "https://files.pythonhosted.org/packages/cb/da/9870eec4b69c63ef5925bf7d8342b7e13bc2ee3d47791461c4e49ca212f4/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65", size = 4219115, upload-time = "2026-04-08T01:57:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/72/05aa5832b82dd341969e9a734d1812a6aadb088d9eb6f0430fc337cc5a8f/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968", size = 4385479, upload-time = "2026-04-08T01:57:46.86Z" }, + { url = "https://files.pythonhosted.org/packages/20/2a/1b016902351a523aa2bd446b50a5bc1175d7a7d1cf90fe2ef904f9b84ebc/cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4", size = 3412829, upload-time = "2026-04-08T01:57:48.874Z" }, ] [[package]] @@ -11215,7 +11215,7 @@ wheels = [ [[package]] name = "gevent" -version = "25.9.1" +version = "26.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation == 'CPython' and sys_platform == 'win32'" }, @@ -11223,46 +11223,42 @@ dependencies = [ { name = "zope-event" }, { name = "zope-interface" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9e/48/b3ef2673ffb940f980966694e40d6d32560f3ffa284ecaeb5ea3a90a6d3f/gevent-25.9.1.tar.gz", hash = "sha256:adf9cd552de44a4e6754c51ff2e78d9193b7fa6eab123db9578a210e657235dd", size = 5059025, upload-time = "2025-09-17T16:15:34.528Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/c7/2c60fc4e5c9144f2b91e23af8d87c626870ad3183cfd09d2b3ba6d699178/gevent-25.9.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:856b990be5590e44c3a3dc6c8d48a40eaccbb42e99d2b791d11d1e7711a4297e", size = 1831980, upload-time = "2025-09-17T15:41:22.597Z" }, - { url = "https://files.pythonhosted.org/packages/2e/ae/49bf0a01f95a1c92c001d7b3f482a2301626b8a0617f448c4cd14ca9b5d4/gevent-25.9.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fe1599d0b30e6093eb3213551751b24feeb43db79f07e89d98dd2f3330c9063e", size = 1918777, upload-time = "2025-09-17T15:48:57.223Z" }, - { url = "https://files.pythonhosted.org/packages/88/3f/266d2eb9f5d75c184a55a39e886b53a4ea7f42ff31f195220a363f0e3f9e/gevent-25.9.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:f0d8b64057b4bf1529b9ef9bd2259495747fba93d1f836c77bfeaacfec373fd0", size = 1869235, upload-time = "2025-09-17T15:49:18.255Z" }, - { url = "https://files.pythonhosted.org/packages/76/24/c0c7c7db70ca74c7b1918388ebda7c8c2a3c3bff0bbfbaa9280ed04b3340/gevent-25.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b56cbc820e3136ba52cd690bdf77e47a4c239964d5f80dc657c1068e0fe9521c", size = 2177334, upload-time = "2025-09-17T15:15:10.073Z" }, - { url = "https://files.pythonhosted.org/packages/4c/1e/de96bd033c03955f54c455b51a5127b1d540afcfc97838d1801fafce6d2e/gevent-25.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c5fa9ce5122c085983e33e0dc058f81f5264cebe746de5c401654ab96dddfca8", size = 1847708, upload-time = "2025-09-17T15:52:38.475Z" }, - { url = "https://files.pythonhosted.org/packages/26/8b/6851e9cd3e4f322fa15c1d196cbf1a8a123da69788b078227dd13dd4208f/gevent-25.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:03c74fec58eda4b4edc043311fca8ba4f8744ad1632eb0a41d5ec25413581975", size = 2234274, upload-time = "2025-09-17T15:24:07.797Z" }, - { url = "https://files.pythonhosted.org/packages/0f/d8/b1178b70538c91493bec283018b47c16eab4bac9ddf5a3d4b7dd905dab60/gevent-25.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a8ae9f895e8651d10b0a8328a61c9c53da11ea51b666388aa99b0ce90f9fdc27", size = 1695326, upload-time = "2025-09-17T20:10:25.455Z" }, - { url = "https://files.pythonhosted.org/packages/81/86/03f8db0704fed41b0fa830425845f1eb4e20c92efa3f18751ee17809e9c6/gevent-25.9.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5aff9e8342dc954adb9c9c524db56c2f3557999463445ba3d9cbe3dada7b7", size = 1792418, upload-time = "2025-09-17T15:41:24.384Z" }, - { url = "https://files.pythonhosted.org/packages/5f/35/f6b3a31f0849a62cfa2c64574bcc68a781d5499c3195e296e892a121a3cf/gevent-25.9.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1cdf6db28f050ee103441caa8b0448ace545364f775059d5e2de089da975c457", size = 1875700, upload-time = "2025-09-17T15:48:59.652Z" }, - { url = "https://files.pythonhosted.org/packages/66/1e/75055950aa9b48f553e061afa9e3728061b5ccecca358cef19166e4ab74a/gevent-25.9.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:812debe235a8295be3b2a63b136c2474241fa5c58af55e6a0f8cfc29d4936235", size = 1831365, upload-time = "2025-09-17T15:49:19.426Z" }, - { url = "https://files.pythonhosted.org/packages/31/e8/5c1f6968e5547e501cfa03dcb0239dff55e44c3660a37ec534e32a0c008f/gevent-25.9.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b28b61ff9216a3d73fe8f35669eefcafa957f143ac534faf77e8a19eb9e6883a", size = 2122087, upload-time = "2025-09-17T15:15:12.329Z" }, - { url = "https://files.pythonhosted.org/packages/c0/2c/ebc5d38a7542af9fb7657bfe10932a558bb98c8a94e4748e827d3823fced/gevent-25.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5e4b6278b37373306fc6b1e5f0f1cf56339a1377f67c35972775143d8d7776ff", size = 1808776, upload-time = "2025-09-17T15:52:40.16Z" }, - { url = "https://files.pythonhosted.org/packages/e6/26/e1d7d6c8ffbf76fe1fbb4e77bdb7f47d419206adc391ec40a8ace6ebbbf0/gevent-25.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d99f0cb2ce43c2e8305bf75bee61a8bde06619d21b9d0316ea190fc7a0620a56", size = 2179141, upload-time = "2025-09-17T15:24:09.895Z" }, - { url = "https://files.pythonhosted.org/packages/1d/6c/bb21fd9c095506aeeaa616579a356aa50935165cc0f1e250e1e0575620a7/gevent-25.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:72152517ecf548e2f838c61b4be76637d99279dbaa7e01b3924df040aa996586", size = 1677941, upload-time = "2025-09-17T19:59:50.185Z" }, - { url = "https://files.pythonhosted.org/packages/f7/49/e55930ba5259629eb28ac7ee1abbca971996a9165f902f0249b561602f24/gevent-25.9.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:46b188248c84ffdec18a686fcac5dbb32365d76912e14fda350db5dc0bfd4f86", size = 2955991, upload-time = "2025-09-17T14:52:30.568Z" }, - { url = "https://files.pythonhosted.org/packages/aa/88/63dc9e903980e1da1e16541ec5c70f2b224ec0a8e34088cb42794f1c7f52/gevent-25.9.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f2b54ea3ca6f0c763281cd3f96010ac7e98c2e267feb1221b5a26e2ca0b9a692", size = 1808503, upload-time = "2025-09-17T15:41:25.59Z" }, - { url = "https://files.pythonhosted.org/packages/7a/8d/7236c3a8f6ef7e94c22e658397009596fa90f24c7d19da11ad7ab3a9248e/gevent-25.9.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7a834804ac00ed8a92a69d3826342c677be651b1c3cd66cc35df8bc711057aa2", size = 1890001, upload-time = "2025-09-17T15:49:01.227Z" }, - { url = "https://files.pythonhosted.org/packages/4f/63/0d7f38c4a2085ecce26b50492fc6161aa67250d381e26d6a7322c309b00f/gevent-25.9.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:323a27192ec4da6b22a9e51c3d9d896ff20bc53fdc9e45e56eaab76d1c39dd74", size = 1855335, upload-time = "2025-09-17T15:49:20.582Z" }, - { url = "https://files.pythonhosted.org/packages/95/18/da5211dfc54c7a57e7432fd9a6ffeae1ce36fe5a313fa782b1c96529ea3d/gevent-25.9.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6ea78b39a2c51d47ff0f130f4c755a9a4bbb2dd9721149420ad4712743911a51", size = 2109046, upload-time = "2025-09-17T15:15:13.817Z" }, - { url = "https://files.pythonhosted.org/packages/a6/5a/7bb5ec8e43a2c6444853c4a9f955f3e72f479d7c24ea86c95fb264a2de65/gevent-25.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dc45cd3e1cc07514a419960af932a62eb8515552ed004e56755e4bf20bad30c5", size = 1827099, upload-time = "2025-09-17T15:52:41.384Z" }, - { url = "https://files.pythonhosted.org/packages/ca/d4/b63a0a60635470d7d986ef19897e893c15326dd69e8fb342c76a4f07fe9e/gevent-25.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34e01e50c71eaf67e92c186ee0196a039d6e4f4b35670396baed4a2d8f1b347f", size = 2172623, upload-time = "2025-09-17T15:24:12.03Z" }, - { url = "https://files.pythonhosted.org/packages/d5/98/caf06d5d22a7c129c1fb2fc1477306902a2c8ddfd399cd26bbbd4caf2141/gevent-25.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:4acd6bcd5feabf22c7c5174bd3b9535ee9f088d2bbce789f740ad8d6554b18f3", size = 1682837, upload-time = "2025-09-17T19:48:47.318Z" }, - { url = "https://files.pythonhosted.org/packages/5a/77/b97f086388f87f8ad3e01364f845004aef0123d4430241c7c9b1f9bde742/gevent-25.9.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:4f84591d13845ee31c13f44bdf6bd6c3dbf385b5af98b2f25ec328213775f2ed", size = 2973739, upload-time = "2025-09-17T14:53:30.279Z" }, - { url = "https://files.pythonhosted.org/packages/3c/2e/9d5f204ead343e5b27bbb2fedaec7cd0009d50696b2266f590ae845d0331/gevent-25.9.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9cdbb24c276a2d0110ad5c978e49daf620b153719ac8a548ce1250a7eb1b9245", size = 1809165, upload-time = "2025-09-17T15:41:27.193Z" }, - { url = "https://files.pythonhosted.org/packages/10/3e/791d1bf1eb47748606d5f2c2aa66571f474d63e0176228b1f1fd7b77ab37/gevent-25.9.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:88b6c07169468af631dcf0fdd3658f9246d6822cc51461d43f7c44f28b0abb82", size = 1890638, upload-time = "2025-09-17T15:49:02.45Z" }, - { url = "https://files.pythonhosted.org/packages/f2/5c/9ad0229b2b4d81249ca41e4f91dd8057deaa0da6d4fbe40bf13cdc5f7a47/gevent-25.9.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b7bb0e29a7b3e6ca9bed2394aa820244069982c36dc30b70eb1004dd67851a48", size = 1857118, upload-time = "2025-09-17T15:49:22.125Z" }, - { url = "https://files.pythonhosted.org/packages/49/2a/3010ed6c44179a3a5c5c152e6de43a30ff8bc2c8de3115ad8733533a018f/gevent-25.9.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2951bb070c0ee37b632ac9134e4fdaad70d2e660c931bb792983a0837fe5b7d7", size = 2111598, upload-time = "2025-09-17T15:15:15.226Z" }, - { url = "https://files.pythonhosted.org/packages/08/75/6bbe57c19a7aa4527cc0f9afcdf5a5f2aed2603b08aadbccb5bf7f607ff4/gevent-25.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e4e17c2d57e9a42e25f2a73d297b22b60b2470a74be5a515b36c984e1a246d47", size = 1829059, upload-time = "2025-09-17T15:52:42.596Z" }, - { url = "https://files.pythonhosted.org/packages/06/6e/19a9bee9092be45679cb69e4dd2e0bf5f897b7140b4b39c57cc123d24829/gevent-25.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d94936f8f8b23d9de2251798fcb603b84f083fdf0d7f427183c1828fb64f117", size = 2173529, upload-time = "2025-09-17T15:24:13.897Z" }, - { url = "https://files.pythonhosted.org/packages/ca/4f/50de9afd879440e25737e63f5ba6ee764b75a3abe17376496ab57f432546/gevent-25.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:eb51c5f9537b07da673258b4832f6635014fee31690c3f0944d34741b69f92fa", size = 1681518, upload-time = "2025-09-17T19:39:47.488Z" }, - { url = "https://files.pythonhosted.org/packages/15/1a/948f8167b2cdce573cf01cec07afc64d0456dc134b07900b26ac7018b37e/gevent-25.9.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:1a3fe4ea1c312dbf6b375b416925036fe79a40054e6bf6248ee46526ea628be1", size = 2982934, upload-time = "2025-09-17T14:54:11.302Z" }, - { url = "https://files.pythonhosted.org/packages/9b/ec/726b146d1d3aad82e03d2e1e1507048ab6072f906e83f97f40667866e582/gevent-25.9.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0adb937f13e5fb90cca2edf66d8d7e99d62a299687400ce2edee3f3504009356", size = 1813982, upload-time = "2025-09-17T15:41:28.506Z" }, - { url = "https://files.pythonhosted.org/packages/35/5d/5f83f17162301662bd1ce702f8a736a8a8cac7b7a35e1d8b9866938d1f9d/gevent-25.9.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:427f869a2050a4202d93cf7fd6ab5cffb06d3e9113c10c967b6e2a0d45237cb8", size = 1894902, upload-time = "2025-09-17T15:49:03.702Z" }, - { url = "https://files.pythonhosted.org/packages/83/cd/cf5e74e353f60dab357829069ffc300a7bb414c761f52cf8c0c6e9728b8d/gevent-25.9.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c049880175e8c93124188f9d926af0a62826a3b81aa6d3074928345f8238279e", size = 1861792, upload-time = "2025-09-17T15:49:23.279Z" }, - { url = "https://files.pythonhosted.org/packages/dd/65/b9a4526d4a4edce26fe4b3b993914ec9dc64baabad625a3101e51adb17f3/gevent-25.9.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b5a67a0974ad9f24721034d1e008856111e0535f1541499f72a733a73d658d1c", size = 2113215, upload-time = "2025-09-17T15:15:16.34Z" }, - { url = "https://files.pythonhosted.org/packages/e5/be/7d35731dfaf8370795b606e515d964a0967e129db76ea7873f552045dd39/gevent-25.9.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1d0f5d8d73f97e24ea8d24d8be0f51e0cf7c54b8021c1fddb580bf239474690f", size = 1833449, upload-time = "2025-09-17T15:52:43.75Z" }, - { url = "https://files.pythonhosted.org/packages/65/58/7bc52544ea5e63af88c4a26c90776feb42551b7555a1c89c20069c168a3f/gevent-25.9.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ddd3ff26e5c4240d3fbf5516c2d9d5f2a998ef87cfb73e1429cfaeaaec860fa6", size = 2176034, upload-time = "2025-09-17T15:24:15.676Z" }, - { url = "https://files.pythonhosted.org/packages/c2/69/a7c4ba2ffbc7c7dbf6d8b4f5d0f0a421f7815d229f4909854266c445a3d4/gevent-25.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:bb63c0d6cb9950cc94036a4995b9cc4667b8915366613449236970f4394f94d7", size = 1703019, upload-time = "2025-09-17T19:30:55.272Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/20/27/1062fa31333dc3428a1f5f33cd6598b0552165ba679ca3ba116de42c9e8e/gevent-26.4.0.tar.gz", hash = "sha256:288d03addfccf0d1c67268358b6759b04392bf3bc35d26f3d9a45c82899c292d", size = 6242440, upload-time = "2026-04-09T12:08:19.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/92/fd1f4016b92591fe7ccf44d01883a3337178a6e9ea4c04e1ddce7a2e3db1/gevent-26.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:079dca3fe5e048714e93ab5ce7cbf2ec31709c860979feb117abbbf2b8ae6ad0", size = 2180478, upload-time = "2026-04-08T21:54:11.739Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b9/ac8a6561b9efd141dfbb2d0ae1d2fd3255f9e9ccfeceb64a6917e2ef6625/gevent-26.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:df208cd53c7382a4cc8470d39a92fc73b3cf2f0f3379d6c88bb556823a26ccb7", size = 2211145, upload-time = "2026-04-08T21:59:59.318Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2f/2cd44b3a2f60903cae39602045344b434e8621f7145470f0f00e5be8a44a/gevent-26.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ccaa0f002cfd69c03621ac05243c1a00ed77cee97b363d0108b0e36663e4ca33", size = 1694090, upload-time = "2026-04-08T23:40:50.101Z" }, + { url = "https://files.pythonhosted.org/packages/12/0e/330c4788860520850b7f4c6f84dd8591df5172cfd3f2796c046704ee879e/gevent-26.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:201323a5fb9a0646a0c7b384395ca55d60ee83200677919229df0648c4b78e6c", size = 1767278, upload-time = "2026-04-08T22:23:16.491Z" }, + { url = "https://files.pythonhosted.org/packages/cf/27/717593d7cce74a2fd6bee0713793518e0398132303d5267f02dd587c5945/gevent-26.4.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:82d68a60a4207826db295b4e80a204c9d392ce78ccc15679195faeb9e29d8388", size = 1861609, upload-time = "2026-04-08T22:27:09.302Z" }, + { url = "https://files.pythonhosted.org/packages/fb/af/ce6d4d554d9afc354b46b78eccb032f6add4d27c3eadaa0201ee103fa831/gevent-26.4.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:35b037b415ed38369717800250fe5974249525953b46026bef9def20f946dfb0", size = 1803675, upload-time = "2026-04-08T22:34:35.289Z" }, + { url = "https://files.pythonhosted.org/packages/57/09/909166fff7d2ab9523e93bbd56e863df79a856b2857350218be83aef119d/gevent-26.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:6d973735d2067607a32cd182893978755eee829a0dc268087592d3b715e63fad", size = 2118034, upload-time = "2026-04-08T21:54:13.293Z" }, + { url = "https://files.pythonhosted.org/packages/83/6b/ab68e1cc09fd6dd7adb9e1c54a47c6328df20aa012ed75526a3244f2ad05/gevent-26.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4fbd3ff28a7babbfee750684c4f46ba6eedb3bce69365dd146726986b79fa6c1", size = 1777768, upload-time = "2026-04-08T22:26:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/ff/d3/b75568e7206ea4b89a7e21750381aa4a6f9afcced41d5a80a72b5fcc6b87/gevent-26.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f0a03650ca60c4c5774cbe21333905b95f2f5abd98ea5a3dbf28d93f2a7a5a84", size = 2144355, upload-time = "2026-04-08T22:00:00.684Z" }, + { url = "https://files.pythonhosted.org/packages/f7/32/5f795143351bfbecd05467deec48ea75416bb90eb7a6dd042c7d7e5ec594/gevent-26.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d00d8c4ca1afab90e478b79679dd53787082c6da8d2f4fdc7667a4440d1e1a7a", size = 1676684, upload-time = "2026-04-08T23:28:04.124Z" }, + { url = "https://files.pythonhosted.org/packages/3d/16/131d3874f50974b355c90a061a12d3fe2292cde0f875a1fa3d8b224f1251/gevent-26.4.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:318a0a73f664113e8d86d0cb0e328e7650e2d7d9c2e045418ab6fb1285831ad3", size = 2928699, upload-time = "2026-04-08T21:25:36.215Z" }, + { url = "https://files.pythonhosted.org/packages/ea/8b/199e59b303adaff7f7365def9ab569c7ecd863363c974548bce3ddc2c89d/gevent-26.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:ce7aa033a3f68beb6732d1450a80c1af29e63e0c2d01abad7918cf2507f72fa6", size = 1783821, upload-time = "2026-04-08T22:23:18.73Z" }, + { url = "https://files.pythonhosted.org/packages/e2/2d/b8249c9bd3f386191311c3a9bec4068e192a3f9df2fad92a71a15265ba15/gevent-26.4.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:a1b897c952baefd72232efaeb3bdb1ca2fa7ae94cbfe68ac21201b03e843190a", size = 1879424, upload-time = "2026-04-08T22:27:10.561Z" }, + { url = "https://files.pythonhosted.org/packages/ef/89/59216985c1f2c11f2f28bbc88e583588ad44cdde823c530ad4e307be6612/gevent-26.4.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:7eef2ea508ce41795e20587a5fc868ae4919543097c81a40fbdfd65bc479f54f", size = 1830575, upload-time = "2026-04-08T22:34:37.093Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a9/2d67d2b0aa0ca9d7bb7fe73c3bbb97b3695cb15c338a6ea7734f58da9add/gevent-26.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f7e12fdd28cc9f39a463d8df5172d698c64a8ed385a21d98e7092fd8308a139a", size = 2113898, upload-time = "2026-04-08T21:54:14.9Z" }, + { url = "https://files.pythonhosted.org/packages/95/a3/457d58d9b3e7da17c8456d841c37a32af8d231a1d71237ad201b19129317/gevent-26.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d48e3ee13d7678c24c22f19d441ad6bc220a79f23662d03ff36fae0d62efdb59", size = 1795890, upload-time = "2026-04-08T22:26:53.252Z" }, + { url = "https://files.pythonhosted.org/packages/a7/cc/cbe78f2626643b20275aaa41cd2cc45ba75056e3665bde36bc190af3cae0/gevent-26.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c58c8e034f94329be4dc0979fba3301005a433dbab42cea0b2c33fd736946872", size = 2139791, upload-time = "2026-04-08T22:00:02.375Z" }, + { url = "https://files.pythonhosted.org/packages/f6/df/7875e08b06a95f4577b71708ec470d029fadf873a66eb813a2861d79dfb5/gevent-26.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1c737e6ac6ce1398df0e3f41c58d982e397c993cbe73ac05b7edbe39e128c9cb", size = 1680530, upload-time = "2026-04-08T23:15:38.714Z" }, + { url = "https://files.pythonhosted.org/packages/3d/be/51809d98bb00846d7756a0b82625024f9302145f3d024846b43f05efeddb/gevent-26.4.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1fe581d41c63cd1d8b12c69561ce53a48ad0d8763b254740d7bfea997335a38c", size = 2951507, upload-time = "2026-04-08T21:25:25.809Z" }, + { url = "https://files.pythonhosted.org/packages/d6/86/89325a62a4e8cc1934e155b383b66491ed21d1e774b13d5054d51fa0ac81/gevent-26.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c503b0c0a681e795255a13e5bb4e41615c3b020c1db93b8dfa04cfeb8f19d5a9", size = 1786029, upload-time = "2026-04-08T22:23:20.395Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ea/04d112844aa992da583cbd280f17a4ba097da338dab347efd0aa5e235645/gevent-26.4.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:684256c29e3e5d4d0c4d06b772d00574d0dc859dfbb2fd13d318c512b16e1f89", size = 1881326, upload-time = "2026-04-08T22:27:11.822Z" }, + { url = "https://files.pythonhosted.org/packages/a1/33/71900c5ba442f5df89456b6d9fdaa43da2ae7cdd937d8c5667b49323ceb4/gevent-26.4.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:73eafd06b158d511f1ec6e5902a45e0ae3b48e745f35e9df97d25f809f537d88", size = 1833123, upload-time = "2026-04-08T22:34:39.001Z" }, + { url = "https://files.pythonhosted.org/packages/d0/af/7df19c92e56842921f34787e1168c7afc52a23b0d1253bba99344809a935/gevent-26.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1a18e543c830a1c07a2efeb33786a57ccac360af70cb42bbaf5a6f5f7ca49300", size = 2114330, upload-time = "2026-04-08T21:54:16.547Z" }, + { url = "https://files.pythonhosted.org/packages/ca/0e/202694960f8d4dda68fd2a73bbcb8251e2d5308339924310ff1fff31bf7c/gevent-26.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:74f1e3a460c43aefcb4ff9ef91aac15abc0b42e5233771e1956574d14ba9cac6", size = 1798427, upload-time = "2026-04-08T22:26:54.462Z" }, + { url = "https://files.pythonhosted.org/packages/75/69/2d056b2a4e3ef1f65f94002725572d1e99163ff79231dbb68ad529e7cb9d/gevent-26.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:954258873ae0bcc97fb41e48db25284fb73454bfefe27db8ceb89225da5502fb", size = 2140100, upload-time = "2026-04-08T22:00:03.966Z" }, + { url = "https://files.pythonhosted.org/packages/fe/a0/1a7f64aa2476c2b44abaecca919a6561bda85234f99fc7ac3c66bcb93050/gevent-26.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:4a9a64c064457c1afaf93ee2815fe0f38be6ecbb92806a6a712f12afc3e26cf5", size = 1680206, upload-time = "2026-04-08T23:01:56.636Z" }, + { url = "https://files.pythonhosted.org/packages/7e/f3/64638a941988f09aa1816e2674eb1efb215b6fa64a97edef6e25177b0845/gevent-26.4.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:7ab0f183a6fd2369eef619832eef14f1f2f69c605163c3f2dc41deb799af4a71", size = 2967206, upload-time = "2026-04-08T21:25:44.73Z" }, + { url = "https://files.pythonhosted.org/packages/f6/70/a86be65a51d3ebb92c82a70adc9c5c32b1a9d9579120d0be1db7cf534ce0/gevent-26.4.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:7e5906860e632bf965e1966c57e6bfc19dcb79dc262f04fdb0a9d7c12147bf69", size = 1792916, upload-time = "2026-04-08T22:23:22.006Z" }, + { url = "https://files.pythonhosted.org/packages/40/92/18fdb4b28f20129395f1c041773adee99e7fc2bcfff216df93bfb80787d5/gevent-26.4.0-cp314-cp314-manylinux_2_28_ppc64le.whl", hash = "sha256:297a361071dc6708115d4544859321e93b02a6cd5823ba02c0a909530a519d45", size = 1886617, upload-time = "2026-04-08T22:27:13.716Z" }, + { url = "https://files.pythonhosted.org/packages/af/c9/d02222ecf79d10c8a0c2755661485395b58c4bfffaafd88bcc230ce392de/gevent-26.4.0-cp314-cp314-manylinux_2_28_s390x.whl", hash = "sha256:7e74f59e5c9011afa2a9cb7106bb9a59f2a1f74c3d7b272c1b852eb0bc0b8f90", size = 1837660, upload-time = "2026-04-08T22:34:40.823Z" }, + { url = "https://files.pythonhosted.org/packages/46/85/9376d125fa4f7b0f269925d0d622eda0ff8f8dfc8d0c097a096c511fc738/gevent-26.4.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:45d6010a6a981f5a2b3411c4e38fbe305a1b46e4b12db3b4914775927dea7ba4", size = 2119342, upload-time = "2026-04-08T21:54:17.747Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c4/1fe2817daca8e97c365fd739dd4057f71cce26ef600fb8465deb8060c83c/gevent-26.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dc38137ba2f43794c488615aafa2eefd0cc142f484a8274d4c827ed7a031a1e2", size = 1805672, upload-time = "2026-04-08T22:26:55.792Z" }, + { url = "https://files.pythonhosted.org/packages/e7/cc/ccbcbd56e7e85482291fbb90a317f5febf630ec4174a91506f4167ba0912/gevent-26.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:29a225d2d4da37e20c7a246754a64442d0e43e4534b8cc764f89530bb22a4237", size = 2145594, upload-time = "2026-04-08T22:00:05.275Z" }, + { url = "https://files.pythonhosted.org/packages/8e/b9/7dd37b6001d16f692b1bfb6e68cad642beb38b34a753c29bbff312f46e4b/gevent-26.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1c08bc9bb6bd79732a26710a99588b5e9b67b668e165dd609704b876f41baab", size = 1703189, upload-time = "2026-04-08T22:48:31.713Z" }, ] [[package]] @@ -11326,7 +11322,7 @@ wheels = [ [[package]] name = "google-api-core" -version = "2.30.2" +version = "2.30.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, @@ -11335,9 +11331,9 @@ dependencies = [ { name = "protobuf" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1a/2e/83ca41eb400eb228f9279ec14ed66f6475218b59af4c6daec2d5a509fe83/google_api_core-2.30.2.tar.gz", hash = "sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9", size = 176862, upload-time = "2026-04-02T21:23:44.876Z" } +sdist = { url = "https://files.pythonhosted.org/packages/16/ce/502a57fb0ec752026d24df1280b162294b22a0afb98a326084f9a979138b/google_api_core-2.30.3.tar.gz", hash = "sha256:e601a37f148585319b26db36e219df68c5d07b6382cff2d580e83404e44d641b", size = 177001, upload-time = "2026-04-10T00:41:28.035Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl", hash = "sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594", size = 173236, upload-time = "2026-04-02T21:23:06.395Z" }, + { url = "https://files.pythonhosted.org/packages/03/15/e56f351cf6ef1cfea58e6ac226a7318ed1deb2218c4b3cc9bd9e4b786c5a/google_api_core-2.30.3-py3-none-any.whl", hash = "sha256:a85761ba72c444dad5d611c2220633480b2b6be2521eca69cca2dbb3ffd6bfe8", size = 173274, upload-time = "2026-04-09T22:57:16.198Z" }, ] [package.optional-dependencies] @@ -11348,7 +11344,7 @@ grpc = [ [[package]] name = "google-api-python-client" -version = "2.193.0" +version = "2.194.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -11357,22 +11353,22 @@ dependencies = [ { name = "httplib2" }, { name = "uritemplate" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/90/f4/e14b6815d3b1885328dd209676a3a4c704882743ac94e18ef0093894f5c8/google_api_python_client-2.193.0.tar.gz", hash = "sha256:8f88d16e89d11341e0a8b199cafde0fb7e6b44260dffb88d451577cbd1bb5d33", size = 14281006, upload-time = "2026-03-17T18:25:29.415Z" } +sdist = { url = "https://files.pythonhosted.org/packages/60/ab/e83af0eb043e4ccc49571ca7a6a49984e9d00f4e9e6e6f1238d60bc84dce/google_api_python_client-2.194.0.tar.gz", hash = "sha256:db92647bd1a90f40b79c9618461553c2b20b6a43ce7395fa6de07132dc14f023", size = 14443469, upload-time = "2026-04-08T23:07:35.757Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f0/6d/fe75167797790a56d17799b75e1129bb93f7ff061efc7b36e9731bd4be2b/google_api_python_client-2.193.0-py3-none-any.whl", hash = "sha256:c42aa324b822109901cfecab5dc4fc3915d35a7b376835233c916c70610322db", size = 14856490, upload-time = "2026-03-17T18:25:26.608Z" }, + { url = "https://files.pythonhosted.org/packages/b0/34/5a624e49f179aa5b0cb87b2ce8093960299030ff40423bfbde09360eb908/google_api_python_client-2.194.0-py3-none-any.whl", hash = "sha256:61eaaac3b8fc8fdf11c08af87abc3d1342d1b37319cc1b57405f86ef7697e717", size = 15016514, upload-time = "2026-04-08T23:07:33.093Z" }, ] [[package]] name = "google-auth" -version = "2.49.1" +version = "2.49.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/80/6a696a07d3d3b0a92488933532f03dbefa4a24ab80fb231395b9a2a1be77/google_auth-2.49.1.tar.gz", hash = "sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64", size = 333825, upload-time = "2026-03-12T19:30:58.135Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c6/fc/e925290a1ad95c975c459e2df070fac2b90954e13a0370ac505dff78cb99/google_auth-2.49.2.tar.gz", hash = "sha256:c1ae38500e73065dcae57355adb6278cf8b5c8e391994ae9cbadbcb9631ab409", size = 333958, upload-time = "2026-04-10T00:41:21.888Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl", hash = "sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7", size = 240737, upload-time = "2026-03-12T19:30:53.159Z" }, + { url = "https://files.pythonhosted.org/packages/73/76/d241a5c927433420507215df6cac1b1fa4ac0ba7a794df42a84326c68da8/google_auth-2.49.2-py3-none-any.whl", hash = "sha256:c2720924dfc82dedb962c9f52cabb2ab16714fd0a6a707e40561d217574ed6d5", size = 240638, upload-time = "2026-04-10T00:41:14.501Z" }, ] [package.optional-dependencies] @@ -11408,7 +11404,7 @@ wheels = [ [[package]] name = "google-cloud-aiplatform" -version = "1.145.0" +version = "1.147.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docstring-parser" }, @@ -11424,9 +11420,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/e5/6442d9d2c019456638825d4665b1e87ec4eaf1d182950ba426d0f0210eab/google_cloud_aiplatform-1.145.0.tar.gz", hash = "sha256:7894c4f3d2684bdb60e9a122004c01678e3b585174a27298ae7a3ed1e5eaf3bd", size = 10222904, upload-time = "2026-04-02T14:06:58.322Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/93/9bfcaaf1ceab12999a881ccf69ebd9b30f467ec5623989c66894e81fc139/google_cloud_aiplatform-1.147.0.tar.gz", hash = "sha256:b2e1b669ba37f02426e03eb13187eebf4cbfeaa0a3bfed37b5578abb375ab689", size = 10235245, upload-time = "2026-04-09T17:14:49.179Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/c6/23e98d3407d5e2416a3dfaecb0a053da899848c50db69e5f2b61a555ce06/google_cloud_aiplatform-1.145.0-py2.py3-none-any.whl", hash = "sha256:4d1c31797a8bd8f3342ed5f186dd30d1f6bca73ddbee2bde452777100d2ddc11", size = 8396640, upload-time = "2026-04-02T14:06:54.125Z" }, + { url = "https://files.pythonhosted.org/packages/d3/d2/1c1c582f6bbed9bbc0daa5acf3a5d98751ca8bc48584548d28569b8ce1a7/google_cloud_aiplatform-1.147.0-py2.py3-none-any.whl", hash = "sha256:29f7ae020718d3c45094f0475464e06a97f81b1572bea150ae6a1b22c5f45997", size = 8408951, upload-time = "2026-04-09T17:14:45.482Z" }, ] [package.optional-dependencies] @@ -11752,7 +11748,7 @@ wheels = [ [[package]] name = "google-cloud-dlp" -version = "3.35.0" +version = "3.36.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -11761,9 +11757,9 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/80/1401785105fba2979bf5c627f96cd326703e520116b961d377bb1b7c82d5/google_cloud_dlp-3.35.0.tar.gz", hash = "sha256:bd6a1b30f263cb170480a60bdedd0424bcc99e2039a228d9c89bb13b32c042cc", size = 279794, upload-time = "2026-03-30T22:50:00.358Z" } +sdist = { url = "https://files.pythonhosted.org/packages/25/fd/7cc493dedfcf2816a51034349d1961dcc0d62e5a6ad6152a62456fdf9631/google_cloud_dlp-3.36.0.tar.gz", hash = "sha256:a239a214303ca08ccdcdd7b6ee270d2ce4e4e81955a05648ffdb383204bf5ca6", size = 280086, upload-time = "2026-04-10T00:41:23.883Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/8c/f359067160140888541332aa0582f9ee9bdcb3d0fffe104a10fe9a244e01/google_cloud_dlp-3.35.0-py3-none-any.whl", hash = "sha256:098031afab08a5fbbb389b32b06303293b69ae9dfb4ca06e564f347554bec7a0", size = 223971, upload-time = "2026-03-30T22:48:09.263Z" }, + { url = "https://files.pythonhosted.org/packages/7b/b1/f3c8a58d6c267308c26ba951003adb6b63f53516eb1e9c91981ad762a5fe/google_cloud_dlp-3.36.0-py3-none-any.whl", hash = "sha256:e215c4d74e87108449838fb81f60875f3811772f645aa0455753d74069395dec", size = 224246, upload-time = "2026-04-10T00:41:03.741Z" }, ] [[package]] @@ -11902,7 +11898,7 @@ wheels = [ [[package]] name = "google-cloud-pubsub" -version = "2.36.0" +version = "2.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -11915,9 +11911,9 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/f5cece431daaa2024129569ed35e6eb90a72bb51f0c96e5c7f5cab6d34d7/google_cloud_pubsub-2.36.0.tar.gz", hash = "sha256:96e057e5f83433ce428852095d652c2f7fc193f0f77db1f27cc39186fe69c1f4", size = 401324, upload-time = "2026-03-12T19:31:02.099Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/89/558c48382d6875335ea6cd7f6409acfbf256b9f7fbc2ad1c19976aabdb1f/google_cloud_pubsub-2.37.0.tar.gz", hash = "sha256:7c5ba9beb5236e2b83c091dd6171423dc7d6d0e989391bd09f60dbd242b29f10", size = 403391, upload-time = "2026-04-10T00:41:17.799Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/fd/d0a8f0f93a4d115282ecdd8ef0267e4611bde6ca29c9dba803f3ebae7115/google_cloud_pubsub-2.36.0-py3-none-any.whl", hash = "sha256:d6726ccf9373924e0746338dadf8244b9aa1a97a24130b59a2106c926ea37598", size = 323364, upload-time = "2026-03-12T19:30:48.077Z" }, + { url = "https://files.pythonhosted.org/packages/64/f1/bb7162ec50971b1d252e6837d05f64f185d5cfe4e08de8f706e363c305d9/google_cloud_pubsub-2.37.0-py3-none-any.whl", hash = "sha256:dd912422cf66e4ffb423b0d5391ca81bdfa408eb0f21f57adecdb6fb3b1e0bb1", size = 325136, upload-time = "2026-04-10T00:41:01.391Z" }, ] [[package]] @@ -12112,7 +12108,7 @@ wheels = [ [[package]] name = "google-cloud-translate" -version = "3.25.0" +version = "3.26.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -12123,9 +12119,9 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/8b/4e65df215e38f67b351c73d67ba9a47ee539cc0c0dede5ae62196f173ba1/google_cloud_translate-3.25.0.tar.gz", hash = "sha256:a3401e20e3d18eeab68e15b80faf4f985c6ca21934affea4038b961cd19310de", size = 276508, upload-time = "2026-03-26T22:17:33.745Z" } +sdist = { url = "https://files.pythonhosted.org/packages/45/52/3bc1f9b87511eb3b4d28c4d7da65f1f4ecc407df46e56cff0eae43b5d875/google_cloud_translate-3.26.0.tar.gz", hash = "sha256:74c4c302ea705daa1d7dda095288fd736bb616f943480db34314cd0cd52cc9dd", size = 276633, upload-time = "2026-04-10T00:41:26.769Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/15/c5bc937385331632fa58f3995baab6609e36767680f4c83c2bc8d553cade/google_cloud_translate-3.25.0-py3-none-any.whl", hash = "sha256:0131befe81fc026d4957ff673424ec32d009151b09687867695d9d05bc59ff8a", size = 210865, upload-time = "2026-03-26T22:13:57.378Z" }, + { url = "https://files.pythonhosted.org/packages/17/c2/50ed19071e57002ee1bb328e3fcfe43d71aafd9ab0b1e4a107d6c4d3c79d/google_cloud_translate-3.26.0-py3-none-any.whl", hash = "sha256:5b9f4d2cfdc41fcd357cda47d4d880acb6d720be7f0b8fdf95f2816dc982359d", size = 210892, upload-time = "2026-04-10T00:41:12.339Z" }, ] [[package]] @@ -12213,7 +12209,7 @@ wheels = [ [[package]] name = "google-genai" -version = "1.70.0" +version = "1.72.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -12227,9 +12223,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/dd/28e4682904b183acbfad3fe6409f13a42f69bb8eab6e882d3bcbea1dde01/google_genai-1.70.0.tar.gz", hash = "sha256:36b67b0fc6f319e08d1f1efd808b790107b1809c8743a05d55dfcf9d9fad7719", size = 519550, upload-time = "2026-04-01T10:52:46.487Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3c/20/2aff5ea3cd7459f85101d119c136d9ca4369fcda3dcf0cfee89b305611a4/google_genai-1.72.0.tar.gz", hash = "sha256:abe7d3aecfafb464b904e3a09c81b626fb425e160e123e71a5125a7021cea7b2", size = 522844, upload-time = "2026-04-09T21:35:46.283Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/a3/d4564c8a9beaf6a3cef8d70fa6354318572cebfee65db4f01af0d41f45ba/google_genai-1.70.0-py3-none-any.whl", hash = "sha256:b74c24549d8b4208f4c736fd11857374788e1ffffc725de45d706e35c97fceee", size = 760584, upload-time = "2026-04-01T10:52:44.349Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3d/9f70246114cdf56a2615a40428ced08bc844f5a26247fe812b2f0dd4eaca/google_genai-1.72.0-py3-none-any.whl", hash = "sha256:ea861e4c6946e3185c24b40d95503e088fc230a73a71fec0ef78164b369a8489", size = 764230, upload-time = "2026-04-09T21:35:44.587Z" }, ] [[package]] @@ -12295,67 +12291,73 @@ wheels = [ [[package]] name = "greenlet" -version = "3.3.2" +version = "3.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a3/51/1664f6b78fc6ebbd98019a1fd730e83fa78f2db7058f72b1463d3612b8db/greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2", size = 188267, upload-time = "2026-02-20T20:54:15.531Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", size = 277747, upload-time = "2026-02-20T20:16:21.325Z" }, - { url = "https://files.pythonhosted.org/packages/fb/07/cb284a8b5c6498dbd7cba35d31380bb123d7dceaa7907f606c8ff5993cbf/greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", size = 579202, upload-time = "2026-02-20T20:47:28.955Z" }, - { url = "https://files.pythonhosted.org/packages/ed/45/67922992b3a152f726163b19f890a85129a992f39607a2a53155de3448b8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", size = 590620, upload-time = "2026-02-20T20:55:55.581Z" }, - { url = "https://files.pythonhosted.org/packages/03/5f/6e2a7d80c353587751ef3d44bb947f0565ec008a2e0927821c007e96d3a7/greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7", size = 602132, upload-time = "2026-02-20T21:02:43.261Z" }, - { url = "https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", size = 591729, upload-time = "2026-02-20T20:20:58.395Z" }, - { url = "https://files.pythonhosted.org/packages/24/b4/21f5455773d37f94b866eb3cf5caed88d6cea6dd2c6e1f9c34f463cba3ec/greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", size = 1551946, upload-time = "2026-02-20T20:49:31.102Z" }, - { url = "https://files.pythonhosted.org/packages/00/68/91f061a926abead128fe1a87f0b453ccf07368666bd59ffa46016627a930/greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", size = 1618494, upload-time = "2026-02-20T20:21:06.541Z" }, - { url = "https://files.pythonhosted.org/packages/ac/78/f93e840cbaef8becaf6adafbaf1319682a6c2d8c1c20224267a5c6c8c891/greenlet-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f", size = 230092, upload-time = "2026-02-20T20:17:09.379Z" }, - { url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" }, - { url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" }, - { url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" }, - { url = "https://files.pythonhosted.org/packages/9c/8b/1430a04657735a3f23116c2e0d5eb10220928846e4537a938a41b350bed6/greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2", size = 605046, upload-time = "2026-02-20T21:02:45.234Z" }, - { url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" }, - { url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" }, - { url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3a/efb2cf697fbccdf75b24e2c18025e7dfa54c4f31fab75c51d0fe79942cef/greenlet-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5", size = 230389, upload-time = "2026-02-20T20:17:18.772Z" }, - { url = "https://files.pythonhosted.org/packages/e1/a1/65bbc059a43a7e2143ec4fc1f9e3f673e04f9c7b371a494a101422ac4fd5/greenlet-3.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd", size = 229645, upload-time = "2026-02-20T20:18:18.695Z" }, - { url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" }, - { url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" }, - { url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c5/cc09412a29e43406eba18d61c70baa936e299bc27e074e2be3806ed29098/greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb", size = 626250, upload-time = "2026-02-20T21:02:46.596Z" }, - { url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" }, - { url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" }, - { url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" }, - { url = "https://files.pythonhosted.org/packages/9b/40/cc802e067d02af8b60b6771cea7d57e21ef5e6659912814babb42b864713/greenlet-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f", size = 231081, upload-time = "2026-02-20T20:17:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/58/2e/fe7f36ff1982d6b10a60d5e0740c759259a7d6d2e1dc41da6d96de32fff6/greenlet-3.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643", size = 230331, upload-time = "2026-02-20T20:17:23.34Z" }, - { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, - { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, - { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, - { url = "https://files.pythonhosted.org/packages/94/2b/4d012a69759ac9d77210b8bfb128bc621125f5b20fc398bce3940d036b1c/greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd", size = 628268, upload-time = "2026-02-20T21:02:48.024Z" }, - { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, - { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, - { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, - { url = "https://files.pythonhosted.org/packages/91/39/5ef5aa23bc545aa0d31e1b9b55822b32c8da93ba657295840b6b34124009/greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124", size = 230961, upload-time = "2026-02-20T20:16:58.461Z" }, - { url = "https://files.pythonhosted.org/packages/62/6b/a89f8456dcb06becff288f563618e9f20deed8dd29beea14f9a168aef64b/greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327", size = 230221, upload-time = "2026-02-20T20:17:37.152Z" }, - { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, - { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ac/85804f74f1ccea31ba518dcc8ee6f14c79f73fe36fa1beba38930806df09/greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9", size = 675371, upload-time = "2026-02-20T21:02:49.664Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, - { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, - { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, - { url = "https://files.pythonhosted.org/packages/f3/ca/2101ca3d9223a1dc125140dbc063644dca76df6ff356531eb27bc267b446/greenlet-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492", size = 232034, upload-time = "2026-02-20T20:20:08.186Z" }, - { url = "https://files.pythonhosted.org/packages/f6/4a/ecf894e962a59dea60f04877eea0fd5724618da89f1867b28ee8b91e811f/greenlet-3.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71", size = 231437, upload-time = "2026-02-20T20:18:59.722Z" }, - { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, - { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, - { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, - { url = "https://files.pythonhosted.org/packages/d1/67/8197b7e7e602150938049d8e7f30de1660cfb87e4c8ee349b42b67bdb2e1/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf", size = 666581, upload-time = "2026-02-20T21:02:51.526Z" }, - { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, - { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, - { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, - { url = "https://files.pythonhosted.org/packages/29/4b/45d90626aef8e65336bed690106d1382f7a43665e2249017e9527df8823b/greenlet-3.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a", size = 237086, upload-time = "2026-02-20T20:20:45.786Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/86/94/a5935717b307d7c71fe877b52b884c6af707d2d2090db118a03fbd799369/greenlet-3.4.0.tar.gz", hash = "sha256:f50a96b64dafd6169e595a5c56c9146ef80333e67d4476a65a9c55f400fc22ff", size = 195913, upload-time = "2026-04-08T17:08:00.863Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/bc/e30e1e3d5e8860b0e0ce4d2b16b2681b77fd13542fc0d72f7e3c22d16eff/greenlet-3.4.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d18eae9a7fb0f499efcd146b8c9750a2e1f6e0e93b5a382b3481875354a430e6", size = 284315, upload-time = "2026-04-08T17:02:52.322Z" }, + { url = "https://files.pythonhosted.org/packages/5b/cc/e023ae1967d2a26737387cac083e99e47f65f58868bd155c4c80c01ec4e0/greenlet-3.4.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:636d2f95c309e35f650e421c23297d5011716be15d966e6328b367c9fc513a82", size = 601916, upload-time = "2026-04-08T16:24:35.533Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/5be1677954b6d8810b33abe94e3eb88726311c58fa777dc97e390f7caf5a/greenlet-3.4.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:234582c20af9742583c3b2ddfbdbb58a756cfff803763ffaae1ac7990a9fac31", size = 616399, upload-time = "2026-04-08T16:30:54.536Z" }, + { url = "https://files.pythonhosted.org/packages/82/0a/3a4af092b09ea02bcda30f33fd7db397619132fe52c6ece24b9363130d34/greenlet-3.4.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ac6a5f618be581e1e0713aecec8e54093c235e5fa17d6d8eb7ffc487e2300508", size = 621077, upload-time = "2026-04-08T16:40:34.946Z" }, + { url = "https://files.pythonhosted.org/packages/74/bf/2d58d5ea515704f83e34699128c9072a34bea27d2b6a556e102105fe62a5/greenlet-3.4.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:523677e69cd4711b5a014e37bc1fb3a29947c3e3a5bb6a527e1cc50312e5a398", size = 611978, upload-time = "2026-04-08T15:56:31.335Z" }, + { url = "https://files.pythonhosted.org/packages/8c/39/3786520a7d5e33ee87b3da2531f589a3882abf686a42a3773183a41ef010/greenlet-3.4.0-cp310-cp310-manylinux_2_39_riscv64.whl", hash = "sha256:d336d46878e486de7d9458653c722875547ac8d36a1cff9ffaf4a74a3c1f62eb", size = 416893, upload-time = "2026-04-08T16:43:02.392Z" }, + { url = "https://files.pythonhosted.org/packages/bd/69/6525049b6c179d8a923256304d8387b8bdd4acab1acf0407852463c6d514/greenlet-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b45e45fe47a19051a396abb22e19e7836a59ee6c5a90f3be427343c37908d65b", size = 1571957, upload-time = "2026-04-08T16:26:17.041Z" }, + { url = "https://files.pythonhosted.org/packages/4e/6c/bbfb798b05fec736a0d24dc23e81b45bcee87f45a83cfb39db031853bddc/greenlet-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5434271357be07f3ad0936c312645853b7e689e679e29310e2de09a9ea6c3adf", size = 1637223, upload-time = "2026-04-08T15:57:27.556Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7d/981fe0e7c07bd9d5e7eb18decb8590a11e3955878291f7a7de2e9c668eb7/greenlet-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:a19093fbad824ed7c0f355b5ff4214bffda5f1a7f35f29b31fcaa240cc0135ab", size = 237902, upload-time = "2026-04-08T17:03:14.16Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c6/dba32cab7e3a625b011aa5647486e2d28423a48845a2998c126dd69c85e1/greenlet-3.4.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:805bebb4945094acbab757d34d6e1098be6de8966009ab9ca54f06ff492def58", size = 285504, upload-time = "2026-04-08T15:52:14.071Z" }, + { url = "https://files.pythonhosted.org/packages/54/f4/7cb5c2b1feb9a1f50e038be79980dfa969aa91979e5e3a18fdbcfad2c517/greenlet-3.4.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:439fc2f12b9b512d9dfa681c5afe5f6b3232c708d13e6f02c845e0d9f4c2d8c6", size = 605476, upload-time = "2026-04-08T16:24:37.064Z" }, + { url = "https://files.pythonhosted.org/packages/d6/af/b66ab0b2f9a4c5a867c136bf66d9599f34f21a1bcca26a2884a29c450bd9/greenlet-3.4.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a70ed1cb0295bee1df57b63bf7f46b4e56a5c93709eea769c1fec1bb23a95875", size = 618336, upload-time = "2026-04-08T16:30:56.59Z" }, + { url = "https://files.pythonhosted.org/packages/6d/31/56c43d2b5de476f77d36ceeec436328533bff960a4cba9a07616e93063ab/greenlet-3.4.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c5696c42e6bb5cfb7c6ff4453789081c66b9b91f061e5e9367fa15792644e76", size = 625045, upload-time = "2026-04-08T16:40:37.111Z" }, + { url = "https://files.pythonhosted.org/packages/e5/5c/8c5633ece6ba611d64bf2770219a98dd439921d6424e4e8cf16b0ac74ea5/greenlet-3.4.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c660bce1940a1acae5f51f0a064f1bc785d07ea16efcb4bc708090afc4d69e83", size = 613515, upload-time = "2026-04-08T15:56:32.478Z" }, + { url = "https://files.pythonhosted.org/packages/80/ca/704d4e2c90acb8bdf7ae593f5cbc95f58e82de95cc540fb75631c1054533/greenlet-3.4.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:89995ce5ddcd2896d89615116dd39b9703bfa0c07b583b85b89bf1b5d6eddf81", size = 419745, upload-time = "2026-04-08T16:43:04.022Z" }, + { url = "https://files.pythonhosted.org/packages/a9/df/950d15bca0d90a0e7395eb777903060504cdb509b7b705631e8fb69ff415/greenlet-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee407d4d1ca9dc632265aee1c8732c4a2d60adff848057cdebfe5fe94eb2c8a2", size = 1574623, upload-time = "2026-04-08T16:26:18.596Z" }, + { url = "https://files.pythonhosted.org/packages/1a/e7/0839afab829fcb7333c9ff6d80c040949510055d2d4d63251f0d1c7c804e/greenlet-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:956215d5e355fffa7c021d168728321fd4d31fd730ac609b1653b450f6a4bc71", size = 1639579, upload-time = "2026-04-08T15:57:29.231Z" }, + { url = "https://files.pythonhosted.org/packages/d9/2b/b4482401e9bcaf9f5c97f67ead38db89c19520ff6d0d6699979c6efcc200/greenlet-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:5cb614ace7c27571270354e9c9f696554d073f8aa9319079dcba466bbdead711", size = 238233, upload-time = "2026-04-08T17:02:54.286Z" }, + { url = "https://files.pythonhosted.org/packages/0c/4d/d8123a4e0bcd583d5cfc8ddae0bbe29c67aab96711be331a7cc935a35966/greenlet-3.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:04403ac74fe295a361f650818de93be11b5038a78f49ccfb64d3b1be8fbf1267", size = 235045, upload-time = "2026-04-08T17:04:05.072Z" }, + { url = "https://files.pythonhosted.org/packages/65/8b/3669ad3b3f247a791b2b4aceb3aa5a31f5f6817bf547e4e1ff712338145a/greenlet-3.4.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:1a54a921561dd9518d31d2d3db4d7f80e589083063ab4d3e2e950756ef809e1a", size = 286902, upload-time = "2026-04-08T15:52:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/38/3e/3c0e19b82900873e2d8469b590a6c4b3dfd2b316d0591f1c26b38a4879a5/greenlet-3.4.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16dec271460a9a2b154e3b1c2fa1050ce6280878430320e85e08c166772e3f97", size = 606099, upload-time = "2026-04-08T16:24:38.408Z" }, + { url = "https://files.pythonhosted.org/packages/b5/33/99fef65e7754fc76a4ed14794074c38c9ed3394a5bd129d7f61b705f3168/greenlet-3.4.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90036ce224ed6fe75508c1907a77e4540176dcf0744473627785dd519c6f9996", size = 618837, upload-time = "2026-04-08T16:30:58.298Z" }, + { url = "https://files.pythonhosted.org/packages/44/57/eae2cac10421feae6c0987e3dc106c6d86262b1cb379e171b017aba893a6/greenlet-3.4.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6f0def07ec9a71d72315cf26c061aceee53b306c36ed38c35caba952ea1b319d", size = 624901, upload-time = "2026-04-08T16:40:38.981Z" }, + { url = "https://files.pythonhosted.org/packages/36/f7/229f3aed6948faa20e0616a0b8568da22e365ede6a54d7d369058b128afd/greenlet-3.4.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1c4f6b453006efb8310affb2d132832e9bbb4fc01ce6df6b70d810d38f1f6dc", size = 615062, upload-time = "2026-04-08T15:56:33.766Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8a/0e73c9b94f31d1cc257fe79a0eff621674141cdae7d6d00f40de378a1e42/greenlet-3.4.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:0e1254cf0cbaa17b04320c3a78575f29f3c161ef38f59c977108f19ffddaf077", size = 423927, upload-time = "2026-04-08T16:43:05.293Z" }, + { url = "https://files.pythonhosted.org/packages/08/97/d988180011aa40135c46cd0d0cf01dd97f7162bae14139b4a3ef54889ba5/greenlet-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b2d9a138ffa0e306d0e2b72976d2fb10b97e690d40ab36a472acaab0838e2de", size = 1573511, upload-time = "2026-04-08T16:26:20.058Z" }, + { url = "https://files.pythonhosted.org/packages/d4/0f/a5a26fe152fb3d12e6a474181f6e9848283504d0afd095f353d85726374b/greenlet-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8424683caf46eb0eb6f626cb95e008e8cc30d0cb675bdfa48200925c79b38a08", size = 1640396, upload-time = "2026-04-08T15:57:30.88Z" }, + { url = "https://files.pythonhosted.org/packages/42/cf/bb2c32d9a100e36ee9f6e38fad6b1e082b8184010cb06259b49e1266ca01/greenlet-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0a53fb071531d003b075c444014ff8f8b1a9898d36bb88abd9ac7b3524648a2", size = 238892, upload-time = "2026-04-08T17:03:10.094Z" }, + { url = "https://files.pythonhosted.org/packages/b7/47/6c41314bac56e71436ce551c7fbe3cc830ed857e6aa9708dbb9c65142eb6/greenlet-3.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:f38b81880ba28f232f1f675893a39cf7b6db25b31cc0a09bb50787ecf957e85e", size = 235599, upload-time = "2026-04-08T15:52:54.3Z" }, + { url = "https://files.pythonhosted.org/packages/7a/75/7e9cd1126a1e1f0cd67b0eda02e5221b28488d352684704a78ed505bd719/greenlet-3.4.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:43748988b097f9c6f09364f260741aa73c80747f63389824435c7a50bfdfd5c1", size = 285856, upload-time = "2026-04-08T15:52:45.82Z" }, + { url = "https://files.pythonhosted.org/packages/9d/c4/3e2df392e5cb199527c4d9dbcaa75c14edcc394b45040f0189f649631e3c/greenlet-3.4.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5566e4e2cd7a880e8c27618e3eab20f3494452d12fd5129edef7b2f7aa9a36d1", size = 610208, upload-time = "2026-04-08T16:24:39.674Z" }, + { url = "https://files.pythonhosted.org/packages/da/af/750cdfda1d1bd30a6c28080245be8d0346e669a98fdbae7f4102aa95fff3/greenlet-3.4.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1054c5a3c78e2ab599d452f23f7adafef55062a783a8e241d24f3b633ba6ff82", size = 621269, upload-time = "2026-04-08T16:30:59.767Z" }, + { url = "https://files.pythonhosted.org/packages/e0/93/c8c508d68ba93232784bbc1b5474d92371f2897dfc6bc281b419f2e0d492/greenlet-3.4.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:98eedd1803353daf1cd9ef23eef23eda5a4d22f99b1f998d273a8b78b70dd47f", size = 628455, upload-time = "2026-04-08T16:40:40.698Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/0cbc693622cd54ebe25207efbb3a0eb07c2639cb8594f6e3aaaa0bb077a8/greenlet-3.4.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f82cb6cddc27dd81c96b1506f4aa7def15070c3b2a67d4e46fd19016aacce6cf", size = 617549, upload-time = "2026-04-08T15:56:34.893Z" }, + { url = "https://files.pythonhosted.org/packages/7f/46/cfaaa0ade435a60550fd83d07dfd5c41f873a01da17ede5c4cade0b9bab8/greenlet-3.4.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:b7857e2202aae67bc5725e0c1f6403c20a8ff46094ece015e7d474f5f7020b55", size = 426238, upload-time = "2026-04-08T16:43:06.865Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c0/8966767de01343c1ff47e8b855dc78e7d1a8ed2b7b9c83576a57e289f81d/greenlet-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:227a46251ecba4ff46ae742bc5ce95c91d5aceb4b02f885487aff269c127a729", size = 1575310, upload-time = "2026-04-08T16:26:21.671Z" }, + { url = "https://files.pythonhosted.org/packages/b8/38/bcdc71ba05e9a5fda87f63ffc2abcd1f15693b659346df994a48c968003d/greenlet-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5b99e87be7eba788dd5b75ba1cde5639edffdec5f91fe0d734a249535ec3408c", size = 1640435, upload-time = "2026-04-08T15:57:32.572Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c2/19b664b7173b9e4ef5f77e8cef9f14c20ec7fce7920dc1ccd7afd955d093/greenlet-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:849f8bc17acd6295fcb5de8e46d55cc0e52381c56eaf50a2afd258e97bc65940", size = 238760, upload-time = "2026-04-08T17:04:03.878Z" }, + { url = "https://files.pythonhosted.org/packages/9b/96/795619651d39c7fbd809a522f881aa6f0ead504cc8201c3a5b789dfaef99/greenlet-3.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9390ad88b652b1903814eaabd629ca184db15e0eeb6fe8a390bbf8b9106ae15a", size = 235498, upload-time = "2026-04-08T17:05:00.584Z" }, + { url = "https://files.pythonhosted.org/packages/78/02/bde66806e8f169cf90b14d02c500c44cdbe02c8e224c9c67bafd1b8cadd1/greenlet-3.4.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:10a07aca6babdd18c16a3f4f8880acfffc2b88dfe431ad6aa5f5740759d7d75e", size = 286291, upload-time = "2026-04-08T17:09:34.307Z" }, + { url = "https://files.pythonhosted.org/packages/05/1f/39da1c336a87d47c58352fb8a78541ce63d63ae57c5b9dae1fe02801bbc2/greenlet-3.4.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:076e21040b3a917d3ce4ad68fb5c3c6b32f1405616c4a57aa83120979649bd3d", size = 656749, upload-time = "2026-04-08T16:24:41.721Z" }, + { url = "https://files.pythonhosted.org/packages/d3/6c/90ee29a4ee27af7aa2e2ec408799eeb69ee3fcc5abcecac6ddd07a5cd0f2/greenlet-3.4.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e82689eea4a237e530bb5cb41b180ef81fa2160e1f89422a67be7d90da67f615", size = 669084, upload-time = "2026-04-08T16:31:01.372Z" }, + { url = "https://files.pythonhosted.org/packages/d2/4a/74078d3936712cff6d3c91a930016f476ce4198d84e224fe6d81d3e02880/greenlet-3.4.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:06c2d3b89e0c62ba50bd7adf491b14f39da9e7e701647cb7b9ff4c99bee04b19", size = 673405, upload-time = "2026-04-08T16:40:42.527Z" }, + { url = "https://files.pythonhosted.org/packages/07/49/d4cad6e5381a50947bb973d2f6cf6592621451b09368b8c20d9b8af49c5b/greenlet-3.4.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4df3b0b2289ec686d3c821a5fee44259c05cfe824dd5e6e12c8e5f5df23085cf", size = 665621, upload-time = "2026-04-08T15:56:35.995Z" }, + { url = "https://files.pythonhosted.org/packages/79/3e/df8a83ab894751bc31e1106fdfaa80ca9753222f106b04de93faaa55feb7/greenlet-3.4.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:070b8bac2ff3b4d9e0ff36a0d19e42103331d9737e8504747cd1e659f76297bd", size = 471670, upload-time = "2026-04-08T16:43:08.512Z" }, + { url = "https://files.pythonhosted.org/packages/37/31/d1edd54f424761b5d47718822f506b435b6aab2f3f93b465441143ea5119/greenlet-3.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8bff29d586ea415688f4cec96a591fcc3bf762d046a796cdadc1fdb6e7f2d5bf", size = 1622259, upload-time = "2026-04-08T16:26:23.201Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c6/6d3f9cdcb21c4e12a79cb332579f1c6aa1af78eb68059c5a957c7812d95e/greenlet-3.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8a569c2fb840c53c13a2b8967c63621fafbd1a0e015b9c82f408c33d626a2fda", size = 1686916, upload-time = "2026-04-08T15:57:34.282Z" }, + { url = "https://files.pythonhosted.org/packages/63/45/c1ca4a1ad975de4727e52d3ffe641ae23e1d7a8ffaa8ff7a0477e1827b92/greenlet-3.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:207ba5b97ea8b0b60eb43ffcacf26969dd83726095161d676aac03ff913ee50d", size = 239821, upload-time = "2026-04-08T17:03:48.423Z" }, + { url = "https://files.pythonhosted.org/packages/71/c4/6f621023364d7e85a4769c014c8982f98053246d142420e0328980933ceb/greenlet-3.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:f8296d4e2b92af34ebde81085a01690f26a51eb9ac09a0fcadb331eb36dbc802", size = 236932, upload-time = "2026-04-08T17:04:33.551Z" }, + { url = "https://files.pythonhosted.org/packages/d4/8f/18d72b629783f5e8d045a76f5325c1e938e659a9e4da79c7dcd10169a48d/greenlet-3.4.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d70012e51df2dbbccfaf63a40aaf9b40c8bed37c3e3a38751c926301ce538ece", size = 294681, upload-time = "2026-04-08T15:52:35.778Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ad/5fa86ec46769c4153820d58a04062285b3b9e10ba3d461ee257b68dcbf53/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a58bec0751f43068cd40cff31bb3ca02ad6000b3a51ca81367af4eb5abc480c8", size = 658899, upload-time = "2026-04-08T16:24:43.32Z" }, + { url = "https://files.pythonhosted.org/packages/43/f0/4e8174ca0e87ae748c409f055a1ba161038c43cc0a5a6f1433a26ac2e5bf/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05fa0803561028f4b2e3b490ee41216a842eaee11aed004cc343a996d9523aa2", size = 665284, upload-time = "2026-04-08T16:31:02.833Z" }, + { url = "https://files.pythonhosted.org/packages/ef/92/466b0d9afd44b8af623139a3599d651c7564fa4152f25f117e1ee5949ffb/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c4cd56a9eb7a6444edbc19062f7b6fbc8f287c663b946e3171d899693b1c19fa", size = 665872, upload-time = "2026-04-08T16:40:43.912Z" }, + { url = "https://files.pythonhosted.org/packages/19/da/991cf7cd33662e2df92a1274b7eb4d61769294d38a1bba8a45f31364845e/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e60d38719cb80b3ab5e85f9f1aed4960acfde09868af6762ccb27b260d68f4ed", size = 661861, upload-time = "2026-04-08T15:56:37.269Z" }, + { url = "https://files.pythonhosted.org/packages/0d/14/3395a7ef3e260de0325152ddfe19dffb3e49fe10873b94654352b53ad48e/greenlet-3.4.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:1f85f204c4d54134ae850d401fa435c89cd667d5ce9dc567571776b45941af72", size = 489237, upload-time = "2026-04-08T16:43:09.993Z" }, + { url = "https://files.pythonhosted.org/packages/36/c5/6c2c708e14db3d9caea4b459d8464f58c32047451142fe2cfd90e7458f41/greenlet-3.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7f50c804733b43eded05ae694691c9aa68bca7d0a867d67d4a3f514742a2d53f", size = 1622182, upload-time = "2026-04-08T16:26:24.777Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4c/50c5fed19378e11a29fabab1f6be39ea95358f4a0a07e115a51ca93385d8/greenlet-3.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2d4f0635dc4aa638cda4b2f5a07ae9a2cff9280327b581a3fcb6f317b4fbc38a", size = 1685050, upload-time = "2026-04-08T15:57:36.453Z" }, + { url = "https://files.pythonhosted.org/packages/db/72/85ae954d734703ab48e622c59d4ce35d77ce840c265814af9c078cacc7aa/greenlet-3.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1a4a48f24681300c640f143ba7c404270e1ebbbcf34331d7104a4ff40f8ea705", size = 245554, upload-time = "2026-04-08T17:03:50.044Z" }, ] [[package]] name = "gremlinpython" -version = "3.8.0" +version = "3.8.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aenum" }, @@ -12364,9 +12366,9 @@ dependencies = [ { name = "isodate" }, { name = "nest-asyncio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3b/43/fb7de8d7a6229099fda0793c808a86f232914aaa80768c6e8579d22305a8/gremlinpython-3.8.0.tar.gz", hash = "sha256:e4389f20dfc4429ebf5d5512e78832ccdde6df04b34c232d02315cd4a81cef11", size = 54619, upload-time = "2025-11-17T23:15:27.479Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5d/56/8867126fc3383ba2aea606e54079353d15568508cf7c60255f727780be8c/gremlinpython-3.8.1.tar.gz", hash = "sha256:23ad0ed694d63ef57611a04d3c648cc6bf05e86678959b6b6d921e83c48fd1f8", size = 53968, upload-time = "2026-04-07T00:22:20.144Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/8b/d1daa2d0cc0413101a690ba0ff6dfe259d163c8457cdc1d0246c399e743c/gremlinpython-3.8.0-py3-none-any.whl", hash = "sha256:e3b5d2340ec6da771b9505d5bcba435495979c6fce0872ba53a909a3ff0d5f41", size = 75905, upload-time = "2025-11-17T23:15:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/a4/55/f6adf83dd74563aca7721d456b1d33d7656448e29cc79a6aede3bb6ffa5b/gremlinpython-3.8.1-py3-none-any.whl", hash = "sha256:2e8136f9ea8cd771f9cc6f86f4ce73130595aed414a363534e1a4e18bfa81427", size = 75457, upload-time = "2026-04-07T00:22:18.776Z" }, ] [[package]] @@ -12839,7 +12841,7 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.9.0" +version = "1.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, @@ -12852,9 +12854,9 @@ dependencies = [ { name = "typer" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/bb/62c7aa86f63a05e2f9b96642fdef9b94526a23979820b09f5455deff4983/huggingface_hub-1.9.0.tar.gz", hash = "sha256:0ea5be7a56135c91797cae6ad726e38eaeb6eb4b77cefff5c9d38ba0ecf874f7", size = 750326, upload-time = "2026-04-03T08:35:55.888Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/28/baf5d745559503ce8d28cf5bc9551f5ac59158eafd7b6a6afff0bcdb0f50/huggingface_hub-1.10.1.tar.gz", hash = "sha256:696c53cf9c2ac9befbfb5dd41d05392a031c69fc6930d1ed9671debd405b6fff", size = 758094, upload-time = "2026-04-09T15:01:18.928Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/73/37/0d15d16150e1829f3e90962c99f28257f6de9e526a680b4c6f5acdb54fd2/huggingface_hub-1.9.0-py3-none-any.whl", hash = "sha256:2999328c058d39fd19ab748dd09bd4da2fbaa4f4c1ddea823eab103051e14a1f", size = 637355, upload-time = "2026-04-03T08:35:53.897Z" }, + { url = "https://files.pythonhosted.org/packages/83/8c/c7a33f3efaa8d6a5bc40e012e5ecc2d72c2e6124550ca9085fe0ceed9993/huggingface_hub-1.10.1-py3-none-any.whl", hash = "sha256:6b981107a62fbe68c74374418983399c632e35786dcd14642a9f2972633c8b5a", size = 642630, upload-time = "2026-04-09T15:01:17.35Z" }, ] [[package]] @@ -13563,36 +13565,43 @@ wheels = [ [[package]] name = "jpype1" -version = "1.6.0" +version = "1.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/34/49/6090a131d84b22c6aae13b1853092028b060fd17da1af87c0e42ad69d50f/jpype1-1.6.0.tar.gz", hash = "sha256:2d46b2a14f8f0e6f17d8aa22b4fc3a64b2790851ebf1409ad79a37c698fd6e9a", size = 1057888, upload-time = "2025-07-07T14:04:11.244Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/95/524c67e2aafa301d6ffd21747847c5e9c9785ff8b39d90275ead2877dd0c/jpype1-1.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:533cf7ced58a4b74272f3d1e962fe33f305184d2fcb3856ca79867d5b6f0fb8b", size = 583402, upload-time = "2025-07-07T13:50:13.487Z" }, - { url = "https://files.pythonhosted.org/packages/13/61/88288a341292d3b76967587e59b674b5445678dcf60e8c921507bd70baa6/jpype1-1.6.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:597063698c074e5bf34e696626423a528cdf099989e22a837e889a0d671fd9e4", size = 468810, upload-time = "2025-07-07T13:50:16.967Z" }, - { url = "https://files.pythonhosted.org/packages/08/ed/18a16c6ae0ac5978fe93ad5c265719a311a613ba3dd4d96bd89e93fd2444/jpype1-1.6.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2f0cd698d160ba825952393b4d87911e7eedcbf5af381bb6438126de863f66b6", size = 512880, upload-time = "2025-07-07T13:50:20.451Z" }, - { url = "https://files.pythonhosted.org/packages/e2/da/9854e41f4b301a52210254d24d5d62792e0700527f7940445d763d0d64c6/jpype1-1.6.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fcabb8cce3be16528bd26e4b73e41d7b8c778111f14de52c33c25e2a9d4c9a9f", size = 496509, upload-time = "2025-07-07T13:50:24.541Z" }, - { url = "https://files.pythonhosted.org/packages/74/85/2975be78a88678c9048d39141f39f1ced1b55e937e7854bfd824282ee176/jpype1-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f02c419d6cdd45ed5576d95f0ab4732371c760ba4b01ea9bd646b98b3c21a16f", size = 356591, upload-time = "2025-07-07T13:50:26.994Z" }, - { url = "https://files.pythonhosted.org/packages/7c/ff/688b8ecbce3c4fa8ee34bc364d447f372d2dcc9597742e7331a328b07f20/jpype1-1.6.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:40b523e11b22398a8ddb777f1e6e8d55108a631311f35b48b0ed0f4c9198d025", size = 583485, upload-time = "2025-07-07T13:50:29.366Z" }, - { url = "https://files.pythonhosted.org/packages/4b/2a/997c0381028998522ef9103a1730be40eee2c8eb5ca244a295f9d5c6a6e2/jpype1-1.6.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ae5927e441894d41b65e08390a0ea6a6512fe222c07aa33fbab623512092fdbd", size = 468977, upload-time = "2025-07-07T13:50:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/2d/f9/e3b0a467b3ac2c4eeac5ca57764bf49a859b10f08f43e5179e1a283d2a9b/jpype1-1.6.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9d85c2077172a32dd8ffde8711cb57c5bc351378ceb44dd8c3bdd80f27fa8caf", size = 512946, upload-time = "2025-07-07T13:50:33.452Z" }, - { url = "https://files.pythonhosted.org/packages/b2/b4/1167be1572704fc365f31038a862afae26dda5006c7f4178f44c27779e37/jpype1-1.6.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f5a02cbba4022a0aa47ee617bc12349457988c653491484a988dc8f4e6269dfc", size = 496609, upload-time = "2025-07-07T13:50:35.631Z" }, - { url = "https://files.pythonhosted.org/packages/25/a9/3ed33c24c86d234cb6fd5c6701b64f0a39ed4fd63fd5bd45ad8ce6ac72d9/jpype1-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:966daa892e6cd9ec3b2b92fd7a6d572687b29021e6d28fb73995a62ddd0a11eb", size = 356597, upload-time = "2025-07-07T13:50:37.54Z" }, - { url = "https://files.pythonhosted.org/packages/38/88/2156a27251492169f947850293d9870d49d784f1355fad7e920095636721/jpype1-1.6.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5454322887505097c46f41521becf31cda2303f54e35cb42e20f1a180055a558", size = 582187, upload-time = "2025-07-07T13:50:39.034Z" }, - { url = "https://files.pythonhosted.org/packages/6b/5d/51bde8695cc3eabcc465779f6dc23b149194bbcdcb8d221a9572422053f4/jpype1-1.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cf646459023a0dd71b3cc3aeeb977225a93f94c97839bb4e6146977b166c7caf", size = 468341, upload-time = "2025-07-07T13:50:40.739Z" }, - { url = "https://files.pythonhosted.org/packages/7a/a1/50cdc2bf9e51c0828faabec6fad50d61aada5a57d0bc435f4db0c16eb2ca/jpype1-1.6.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:7a98b34bc68a117881382dffa9b02d5e1d0d94325f85d7f564c33cc9e9d2916b", size = 511724, upload-time = "2025-07-07T13:50:42.479Z" }, - { url = "https://files.pythonhosted.org/packages/c4/a4/6038228e44cbcdb8f96ff2518cd6c577730f31fb62e9f46de7efdfabc2de/jpype1-1.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b56d7b662ce353c7f876e9ff3d4e775918348340795801e1f00c3b6241006264", size = 495897, upload-time = "2025-07-07T13:50:44.018Z" }, - { url = "https://files.pythonhosted.org/packages/8c/e4/af69d43779da0e49d37d7fd8a4a01bede03f6a3bab450eab1c10cf48e20e/jpype1-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf41134bc59c28de2721614ed00a34f76f69f2b525583a5c42fee5c7bae05d40", size = 355702, upload-time = "2025-07-07T13:50:45.368Z" }, - { url = "https://files.pythonhosted.org/packages/3f/1b/7167cfb702cfbcb17b0973150608f9cb92c3f409ebaaff655f7389617766/jpype1-1.6.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ce1da9ff01010a4529de194aecc053bfc8ab25440ea6b63579ef8c8d381da21d", size = 582384, upload-time = "2025-07-07T13:50:47.418Z" }, - { url = "https://files.pythonhosted.org/packages/c0/48/8ae425d8842bc76eb51052bbea5941dac230c8f6b58614ef2b7cb2da1a74/jpype1-1.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4a387430cd4f3f68761013dca7f71b79d8d64b47dfd56eedcbd44c894d98d7f2", size = 468237, upload-time = "2025-07-07T13:50:48.925Z" }, - { url = "https://files.pythonhosted.org/packages/ef/2f/dbdc15aa99404dda0315a9883add7422c9ac7acce28ce24b66c89052c2fb/jpype1-1.6.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:6c9d99f41a5d05a8a2b6aeda796f646904c1c2b68aed0cc9a3bbc165483d9e1e", size = 511905, upload-time = "2025-07-07T13:50:50.87Z" }, - { url = "https://files.pythonhosted.org/packages/00/0d/50fcdd6d3bb42a87cbda8b04fc72283a9c6d955ada0d011190ce31e0e027/jpype1-1.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:55ba7257988a69bee84f7cd1444131725d5447999149fdafdba25bf46e4b1a3f", size = 496001, upload-time = "2025-07-07T13:50:52.711Z" }, - { url = "https://files.pythonhosted.org/packages/4f/b8/25214a9ebecbd31447b685500dca5fe2ac070df38358d6823f591a8ce52e/jpype1-1.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:ef8dd72442d91cde7e5eefef24ab71323cdd4137283a59f79d265a6620f7d0ab", size = 355727, upload-time = "2025-07-07T13:51:00.402Z" }, - { url = "https://files.pythonhosted.org/packages/29/a0/b2347572998020de8ce3ee0a285a1b84b052b522e8d452ee9ad330570918/jpype1-1.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:dc0c1c8b989b9857f87648980a746084b323858b0450225eab3642bb674645d6", size = 471150, upload-time = "2025-07-07T13:50:54.254Z" }, - { url = "https://files.pythonhosted.org/packages/7c/62/5e0f64a185f37303d0dd07e7b7a927cd5237fdc3c8176add949ed8cafaa2/jpype1-1.6.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cbbba16381ccd23530ad4ef09f7b2b1b12bd7fd0f6ca9fe4c7b4e3da8fe4cf63", size = 514015, upload-time = "2025-07-07T13:50:56.299Z" }, - { url = "https://files.pythonhosted.org/packages/72/68/84050ed2679e2d2ee2030a60d3e5a59a29d0533cd03fd8d9891e36592b0f/jpype1-1.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1a3814e4f65d67e36bdb03b8851d5ece8d7a408aa3a24251ea0609bb8fba77dd", size = 497229, upload-time = "2025-07-07T13:50:57.842Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/ff/b3/a95951c2d967ca5e61f50d96549f528193315c2e2f38817bfbe214cc162d/jpype1-1.7.0.tar.gz", hash = "sha256:2109138b7264f6360c717b887b6a4d20b29e997c516e8d7fa8756e40595bb537", size = 782128, upload-time = "2026-04-09T22:18:53.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/4c/0ac784fe2ef4dce88cda18969d08dd584709279861367b79d0738a9bda9c/jpype1-1.7.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:fffa7228d25efd00ff75df5192d69ec8674d2aaa51b48e60871bc07bb151afb0", size = 375246, upload-time = "2026-04-09T22:17:57.324Z" }, + { url = "https://files.pythonhosted.org/packages/20/55/a06cb7fdc9b025b203fdd9ade1f5b649e743f02dce0806cd93aa7bbda32b/jpype1-1.7.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b109abef2dc94f159828f15e161a83ef2243ca45a0c23c311de7679e62bd664", size = 407739, upload-time = "2026-04-09T22:17:59.713Z" }, + { url = "https://files.pythonhosted.org/packages/79/93/4101a487aece26cac567b23daca9627876d459e46486b79649254f8d47c8/jpype1-1.7.0-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:51275f9f25cd431bec65aaa752806521e3abd19ad3ac29e1de35ec216697e615", size = 454431, upload-time = "2026-04-09T22:18:01.561Z" }, + { url = "https://files.pythonhosted.org/packages/32/f5/5005e0ca4b222bfdd7e24814dbfbb6b6a0b93b65a21506e7ed79a3134c2f/jpype1-1.7.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1baea397292698579d69207df1b23f4261c6814c90f91081359f4aff958b804", size = 438987, upload-time = "2026-04-09T22:18:03.425Z" }, + { url = "https://files.pythonhosted.org/packages/df/0c/51bd6e0ec919bcadca0074e6e90c5b725e6989f3d00d809c5175d160261f/jpype1-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:280fe6aecf086c1d311dff008c1b0129d7197940a6871ea845dc6a5f8b3319a0", size = 357687, upload-time = "2026-04-09T22:18:05.035Z" }, + { url = "https://files.pythonhosted.org/packages/78/c8/9613746ac28b4a1c5ec3871b9e56297493ac586d56c61b93724fc1a0cd36/jpype1-1.7.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:83486bd4629f40386ae6557311e7baca89bb9f2b70c2210d16bcdfafe1ac812c", size = 375265, upload-time = "2026-04-09T22:18:07.084Z" }, + { url = "https://files.pythonhosted.org/packages/46/05/4052f15ce9d5d8a82a9a8537454119acfaf6dfcc42595f75ca6a366bf227/jpype1-1.7.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b248d080a3a95249a2aad3ce53f9b56f84916d1bdc01df18b06c152deb12b8d", size = 407735, upload-time = "2026-04-09T22:18:09.641Z" }, + { url = "https://files.pythonhosted.org/packages/66/bd/a75f8309d98efebd4dfea57c4009d0f86834dac4eeaa8bd6d2c9db37b468/jpype1-1.7.0-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:9198e7a87f6afd7c6953df23ea0eab424b0a30ec103ca91104082b075e0e11c5", size = 454398, upload-time = "2026-04-09T22:18:11.871Z" }, + { url = "https://files.pythonhosted.org/packages/13/21/63fea3b7b18c929c85ab29b6b5cafc9909f6fca8361b4442b26da177f87f/jpype1-1.7.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b042813690e68cec1611e10982bf3e496cf47754e681abd8c3342be0aa97a802", size = 438963, upload-time = "2026-04-09T22:18:13.764Z" }, + { url = "https://files.pythonhosted.org/packages/cf/5d/d6331ad2350f10451cb9082ea3cf0dee63be2e7246c74998a9de57e3fdc6/jpype1-1.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:1d1f5b67eade4ef21e0e9f184034e47aee1e349eebb55ab97078219a50cf1e9c", size = 357721, upload-time = "2026-04-09T22:18:15.499Z" }, + { url = "https://files.pythonhosted.org/packages/39/87/7512ac8d3d2499f8fb23611d6d870189da609683239e50fa961ea82edf0a/jpype1-1.7.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:ce9a4addeb0494da774ae5ef7284f1f2eb52e05842d6700aa21988e2b50b2b88", size = 374171, upload-time = "2026-04-09T22:18:17.731Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9e/2544fabe521f969258bb532bc82d54cf2d799c5d93fd97f7453496ff3936/jpype1-1.7.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10d81fe60d4c37b3dc175e3ca2a08b7f655f8854d117a74d190e66f10833adcc", size = 406974, upload-time = "2026-04-09T22:18:19.896Z" }, + { url = "https://files.pythonhosted.org/packages/0f/f2/03763b0e7ff5038307a919c4bcd629fba398f48472876b974db7d7f5a31e/jpype1-1.7.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:e3c4befd919f05e23e0a4245af2bc188771bc8daff5041d544ae29f467976a29", size = 453801, upload-time = "2026-04-09T22:18:21.706Z" }, + { url = "https://files.pythonhosted.org/packages/37/d5/56214f4a93943d6786e7b024b8c07cfbc36df20c79ed520bf1db0053c780/jpype1-1.7.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ee5d72fee3b39e2e339adf3c4344d01d4473e10fbc4a3bb7d79ac06a8426da0", size = 437982, upload-time = "2026-04-09T22:18:23.58Z" }, + { url = "https://files.pythonhosted.org/packages/8e/d1/64671f546467ba3733f7824d9728d03a563024a83ee6037a8b0a4c255710/jpype1-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:22ddcf4b8616b3ef54ac666a484f8238a921ab3f435d066de724a9705c2eeb84", size = 356788, upload-time = "2026-04-09T22:18:25.606Z" }, + { url = "https://files.pythonhosted.org/packages/43/8d/1c15575ae2d3a5e7da2515886b4c411eef3a4f079003e1fdbb5b5a8052c4/jpype1-1.7.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:74d6a88a84f0ad44f5962119a3e9c7876bfed2b5385804ff1f755620849b5aaf", size = 374362, upload-time = "2026-04-09T22:18:27.174Z" }, + { url = "https://files.pythonhosted.org/packages/4b/e7/c1259ad95eaa29385d1407d8dc8ccff063de5cdb8054445ee7c4b2f77321/jpype1-1.7.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:783251ea09387efb490405ffeeccde167b30f12375f94ffc5db0ccb79f276a25", size = 407130, upload-time = "2026-04-09T22:18:29.42Z" }, + { url = "https://files.pythonhosted.org/packages/5a/4e/65220f2e27df18c1f8696343436a9e3645beaee073f80c4a17fa8fd542ac/jpype1-1.7.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:28bbcf8532cfe71507d2ec4416f7387db7d7ee631ddf820e8c6ad559167d9abb", size = 453893, upload-time = "2026-04-09T22:18:31.257Z" }, + { url = "https://files.pythonhosted.org/packages/a0/00/5991cbdf56898459f79817c0d91f1957c094d0805c0815e26c38f8fc39b3/jpype1-1.7.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b9b22b58becd92cc899a88298a5b06b001a1988147c37c4fee503415a7cb5539", size = 438095, upload-time = "2026-04-09T22:18:33.393Z" }, + { url = "https://files.pythonhosted.org/packages/57/11/5524a0d2f5f5121b0ba52f93bf78043a7c7fc7d3a8d6a2bab55a84e2d7cd/jpype1-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:b1284f524e96abaa0421172ab74640d1e131583d95df083d7c91173ff83253f9", size = 356829, upload-time = "2026-04-09T22:18:40.228Z" }, + { url = "https://files.pythonhosted.org/packages/41/1a/bf230eb769515030d53cb06b8adc665ae40f43a4b6dff51985c9a8859387/jpype1-1.7.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ecd3b126139397f6cdd0f2f1cf7638d8da09de35878c12f36dd3690b0ad02ff", size = 409188, upload-time = "2026-04-09T22:18:35.244Z" }, + { url = "https://files.pythonhosted.org/packages/8d/68/48afb91d0ed5e1695eead9b1c30c5a6fbd13e050ceee8004d0984d219a9b/jpype1-1.7.0-cp313-cp313t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:a1197341ed17b120a0f09d2e2c5d6877ede67e6f37defa06e12f904d5136b931", size = 455092, upload-time = "2026-04-09T22:18:37.08Z" }, + { url = "https://files.pythonhosted.org/packages/a0/62/b04fdf72d0e513112e47a7da1f0f3e8d515a1917f752b1eda1ca64c124fa/jpype1-1.7.0-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ec3e8389269c070615546e02493da031c8c85bbf3f20949db9183ea0fa6c4ffe", size = 439030, upload-time = "2026-04-09T22:18:38.557Z" }, + { url = "https://files.pythonhosted.org/packages/1e/1c/b05f0ae377f92185adfca3fc74a3ca812eccdf274b64887243af8067d515/jpype1-1.7.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3089236c91374eb8daffa9831a9a6462ccd3d8ed0e15c679ba9d3ea438cd773f", size = 407041, upload-time = "2026-04-09T22:18:41.69Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b3/f8384822924119005c64f395e253da3c1ff7ec5a40cd96736e9ccb255df7/jpype1-1.7.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:cc17dc8ea5440e21240b96f0b1c685bdc7bbafc26034af95d124ba908399bc4e", size = 453713, upload-time = "2026-04-09T22:18:43.647Z" }, + { url = "https://files.pythonhosted.org/packages/00/8d/afff4cfc97a69a1d526428523ad2ce053f9d24cdff037657ea87d1a45d11/jpype1-1.7.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85b3407edef65e87cf9c80b5eec418c14fff2f9b3f875447e9b2507bb41c4736", size = 437928, upload-time = "2026-04-09T22:18:45.568Z" }, + { url = "https://files.pythonhosted.org/packages/35/83/b2fed1864e908cd59a4d81bb7c9a06e4ce5bd3b39adb0d1ba14743ada8ac/jpype1-1.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:ee19bff59b206f52a9325dd77236ec8edda26154504356d1fa489cf70f53e30e", size = 364238, upload-time = "2026-04-09T22:18:52.115Z" }, + { url = "https://files.pythonhosted.org/packages/89/b1/eaa05a8fd170aa2a4605a5672e84d72acc95b9db297f8c8c7fca39d9e9ad/jpype1-1.7.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:54be61e3bc67b04301306207fc012ab9f354283f665655b576e1e8657617f1e2", size = 409082, upload-time = "2026-04-09T22:18:47.062Z" }, + { url = "https://files.pythonhosted.org/packages/36/4e/13d62564d0ef1db5534bf0af12373d289e7cf853f7893f0ba5c3c7d48a97/jpype1-1.7.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:6f893ad52e55a96db9f59af37e4ecc6731a7067c71e398457c7c32ea2ff85fe2", size = 454844, upload-time = "2026-04-09T22:18:49.16Z" }, + { url = "https://files.pythonhosted.org/packages/be/68/252059b8ff667fb60307feacc1875caebe4960cf225d82c791f777f6a445/jpype1-1.7.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36666a26a37e8a48c5b087a875f94d69846383a3414ed05761ea293de95525e6", size = 439051, upload-time = "2026-04-09T22:18:50.701Z" }, ] [[package]] @@ -13715,15 +13724,15 @@ wheels = [ [[package]] name = "jwcrypto" -version = "1.5.6" +version = "1.5.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/db/870e5d5fb311b0bcf049630b5ba3abca2d339fd5e13ba175b4c13b456d08/jwcrypto-1.5.6.tar.gz", hash = "sha256:771a87762a0c081ae6166958a954f80848820b2ab066937dc8b8379d65b1b039", size = 87168, upload-time = "2024-03-06T19:58:31.831Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/90/f065668004d22715c1940d6e88e4c3afc8ee16d5664e4478d2c8fd23a250/jwcrypto-1.5.7.tar.gz", hash = "sha256:70204d7cca406eda8c82352e3c41ba2d946610dafd19e54403f0a1f4f18633c6", size = 89535, upload-time = "2026-04-07T00:35:36.116Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl", hash = "sha256:150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789", size = 92520, upload-time = "2024-03-06T19:58:29.765Z" }, + { url = "https://files.pythonhosted.org/packages/72/24/fb7da4d6613de7001feaf540d4b5969c6b5a1c42839043b0196cb13aa057/jwcrypto-1.5.7-py3-none-any.whl", hash = "sha256:729463fefe28b6de5cf1ebfda3e94f1a1b41d2799148ef98a01cb9678ebe2bb0", size = 94799, upload-time = "2026-04-07T00:35:35.085Z" }, ] [[package]] @@ -13964,87 +13973,87 @@ wheels = [ [[package]] name = "librt" -version = "0.8.1" +version = "0.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/56/9c/b4b0c54d84da4a94b37bd44151e46d5e583c9534c7e02250b961b1b6d8a8/librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73", size = 177471, upload-time = "2026-02-17T16:13:06.101Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/5f/63f5fa395c7a8a93558c0904ba8f1c8d1b997ca6a3de61bc7659970d66bf/librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc", size = 65697, upload-time = "2026-02-17T16:11:06.903Z" }, - { url = "https://files.pythonhosted.org/packages/ff/e0/0472cf37267b5920eff2f292ccfaede1886288ce35b7f3203d8de00abfe6/librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7", size = 68376, upload-time = "2026-02-17T16:11:08.395Z" }, - { url = "https://files.pythonhosted.org/packages/c8/be/8bd1359fdcd27ab897cd5963294fa4a7c83b20a8564678e4fd12157e56a5/librt-0.8.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6", size = 197084, upload-time = "2026-02-17T16:11:09.774Z" }, - { url = "https://files.pythonhosted.org/packages/e2/fe/163e33fdd091d0c2b102f8a60cc0a61fd730ad44e32617cd161e7cd67a01/librt-0.8.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0", size = 207337, upload-time = "2026-02-17T16:11:11.311Z" }, - { url = "https://files.pythonhosted.org/packages/01/99/f85130582f05dcf0c8902f3d629270231d2f4afdfc567f8305a952ac7f14/librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b", size = 219980, upload-time = "2026-02-17T16:11:12.499Z" }, - { url = "https://files.pythonhosted.org/packages/6f/54/cb5e4d03659e043a26c74e08206412ac9a3742f0477d96f9761a55313b5f/librt-0.8.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6", size = 212921, upload-time = "2026-02-17T16:11:14.484Z" }, - { url = "https://files.pythonhosted.org/packages/b1/81/a3a01e4240579c30f3487f6fed01eb4bc8ef0616da5b4ebac27ca19775f3/librt-0.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71", size = 221381, upload-time = "2026-02-17T16:11:17.459Z" }, - { url = "https://files.pythonhosted.org/packages/08/b0/fc2d54b4b1c6fb81e77288ff31ff25a2c1e62eaef4424a984f228839717b/librt-0.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7", size = 216714, upload-time = "2026-02-17T16:11:19.197Z" }, - { url = "https://files.pythonhosted.org/packages/96/96/85daa73ffbd87e1fb287d7af6553ada66bf25a2a6b0de4764344a05469f6/librt-0.8.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05", size = 214777, upload-time = "2026-02-17T16:11:20.443Z" }, - { url = "https://files.pythonhosted.org/packages/12/9c/c3aa7a2360383f4bf4f04d98195f2739a579128720c603f4807f006a4225/librt-0.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891", size = 237398, upload-time = "2026-02-17T16:11:22.083Z" }, - { url = "https://files.pythonhosted.org/packages/61/19/d350ea89e5274665185dabc4bbb9c3536c3411f862881d316c8b8e00eb66/librt-0.8.1-cp310-cp310-win32.whl", hash = "sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7", size = 54285, upload-time = "2026-02-17T16:11:23.27Z" }, - { url = "https://files.pythonhosted.org/packages/4f/d6/45d587d3d41c112e9543a0093d883eb57a24a03e41561c127818aa2a6bcc/librt-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2", size = 61352, upload-time = "2026-02-17T16:11:24.207Z" }, - { url = "https://files.pythonhosted.org/packages/1d/01/0e748af5e4fee180cf7cd12bd12b0513ad23b045dccb2a83191bde82d168/librt-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd", size = 65315, upload-time = "2026-02-17T16:11:25.152Z" }, - { url = "https://files.pythonhosted.org/packages/9d/4d/7184806efda571887c798d573ca4134c80ac8642dcdd32f12c31b939c595/librt-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965", size = 68021, upload-time = "2026-02-17T16:11:26.129Z" }, - { url = "https://files.pythonhosted.org/packages/ae/88/c3c52d2a5d5101f28d3dc89298444626e7874aa904eed498464c2af17627/librt-0.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da", size = 194500, upload-time = "2026-02-17T16:11:27.177Z" }, - { url = "https://files.pythonhosted.org/packages/d6/5d/6fb0a25b6a8906e85b2c3b87bee1d6ed31510be7605b06772f9374ca5cb3/librt-0.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0", size = 205622, upload-time = "2026-02-17T16:11:28.242Z" }, - { url = "https://files.pythonhosted.org/packages/b2/a6/8006ae81227105476a45691f5831499e4d936b1c049b0c1feb17c11b02d1/librt-0.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e", size = 218304, upload-time = "2026-02-17T16:11:29.344Z" }, - { url = "https://files.pythonhosted.org/packages/ee/19/60e07886ad16670aae57ef44dada41912c90906a6fe9f2b9abac21374748/librt-0.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3", size = 211493, upload-time = "2026-02-17T16:11:30.445Z" }, - { url = "https://files.pythonhosted.org/packages/9c/cf/f666c89d0e861d05600438213feeb818c7514d3315bae3648b1fc145d2b6/librt-0.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac", size = 219129, upload-time = "2026-02-17T16:11:32.021Z" }, - { url = "https://files.pythonhosted.org/packages/8f/ef/f1bea01e40b4a879364c031476c82a0dc69ce068daad67ab96302fed2d45/librt-0.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596", size = 213113, upload-time = "2026-02-17T16:11:33.192Z" }, - { url = "https://files.pythonhosted.org/packages/9b/80/cdab544370cc6bc1b72ea369525f547a59e6938ef6863a11ab3cd24759af/librt-0.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99", size = 212269, upload-time = "2026-02-17T16:11:34.373Z" }, - { url = "https://files.pythonhosted.org/packages/9d/9c/48d6ed8dac595654f15eceab2035131c136d1ae9a1e3548e777bb6dbb95d/librt-0.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe", size = 234673, upload-time = "2026-02-17T16:11:36.063Z" }, - { url = "https://files.pythonhosted.org/packages/16/01/35b68b1db517f27a01be4467593292eb5315def8900afad29fabf56304ba/librt-0.8.1-cp311-cp311-win32.whl", hash = "sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb", size = 54597, upload-time = "2026-02-17T16:11:37.544Z" }, - { url = "https://files.pythonhosted.org/packages/71/02/796fe8f02822235966693f257bf2c79f40e11337337a657a8cfebba5febc/librt-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b", size = 61733, upload-time = "2026-02-17T16:11:38.691Z" }, - { url = "https://files.pythonhosted.org/packages/28/ad/232e13d61f879a42a4e7117d65e4984bb28371a34bb6fb9ca54ec2c8f54e/librt-0.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9", size = 52273, upload-time = "2026-02-17T16:11:40.308Z" }, - { url = "https://files.pythonhosted.org/packages/95/21/d39b0a87ac52fc98f621fb6f8060efb017a767ebbbac2f99fbcbc9ddc0d7/librt-0.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a", size = 66516, upload-time = "2026-02-17T16:11:41.604Z" }, - { url = "https://files.pythonhosted.org/packages/69/f1/46375e71441c43e8ae335905e069f1c54febee63a146278bcee8782c84fd/librt-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9", size = 68634, upload-time = "2026-02-17T16:11:43.268Z" }, - { url = "https://files.pythonhosted.org/packages/0a/33/c510de7f93bf1fa19e13423a606d8189a02624a800710f6e6a0a0f0784b3/librt-0.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb", size = 198941, upload-time = "2026-02-17T16:11:44.28Z" }, - { url = "https://files.pythonhosted.org/packages/dd/36/e725903416409a533d92398e88ce665476f275081d0d7d42f9c4951999e5/librt-0.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d", size = 209991, upload-time = "2026-02-17T16:11:45.462Z" }, - { url = "https://files.pythonhosted.org/packages/30/7a/8d908a152e1875c9f8eac96c97a480df425e657cdb47854b9efaa4998889/librt-0.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7", size = 224476, upload-time = "2026-02-17T16:11:46.542Z" }, - { url = "https://files.pythonhosted.org/packages/a8/b8/a22c34f2c485b8903a06f3fe3315341fe6876ef3599792344669db98fcff/librt-0.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440", size = 217518, upload-time = "2026-02-17T16:11:47.746Z" }, - { url = "https://files.pythonhosted.org/packages/79/6f/5c6fea00357e4f82ba44f81dbfb027921f1ab10e320d4a64e1c408d035d9/librt-0.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9", size = 225116, upload-time = "2026-02-17T16:11:49.298Z" }, - { url = "https://files.pythonhosted.org/packages/f2/a0/95ced4e7b1267fe1e2720a111685bcddf0e781f7e9e0ce59d751c44dcfe5/librt-0.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972", size = 217751, upload-time = "2026-02-17T16:11:50.49Z" }, - { url = "https://files.pythonhosted.org/packages/93/c2/0517281cb4d4101c27ab59472924e67f55e375bc46bedae94ac6dc6e1902/librt-0.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921", size = 218378, upload-time = "2026-02-17T16:11:51.783Z" }, - { url = "https://files.pythonhosted.org/packages/43/e8/37b3ac108e8976888e559a7b227d0ceac03c384cfd3e7a1c2ee248dbae79/librt-0.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0", size = 241199, upload-time = "2026-02-17T16:11:53.561Z" }, - { url = "https://files.pythonhosted.org/packages/4b/5b/35812d041c53967fedf551a39399271bbe4257e681236a2cf1a69c8e7fa1/librt-0.8.1-cp312-cp312-win32.whl", hash = "sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a", size = 54917, upload-time = "2026-02-17T16:11:54.758Z" }, - { url = "https://files.pythonhosted.org/packages/de/d1/fa5d5331b862b9775aaf2a100f5ef86854e5d4407f71bddf102f4421e034/librt-0.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444", size = 62017, upload-time = "2026-02-17T16:11:55.748Z" }, - { url = "https://files.pythonhosted.org/packages/c7/7c/c614252f9acda59b01a66e2ddfd243ed1c7e1deab0293332dfbccf862808/librt-0.8.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d", size = 52441, upload-time = "2026-02-17T16:11:56.801Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3c/f614c8e4eaac7cbf2bbdf9528790b21d89e277ee20d57dc6e559c626105f/librt-0.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35", size = 66529, upload-time = "2026-02-17T16:11:57.809Z" }, - { url = "https://files.pythonhosted.org/packages/ab/96/5836544a45100ae411eda07d29e3d99448e5258b6e9c8059deb92945f5c2/librt-0.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583", size = 68669, upload-time = "2026-02-17T16:11:58.843Z" }, - { url = "https://files.pythonhosted.org/packages/06/53/f0b992b57af6d5531bf4677d75c44f095f2366a1741fb695ee462ae04b05/librt-0.8.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c", size = 199279, upload-time = "2026-02-17T16:11:59.862Z" }, - { url = "https://files.pythonhosted.org/packages/f3/ad/4848cc16e268d14280d8168aee4f31cea92bbd2b79ce33d3e166f2b4e4fc/librt-0.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04", size = 210288, upload-time = "2026-02-17T16:12:00.954Z" }, - { url = "https://files.pythonhosted.org/packages/52/05/27fdc2e95de26273d83b96742d8d3b7345f2ea2bdbd2405cc504644f2096/librt-0.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363", size = 224809, upload-time = "2026-02-17T16:12:02.108Z" }, - { url = "https://files.pythonhosted.org/packages/7a/d0/78200a45ba3240cb042bc597d6f2accba9193a2c57d0356268cbbe2d0925/librt-0.8.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0", size = 218075, upload-time = "2026-02-17T16:12:03.631Z" }, - { url = "https://files.pythonhosted.org/packages/af/72/a210839fa74c90474897124c064ffca07f8d4b347b6574d309686aae7ca6/librt-0.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012", size = 225486, upload-time = "2026-02-17T16:12:04.725Z" }, - { url = "https://files.pythonhosted.org/packages/a3/c1/a03cc63722339ddbf087485f253493e2b013039f5b707e8e6016141130fa/librt-0.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb", size = 218219, upload-time = "2026-02-17T16:12:05.828Z" }, - { url = "https://files.pythonhosted.org/packages/58/f5/fff6108af0acf941c6f274a946aea0e484bd10cd2dc37610287ce49388c5/librt-0.8.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b", size = 218750, upload-time = "2026-02-17T16:12:07.09Z" }, - { url = "https://files.pythonhosted.org/packages/71/67/5a387bfef30ec1e4b4f30562c8586566faf87e47d696768c19feb49e3646/librt-0.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d", size = 241624, upload-time = "2026-02-17T16:12:08.43Z" }, - { url = "https://files.pythonhosted.org/packages/d4/be/24f8502db11d405232ac1162eb98069ca49c3306c1d75c6ccc61d9af8789/librt-0.8.1-cp313-cp313-win32.whl", hash = "sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a", size = 54969, upload-time = "2026-02-17T16:12:09.633Z" }, - { url = "https://files.pythonhosted.org/packages/5c/73/c9fdf6cb2a529c1a092ce769a12d88c8cca991194dfe641b6af12fa964d2/librt-0.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79", size = 62000, upload-time = "2026-02-17T16:12:10.632Z" }, - { url = "https://files.pythonhosted.org/packages/d3/97/68f80ca3ac4924f250cdfa6e20142a803e5e50fca96ef5148c52ee8c10ea/librt-0.8.1-cp313-cp313-win_arm64.whl", hash = "sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0", size = 52495, upload-time = "2026-02-17T16:12:11.633Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6a/907ef6800f7bca71b525a05f1839b21f708c09043b1c6aa77b6b827b3996/librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f", size = 66081, upload-time = "2026-02-17T16:12:12.766Z" }, - { url = "https://files.pythonhosted.org/packages/1b/18/25e991cd5640c9fb0f8d91b18797b29066b792f17bf8493da183bf5caabe/librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c", size = 68309, upload-time = "2026-02-17T16:12:13.756Z" }, - { url = "https://files.pythonhosted.org/packages/a4/36/46820d03f058cfb5a9de5940640ba03165ed8aded69e0733c417bb04df34/librt-0.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc", size = 196804, upload-time = "2026-02-17T16:12:14.818Z" }, - { url = "https://files.pythonhosted.org/packages/59/18/5dd0d3b87b8ff9c061849fbdb347758d1f724b9a82241aa908e0ec54ccd0/librt-0.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c", size = 206907, upload-time = "2026-02-17T16:12:16.513Z" }, - { url = "https://files.pythonhosted.org/packages/d1/96/ef04902aad1424fd7299b62d1890e803e6ab4018c3044dca5922319c4b97/librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3", size = 221217, upload-time = "2026-02-17T16:12:17.906Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ff/7e01f2dda84a8f5d280637a2e5827210a8acca9a567a54507ef1c75b342d/librt-0.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14", size = 214622, upload-time = "2026-02-17T16:12:19.108Z" }, - { url = "https://files.pythonhosted.org/packages/1e/8c/5b093d08a13946034fed57619742f790faf77058558b14ca36a6e331161e/librt-0.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7", size = 221987, upload-time = "2026-02-17T16:12:20.331Z" }, - { url = "https://files.pythonhosted.org/packages/d3/cc/86b0b3b151d40920ad45a94ce0171dec1aebba8a9d72bb3fa00c73ab25dd/librt-0.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6", size = 215132, upload-time = "2026-02-17T16:12:21.54Z" }, - { url = "https://files.pythonhosted.org/packages/fc/be/8588164a46edf1e69858d952654e216a9a91174688eeefb9efbb38a9c799/librt-0.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071", size = 215195, upload-time = "2026-02-17T16:12:23.073Z" }, - { url = "https://files.pythonhosted.org/packages/f5/f2/0b9279bea735c734d69344ecfe056c1ba211694a72df10f568745c899c76/librt-0.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78", size = 237946, upload-time = "2026-02-17T16:12:24.275Z" }, - { url = "https://files.pythonhosted.org/packages/e9/cc/5f2a34fbc8aeb35314a3641f9956fa9051a947424652fad9882be7a97949/librt-0.8.1-cp314-cp314-win32.whl", hash = "sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023", size = 50689, upload-time = "2026-02-17T16:12:25.766Z" }, - { url = "https://files.pythonhosted.org/packages/a0/76/cd4d010ab2147339ca2b93e959c3686e964edc6de66ddacc935c325883d7/librt-0.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730", size = 57875, upload-time = "2026-02-17T16:12:27.465Z" }, - { url = "https://files.pythonhosted.org/packages/84/0f/2143cb3c3ca48bd3379dcd11817163ca50781927c4537345d608b5045998/librt-0.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3", size = 48058, upload-time = "2026-02-17T16:12:28.556Z" }, - { url = "https://files.pythonhosted.org/packages/d2/0e/9b23a87e37baf00311c3efe6b48d6b6c168c29902dfc3f04c338372fd7db/librt-0.8.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1", size = 68313, upload-time = "2026-02-17T16:12:29.659Z" }, - { url = "https://files.pythonhosted.org/packages/db/9a/859c41e5a4f1c84200a7d2b92f586aa27133c8243b6cac9926f6e54d01b9/librt-0.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee", size = 70994, upload-time = "2026-02-17T16:12:31.516Z" }, - { url = "https://files.pythonhosted.org/packages/4c/28/10605366ee599ed34223ac2bf66404c6fb59399f47108215d16d5ad751a8/librt-0.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7", size = 220770, upload-time = "2026-02-17T16:12:33.294Z" }, - { url = "https://files.pythonhosted.org/packages/af/8d/16ed8fd452dafae9c48d17a6bc1ee3e818fd40ef718d149a8eff2c9f4ea2/librt-0.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040", size = 235409, upload-time = "2026-02-17T16:12:35.443Z" }, - { url = "https://files.pythonhosted.org/packages/89/1b/7bdf3e49349c134b25db816e4a3db6b94a47ac69d7d46b1e682c2c4949be/librt-0.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e", size = 246473, upload-time = "2026-02-17T16:12:36.656Z" }, - { url = "https://files.pythonhosted.org/packages/4e/8a/91fab8e4fd2a24930a17188c7af5380eb27b203d72101c9cc000dbdfd95a/librt-0.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732", size = 238866, upload-time = "2026-02-17T16:12:37.849Z" }, - { url = "https://files.pythonhosted.org/packages/b9/e0/c45a098843fc7c07e18a7f8a24ca8496aecbf7bdcd54980c6ca1aaa79a8e/librt-0.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624", size = 250248, upload-time = "2026-02-17T16:12:39.445Z" }, - { url = "https://files.pythonhosted.org/packages/82/30/07627de23036640c952cce0c1fe78972e77d7d2f8fd54fa5ef4554ff4a56/librt-0.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4", size = 240629, upload-time = "2026-02-17T16:12:40.889Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c1/55bfe1ee3542eba055616f9098eaf6eddb966efb0ca0f44eaa4aba327307/librt-0.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382", size = 239615, upload-time = "2026-02-17T16:12:42.446Z" }, - { url = "https://files.pythonhosted.org/packages/2b/39/191d3d28abc26c9099b19852e6c99f7f6d400b82fa5a4e80291bd3803e19/librt-0.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994", size = 263001, upload-time = "2026-02-17T16:12:43.627Z" }, - { url = "https://files.pythonhosted.org/packages/b9/eb/7697f60fbe7042ab4e88f4ee6af496b7f222fffb0a4e3593ef1f29f81652/librt-0.8.1-cp314-cp314t-win32.whl", hash = "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a", size = 51328, upload-time = "2026-02-17T16:12:45.148Z" }, - { url = "https://files.pythonhosted.org/packages/7c/72/34bf2eb7a15414a23e5e70ecb9440c1d3179f393d9349338a91e2781c0fb/librt-0.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4", size = 58722, upload-time = "2026-02-17T16:12:46.85Z" }, - { url = "https://files.pythonhosted.org/packages/b2/c8/d148e041732d631fc76036f8b30fae4e77b027a1e95b7a84bb522481a940/librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61", size = 48755, upload-time = "2026-02-17T16:12:47.943Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/eb/6b/3d5c13fb3e3c4f43206c8f9dfed13778c2ed4f000bacaa0b7ce3c402a265/librt-0.9.0.tar.gz", hash = "sha256:a0951822531e7aee6e0dfb556b30d5ee36bbe234faf60c20a16c01be3530869d", size = 184368, upload-time = "2026-04-09T16:06:26.173Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/4a/c64265d71b84030174ff3ac2cd16d8b664072afab8c41fccd8e2ee5a6f8d/librt-0.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f8e12706dcb8ff6b3ed57514a19e45c49ad00bcd423e87b2b2e4b5f64578443", size = 67529, upload-time = "2026-04-09T16:04:27.373Z" }, + { url = "https://files.pythonhosted.org/packages/23/b1/30ca0b3a8bdac209a00145c66cf42e5e7da2cc056ffc6ebc5c7b430ddd34/librt-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e3dda8345307fd7306db0ed0cb109a63a2c85ba780eb9dc2d09b2049a931f9c", size = 70248, upload-time = "2026-04-09T16:04:28.758Z" }, + { url = "https://files.pythonhosted.org/packages/fa/fc/c6018dc181478d6ac5aa24a5846b8185101eb90894346db239eb3ea53209/librt-0.9.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:de7dac64e3eb832ffc7b840eb8f52f76420cde1b845be51b2a0f6b870890645e", size = 202184, upload-time = "2026-04-09T16:04:29.893Z" }, + { url = "https://files.pythonhosted.org/packages/bf/58/d69629f002203370ef41ea69ff71c49a2c618aec39b226ff49986ecd8623/librt-0.9.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22a904cbdb678f7cb348c90d543d3c52f581663d687992fee47fd566dcbf5285", size = 212926, upload-time = "2026-04-09T16:04:31.126Z" }, + { url = "https://files.pythonhosted.org/packages/cc/55/01d859f57824e42bd02465c77bec31fa5ef9d8c2bcee702ccf8ef1b9f508/librt-0.9.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:224b9727eb8bc188bc3bcf29d969dba0cd61b01d9bac80c41575520cc4baabb2", size = 225664, upload-time = "2026-04-09T16:04:32.352Z" }, + { url = "https://files.pythonhosted.org/packages/9b/02/32f63ad0ef085a94a70315291efe1151a48b9947af12261882f8445b2a30/librt-0.9.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e94cbc6ad9a6aeea46d775cbb11f361022f778a9cc8cc90af653d3a594b057ce", size = 219534, upload-time = "2026-04-09T16:04:33.667Z" }, + { url = "https://files.pythonhosted.org/packages/6a/5a/9d77111a183c885acf3b3b6e4c00f5b5b07b5817028226499a55f1fedc59/librt-0.9.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7bc30ad339f4e1a01d4917d645e522a0bc0030644d8973f6346397c93ba1503f", size = 227322, upload-time = "2026-04-09T16:04:34.945Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e7/05d700c93063753e12ab230b972002a3f8f3b9c95d8a980c2f646c8b6963/librt-0.9.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:56d65b583cf43b8cf4c8fbe1e1da20fa3076cc32a1149a141507af1062718236", size = 223407, upload-time = "2026-04-09T16:04:36.22Z" }, + { url = "https://files.pythonhosted.org/packages/c0/26/26c3124823c67c987456977c683da9a27cc874befc194ddcead5f9988425/librt-0.9.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0a1be03168b2691ba61927e299b352a6315189199ca18a57b733f86cb3cc8d38", size = 221302, upload-time = "2026-04-09T16:04:37.62Z" }, + { url = "https://files.pythonhosted.org/packages/50/2b/c7cc2be5cf4ff7b017d948a789256288cb33a517687ff1995e72a7eea79f/librt-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:63c12efcd160e1d14da11af0c46c0217473e1e0d2ae1acbccc83f561ea4c2a7b", size = 243893, upload-time = "2026-04-09T16:04:38.909Z" }, + { url = "https://files.pythonhosted.org/packages/62/d3/da553d37417a337d12660450535d5fd51373caffbedf6962173c87867246/librt-0.9.0-cp310-cp310-win32.whl", hash = "sha256:e9002e98dcb1c0a66723592520decd86238ddcef168b37ff6cfb559200b4b774", size = 55375, upload-time = "2026-04-09T16:04:40.148Z" }, + { url = "https://files.pythonhosted.org/packages/9b/5a/46fa357bab8311b6442a83471591f2f9e5b15ecc1d2121a43725e0c529b8/librt-0.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:9fcb461fbf70654a52a7cc670e606f04449e2374c199b1825f754e16dacfedd8", size = 62581, upload-time = "2026-04-09T16:04:41.452Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1e/2ec7afcebcf3efea593d13aee18bbcfdd3a243043d848ebf385055e9f636/librt-0.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90904fac73c478f4b83f4ed96c99c8208b75e6f9a8a1910548f69a00f1eaa671", size = 67155, upload-time = "2026-04-09T16:04:42.933Z" }, + { url = "https://files.pythonhosted.org/packages/18/77/72b85afd4435268338ad4ec6231b3da8c77363f212a0227c1ff3b45e4d35/librt-0.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:789fff71757facc0738e8d89e3b84e4f0251c1c975e85e81b152cdaca927cc2d", size = 69916, upload-time = "2026-04-09T16:04:44.042Z" }, + { url = "https://files.pythonhosted.org/packages/27/fb/948ea0204fbe2e78add6d46b48330e58d39897e425560674aee302dca81c/librt-0.9.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1bf465d1e5b0a27713862441f6467b5ab76385f4ecf8f1f3a44f8aa3c695b4b6", size = 199635, upload-time = "2026-04-09T16:04:45.5Z" }, + { url = "https://files.pythonhosted.org/packages/ac/cd/894a29e251b296a27957856804cfd21e93c194aa131de8bb8032021be07e/librt-0.9.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f819e0c6413e259a17a7c0d49f97f405abadd3c2a316a3b46c6440b7dbbedbb1", size = 211051, upload-time = "2026-04-09T16:04:47.016Z" }, + { url = "https://files.pythonhosted.org/packages/18/8f/dcaed0bc084a35f3721ff2d081158db569d2c57ea07d35623ddaca5cfc8e/librt-0.9.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0785c2fb4a81e1aece366aa3e2e039f4a4d7d21aaaded5227d7f3c703427882", size = 224031, upload-time = "2026-04-09T16:04:48.207Z" }, + { url = "https://files.pythonhosted.org/packages/03/44/88f6c1ed1132cd418601cc041fbd92fed28b3a09f39de81978e0822d13ff/librt-0.9.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:80b25c7b570a86c03b5da69e665809deb39265476e8e21d96a9328f9762f9990", size = 218069, upload-time = "2026-04-09T16:04:50.025Z" }, + { url = "https://files.pythonhosted.org/packages/a3/90/7d02e981c2db12188d82b4410ff3e35bfdb844b26aecd02233626f46af2b/librt-0.9.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d4d16b608a1c43d7e33142099a75cd93af482dadce0bf82421e91cad077157f4", size = 224857, upload-time = "2026-04-09T16:04:51.684Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c3/c77e706b7215ca32e928d47535cf13dbc3d25f096f84ddf8fbc06693e229/librt-0.9.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:194fc1a32e1e21fe809d38b5faea66cc65eaa00217c8901fbdb99866938adbdb", size = 219865, upload-time = "2026-04-09T16:04:52.949Z" }, + { url = "https://files.pythonhosted.org/packages/52/d1/32b0c1a0eb8461c70c11656c46a29f760b7c7edf3c36d6f102470c17170f/librt-0.9.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8c6bc1384d9738781cfd41d09ad7f6e8af13cfea2c75ece6bd6d2566cdea2076", size = 218451, upload-time = "2026-04-09T16:04:54.174Z" }, + { url = "https://files.pythonhosted.org/packages/74/d1/adfd0f9c44761b1d49b1bec66173389834c33ee2bd3c7fd2e2367f1942d4/librt-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:15cb151e52a044f06e54ac7f7b47adbfc89b5c8e2b63e1175a9d587c43e8942a", size = 241300, upload-time = "2026-04-09T16:04:55.452Z" }, + { url = "https://files.pythonhosted.org/packages/09/b0/9074b64407712f0003c27f5b1d7655d1438979155f049720e8a1abd9b1a1/librt-0.9.0-cp311-cp311-win32.whl", hash = "sha256:f100bfe2acf8a3689af9d0cc660d89f17286c9c795f9f18f7b62dd1a6b247ae6", size = 55668, upload-time = "2026-04-09T16:04:56.689Z" }, + { url = "https://files.pythonhosted.org/packages/24/19/40b77b77ce80b9389fb03971431b09b6b913911c38d412059e0b3e2a9ef2/librt-0.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:0b73e4266307e51c95e09c0750b7ec383c561d2e97d58e473f6f6a209952fbb8", size = 62976, upload-time = "2026-04-09T16:04:57.733Z" }, + { url = "https://files.pythonhosted.org/packages/70/9d/9fa7a64041e29035cb8c575af5f0e3840be1b97b4c4d9061e0713f171849/librt-0.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc5518873822d2faa8ebdd2c1a4d7c8ef47b01a058495ab7924cb65bdbf5fc9a", size = 53502, upload-time = "2026-04-09T16:04:58.806Z" }, + { url = "https://files.pythonhosted.org/packages/bf/90/89ddba8e1c20b0922783cd93ed8e64f34dc05ab59c38a9c7e313632e20ff/librt-0.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b3e3bc363f71bda1639a4ee593cb78f7fbfeacc73411ec0d4c92f00730010a4", size = 68332, upload-time = "2026-04-09T16:05:00.09Z" }, + { url = "https://files.pythonhosted.org/packages/a8/40/7aa4da1fb08bdeeb540cb07bfc8207cb32c5c41642f2594dbd0098a0662d/librt-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a09c2f5869649101738653a9b7ab70cf045a1105ac66cbb8f4055e61df78f2d", size = 70581, upload-time = "2026-04-09T16:05:01.213Z" }, + { url = "https://files.pythonhosted.org/packages/48/ac/73a2187e1031041e93b7e3a25aae37aa6f13b838c550f7e0f06f66766212/librt-0.9.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5ca8e133d799c948db2ab1afc081c333a825b5540475164726dcbf73537e5c2f", size = 203984, upload-time = "2026-04-09T16:05:02.542Z" }, + { url = "https://files.pythonhosted.org/packages/5e/3d/23460d571e9cbddb405b017681df04c142fb1b04cbfce77c54b08e28b108/librt-0.9.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:603138ee838ee1583f1b960b62d5d0007845c5c423feb68e44648b1359014e27", size = 215762, upload-time = "2026-04-09T16:05:04.127Z" }, + { url = "https://files.pythonhosted.org/packages/de/1e/42dc7f8ab63e65b20640d058e63e97fd3e482c1edbda3570d813b4d0b927/librt-0.9.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4003f70c56a5addd6aa0897f200dd59afd3bf7bcd5b3cce46dd21f925743bc2", size = 230288, upload-time = "2026-04-09T16:05:05.883Z" }, + { url = "https://files.pythonhosted.org/packages/dc/08/ca812b6d8259ad9ece703397f8ad5c03af5b5fedfce64279693d3ce4087c/librt-0.9.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:78042f6facfd98ecb25e9829c7e37cce23363d9d7c83bc5f72702c5059eb082b", size = 224103, upload-time = "2026-04-09T16:05:07.148Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3f/620490fb2fa66ffd44e7f900254bc110ebec8dac6c1b7514d64662570e6f/librt-0.9.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a361c9434a64d70a7dbb771d1de302c0cc9f13c0bffe1cf7e642152814b35265", size = 232122, upload-time = "2026-04-09T16:05:08.386Z" }, + { url = "https://files.pythonhosted.org/packages/e9/83/12864700a1b6a8be458cf5d05db209b0d8e94ae281e7ec261dbe616597b4/librt-0.9.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:dd2c7e082b0b92e1baa4da28163a808672485617bc855cc22a2fd06978fa9084", size = 225045, upload-time = "2026-04-09T16:05:09.707Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1b/845d339c29dc7dbc87a2e992a1ba8d28d25d0e0372f9a0a2ecebde298186/librt-0.9.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7e6274fd33fc5b2a14d41c9119629d3ff395849d8bcbc80cf637d9e8d2034da8", size = 227372, upload-time = "2026-04-09T16:05:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/8d/fe/277985610269d926a64c606f761d58d3db67b956dbbf40024921e95e7fcb/librt-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5093043afb226ecfa1400120d1ebd4442b4f99977783e4f4f7248879009b227f", size = 248224, upload-time = "2026-04-09T16:05:12.254Z" }, + { url = "https://files.pythonhosted.org/packages/92/1b/ee486d244b8de6b8b5dbaefabe6bfdd4a72e08f6353edf7d16d27114da8d/librt-0.9.0-cp312-cp312-win32.whl", hash = "sha256:9edcc35d1cae9fd5320171b1a838c7da8a5c968af31e82ecc3dff30b4be0957f", size = 55986, upload-time = "2026-04-09T16:05:13.529Z" }, + { url = "https://files.pythonhosted.org/packages/89/7a/ba1737012308c17dc6d5516143b5dce9a2c7ba3474afd54e11f44a4d1ef3/librt-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:3cc2917258e131ae5f958a4d872e07555b51cb7466a43433218061c74ef33745", size = 63260, upload-time = "2026-04-09T16:05:14.68Z" }, + { url = "https://files.pythonhosted.org/packages/36/e4/01752c113da15127f18f7bf11142f5640038f062407a611c059d0036c6aa/librt-0.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:90e6d5420fc8a300518d4d2288154ff45005e920425c22cbbfe8330f3f754bd9", size = 53694, upload-time = "2026-04-09T16:05:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d7/1b3e26fffde1452d82f5666164858a81c26ebe808e7ae8c9c88628981540/librt-0.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29b68cd9714531672db62cc54f6e8ff981900f824d13fa0e00749189e13778e", size = 68367, upload-time = "2026-04-09T16:05:17.243Z" }, + { url = "https://files.pythonhosted.org/packages/a5/5b/c61b043ad2e091fbe1f2d35d14795e545d0b56b03edaa390fa1dcee3d160/librt-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d5c8a5929ac325729f6119802070b561f4db793dffc45e9ac750992a4ed4d22", size = 70595, upload-time = "2026-04-09T16:05:18.471Z" }, + { url = "https://files.pythonhosted.org/packages/a3/22/2448471196d8a73370aa2f23445455dc42712c21404081fcd7a03b9e0749/librt-0.9.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:756775d25ec8345b837ab52effee3ad2f3b2dfd6bbee3e3f029c517bd5d8f05a", size = 204354, upload-time = "2026-04-09T16:05:19.593Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5e/39fc4b153c78cfd2c8a2dcb32700f2d41d2312aa1050513183be4540930d/librt-0.9.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b8f5d00b49818f4e2b1667db994488b045835e0ac16fe2f924f3871bd2b8ac5", size = 216238, upload-time = "2026-04-09T16:05:20.868Z" }, + { url = "https://files.pythonhosted.org/packages/d7/42/bc2d02d0fa7badfa63aa8d6dcd8793a9f7ef5a94396801684a51ed8d8287/librt-0.9.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c81aef782380f0f13ead670aae01825eb653b44b046aa0e5ebbb79f76ed4aa11", size = 230589, upload-time = "2026-04-09T16:05:22.305Z" }, + { url = "https://files.pythonhosted.org/packages/c8/7b/e2d95cc513866373692aa5edf98080d5602dd07cabfb9e5d2f70df2f25f7/librt-0.9.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66b58fed90a545328e80d575467244de3741e088c1af928f0b489ebec3ef3858", size = 224610, upload-time = "2026-04-09T16:05:23.647Z" }, + { url = "https://files.pythonhosted.org/packages/31/d5/6cec4607e998eaba57564d06a1295c21b0a0c8de76e4e74d699e627bd98c/librt-0.9.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e78fb7419e07d98c2af4b8567b72b3eaf8cb05caad642e9963465569c8b2d87e", size = 232558, upload-time = "2026-04-09T16:05:25.025Z" }, + { url = "https://files.pythonhosted.org/packages/95/8c/27f1d8d3aaf079d3eb26439bf0b32f1482340c3552e324f7db9dca858671/librt-0.9.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c3786f0f4490a5cd87f1ed6cefae833ad6b1060d52044ce0434a2e85893afd0", size = 225521, upload-time = "2026-04-09T16:05:26.311Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d8/1e0d43b1c329b416017619469b3c3801a25a6a4ef4a1c68332aeaa6f72ca/librt-0.9.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8494cfc61e03542f2d381e71804990b3931175a29b9278fdb4a5459948778dc2", size = 227789, upload-time = "2026-04-09T16:05:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/2c/b4/d3d842e88610fcd4c8eec7067b0c23ef2d7d3bff31496eded6a83b0f99be/librt-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:07cf11f769831186eeac424376e6189f20ace4f7263e2134bdb9757340d84d4d", size = 248616, upload-time = "2026-04-09T16:05:29.181Z" }, + { url = "https://files.pythonhosted.org/packages/ec/28/527df8ad0d1eb6c8bdfa82fc190f1f7c4cca5a1b6d7b36aeabf95b52d74d/librt-0.9.0-cp313-cp313-win32.whl", hash = "sha256:850d6d03177e52700af605fd60db7f37dcb89782049a149674d1a9649c2138fd", size = 56039, upload-time = "2026-04-09T16:05:30.709Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a7/413652ad0d92273ee5e30c000fc494b361171177c83e57c060ecd3c21538/librt-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:a5af136bfba820d592f86c67affcef9b3ff4d4360ac3255e341e964489b48519", size = 63264, upload-time = "2026-04-09T16:05:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0a/92c244309b774e290ddb15e93363846ae7aa753d9586b8aad511c5e6145b/librt-0.9.0-cp313-cp313-win_arm64.whl", hash = "sha256:4c4d0440a3a8e31d962340c3e1cc3fc9ee7febd34c8d8f770d06adb947779ea5", size = 53728, upload-time = "2026-04-09T16:05:33.31Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c1/184e539543f06ea2912f4b92a5ffaede4f9b392689e3f00acbf8134bee92/librt-0.9.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:3f05d145df35dca5056a8bc3838e940efebd893a54b3e19b2dda39ceaa299bcb", size = 67830, upload-time = "2026-04-09T16:05:34.517Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ad/23399bdcb7afca819acacdef31b37ee59de261bd66b503a7995c03c4b0dc/librt-0.9.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1c587494461ebd42229d0f1739f3aa34237dd9980623ecf1be8d3bcba79f4499", size = 70280, upload-time = "2026-04-09T16:05:35.649Z" }, + { url = "https://files.pythonhosted.org/packages/9f/0b/4542dc5a2b8772dbf92cafb9194701230157e73c14b017b6961a23598b03/librt-0.9.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0a2040f801406b93657a70b72fa12311063a319fee72ce98e1524da7200171f", size = 201925, upload-time = "2026-04-09T16:05:36.739Z" }, + { url = "https://files.pythonhosted.org/packages/31/d4/8ee7358b08fd0cfce051ef96695380f09b3c2c11b77c9bfbc367c921cce5/librt-0.9.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f38bc489037eca88d6ebefc9c4d41a4e07c8e8b4de5188a9e6d290273ad7ebb1", size = 212381, upload-time = "2026-04-09T16:05:38.043Z" }, + { url = "https://files.pythonhosted.org/packages/f2/94/a2025fe442abedf8b038038dab3dba942009ad42b38ea064a1a9e6094241/librt-0.9.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3fd278f5e6bf7c75ccd6d12344eb686cc020712683363b66f46ac79d37c799f", size = 227065, upload-time = "2026-04-09T16:05:39.394Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e9/b9fcf6afa909f957cfbbf918802f9dada1bd5d3c1da43d722fd6a310dc3f/librt-0.9.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fcbdf2a9ca24e87bbebb47f1fe34e531ef06f104f98c9ccfc953a3f3344c567a", size = 221333, upload-time = "2026-04-09T16:05:40.999Z" }, + { url = "https://files.pythonhosted.org/packages/ac/7c/ba54cd6aa6a3c8cd12757a6870e0c79a64b1e6327f5248dcff98423f4d43/librt-0.9.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e306d956cfa027fe041585f02a1602c32bfa6bb8ebea4899d373383295a6c62f", size = 229051, upload-time = "2026-04-09T16:05:42.605Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4b/8cfdbad314c8677a0148bf0b70591d6d18587f9884d930276098a235461b/librt-0.9.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:465814ab157986acb9dfa5ccd7df944be5eefc0d08d31ec6e8d88bc71251d845", size = 222492, upload-time = "2026-04-09T16:05:43.842Z" }, + { url = "https://files.pythonhosted.org/packages/1f/d1/2eda69563a1a88706808decdce035e4b32755dbfbb0d05e1a65db9547ed1/librt-0.9.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:703f4ae36d6240bfe24f542bac784c7e4194ec49c3ba5a994d02891649e2d85b", size = 223849, upload-time = "2026-04-09T16:05:45.054Z" }, + { url = "https://files.pythonhosted.org/packages/04/44/b2ed37df6be5b3d42cfe36318e0598e80843d5c6308dd63d0bf4e0ce5028/librt-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3be322a15ee5e70b93b7a59cfd074614f22cc8c9ff18bd27f474e79137ea8d3b", size = 245001, upload-time = "2026-04-09T16:05:46.34Z" }, + { url = "https://files.pythonhosted.org/packages/47/e7/617e412426df89169dd2a9ed0cc8752d5763336252c65dbf945199915119/librt-0.9.0-cp314-cp314-win32.whl", hash = "sha256:b8da9f8035bb417770b1e1610526d87ad4fc58a2804dc4d79c53f6d2cf5a6eb9", size = 51799, upload-time = "2026-04-09T16:05:47.738Z" }, + { url = "https://files.pythonhosted.org/packages/24/ed/c22ca4db0ca3cbc285e4d9206108746beda561a9792289c3c31281d7e9df/librt-0.9.0-cp314-cp314-win_amd64.whl", hash = "sha256:b8bd70d5d816566a580d193326912f4a76ec2d28a97dc4cd4cc831c0af8e330e", size = 59165, upload-time = "2026-04-09T16:05:49.198Z" }, + { url = "https://files.pythonhosted.org/packages/24/56/875398fafa4cbc8f15b89366fc3287304ddd3314d861f182a4b87595ace0/librt-0.9.0-cp314-cp314-win_arm64.whl", hash = "sha256:fc5758e2b7a56532dc33e3c544d78cbaa9ecf0a0f2a2da2df882c1d6b99a317f", size = 49292, upload-time = "2026-04-09T16:05:50.362Z" }, + { url = "https://files.pythonhosted.org/packages/4c/61/bc448ecbf9b2d69c5cff88fe41496b19ab2a1cbda0065e47d4d0d51c0867/librt-0.9.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f24b90b0e0c8cc9491fb1693ae91fe17cb7963153a1946395acdbdd5818429a4", size = 70175, upload-time = "2026-04-09T16:05:51.564Z" }, + { url = "https://files.pythonhosted.org/packages/60/f2/c47bb71069a73e2f04e70acbd196c1e5cc411578ac99039a224b98920fd4/librt-0.9.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fe56e80badb66fdcde06bef81bbaa5bfcf6fbd7aefb86222d9e369c38c6b228", size = 72951, upload-time = "2026-04-09T16:05:52.699Z" }, + { url = "https://files.pythonhosted.org/packages/29/19/0549df59060631732df758e8886d92088da5fdbedb35b80e4643664e8412/librt-0.9.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:527b5b820b47a09e09829051452bb0d1dd2122261254e2a6f674d12f1d793d54", size = 225864, upload-time = "2026-04-09T16:05:53.895Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f8/3b144396d302ac08e50f89e64452c38db84bc7b23f6c60479c5d3abd303c/librt-0.9.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d429bdd4ac0ab17c8e4a8af0ed2a7440b16eba474909ab357131018fe8c7e71", size = 241155, upload-time = "2026-04-09T16:05:55.191Z" }, + { url = "https://files.pythonhosted.org/packages/7a/ce/ee67ec14581de4043e61d05786d2aed6c9b5338816b7859bcf07455c6a9f/librt-0.9.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7202bdcac47d3a708271c4304a474a8605a4a9a4a709e954bf2d3241140aa938", size = 252235, upload-time = "2026-04-09T16:05:56.549Z" }, + { url = "https://files.pythonhosted.org/packages/8a/fa/0ead15daa2b293a54101550b08d4bafe387b7d4a9fc6d2b985602bae69b6/librt-0.9.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0d620e74897f8c2613b3c4e2e9c1e422eb46d2ddd07df540784d44117836af3", size = 244963, upload-time = "2026-04-09T16:05:57.858Z" }, + { url = "https://files.pythonhosted.org/packages/29/68/9fbf9a9aa704ba87689e40017e720aced8d9a4d2b46b82451d8142f91ec9/librt-0.9.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d69fc39e627908f4c03297d5a88d9284b73f4d90b424461e32e8c2485e21c283", size = 257364, upload-time = "2026-04-09T16:05:59.686Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8d/9d60869f1b6716c762e45f66ed945b1e5dd649f7377684c3b176ae424648/librt-0.9.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:c2640e23d2b7c98796f123ffd95cf2022c7777aa8a4a3b98b36c570d37e85eee", size = 247661, upload-time = "2026-04-09T16:06:00.938Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/a5c365093962310bfdb4f6af256f191085078ffb529b3f0cbebb5b33ebe2/librt-0.9.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:451daa98463b7695b0a30aa56bf637831ea559e7b8101ac2ef6382e8eb15e29c", size = 248238, upload-time = "2026-04-09T16:06:02.537Z" }, + { url = "https://files.pythonhosted.org/packages/a0/3c/2d34365177f412c9e19c0a29f969d70f5343f27634b76b765a54d8b27705/librt-0.9.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:928bd06eca2c2bbf4349e5b817f837509b0604342e65a502de1d50a7570afd15", size = 269457, upload-time = "2026-04-09T16:06:03.833Z" }, + { url = "https://files.pythonhosted.org/packages/bc/cd/de45b239ea3bdf626f982a00c14bfcf2e12d261c510ba7db62c5969a27cd/librt-0.9.0-cp314-cp314t-win32.whl", hash = "sha256:a9c63e04d003bc0fb6a03b348018b9a3002f98268200e22cc80f146beac5dc40", size = 52453, upload-time = "2026-04-09T16:06:05.229Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f9/bfb32ae428aa75c0c533915622176f0a17d6da7b72b5a3c6363685914f70/librt-0.9.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f162af66a2ed3f7d1d161a82ca584efd15acd9c1cff190a373458c32f7d42118", size = 60044, upload-time = "2026-04-09T16:06:06.398Z" }, + { url = "https://files.pythonhosted.org/packages/aa/47/7d70414bcdbb3bc1f458a8d10558f00bbfdb24e5a11740fc8197e12c3255/librt-0.9.0-cp314-cp314t-win_arm64.whl", hash = "sha256:a4b25c6c25cac5d0d9d6d6da855195b254e0021e513e0249f0e3b444dc6e0e61", size = 50009, upload-time = "2026-04-09T16:06:07.995Z" }, ] [[package]] @@ -14107,11 +14116,11 @@ wheels = [ [[package]] name = "logfire-api" -version = "4.31.0" +version = "4.31.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/08/a2/8d5a3c1c282d5f2bd9f5e9ddd5288d1414a53301ce389af9016b6d82bd50/logfire_api-4.31.0.tar.gz", hash = "sha256:fc4b01257ebd4ce297ad374ed201eb1a9213b999f6ae6df45cfca5bd0ef378f8", size = 77838, upload-time = "2026-03-27T19:00:47.545Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a8/0f/f15348f05889e30fbb3e1803517fd0a34edefa9bda98ac323285c2ff9e6b/logfire_api-4.31.1.tar.gz", hash = "sha256:d671861211520f3e5a8ba240c288099235824daf4bf15d857cf6257dc4ab714e", size = 77841, upload-time = "2026-04-09T14:03:21.229Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/27/9372b7492b3e146908d520f8599909311cd930175801ad219171fafc6f3e/logfire_api-4.31.0-py3-none-any.whl", hash = "sha256:3c1f502fd4eb8ef0996427a5cf275fd8f327f38600650a1f53071a8171c812db", size = 123402, upload-time = "2026-03-27T19:00:44.952Z" }, + { url = "https://files.pythonhosted.org/packages/7d/22/5626d78361d3656282ecdd165d8ff8505fd5714a5b849cb6a52c0bee16c9/logfire_api-4.31.1-py3-none-any.whl", hash = "sha256:27e7136afdae0fa60ccef858d23a759450b0248aecd98648ba995506b444c49f", size = 123402, upload-time = "2026-04-09T14:03:18.008Z" }, ] [[package]] @@ -14520,51 +14529,51 @@ wheels = [ [[package]] name = "memray" -version = "1.19.2" +version = "1.19.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jinja2" }, { name = "rich" }, { name = "textual" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e9/db/56ff21f47be261ab781105b233d1851d3f2fcdd4f08ebf689f6d6fd84f0d/memray-1.19.2.tar.gz", hash = "sha256:680cb90ac4564d140673ac9d8b7a7e07a8405bd1fb8f933da22616f93124ca84", size = 2410256, upload-time = "2026-03-13T15:22:31.825Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/5f/48c6d7c6e4d02883d0c3de98c46c71d20c53038dfdde79614d0e55f9f163/memray-1.19.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:50d7130bb0c8609176b3b691c8b67fc92805180166e087549a59e7881ae8cf36", size = 2181142, upload-time = "2026-03-13T15:20:26.87Z" }, - { url = "https://files.pythonhosted.org/packages/1d/85/34d5dc497741bf684cfb5f59d58428b6fd4a034e55cb950339ee8f137f9d/memray-1.19.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3643d601c4c1c413a62fb296598ed05dce1e1c3a58ea5c8659ae98ad36ce3a7a", size = 2162529, upload-time = "2026-03-13T15:20:29.187Z" }, - { url = "https://files.pythonhosted.org/packages/95/5f/ca6ab3cd76de6134cbe29f5a6daa77234f216ae9bd8c963beda226a22653/memray-1.19.2-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:661aca0dbf4c448eef93f2f0bd0852eeefe3de2460e8105c2160c86e308beea5", size = 9707355, upload-time = "2026-03-13T15:20:30.941Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c9/4b79508b2cf646ca3fe3c87bdef80cd26362679274b26dab1f4b725ebba0/memray-1.19.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d13f33f1fa76165c5596e73bc45a366d58066be567fb131498cd770fa87f5a02", size = 9938651, upload-time = "2026-03-13T15:20:33.755Z" }, - { url = "https://files.pythonhosted.org/packages/d5/d6/ca9cef1c0aba2245c41aed699a45a748db7b0dd8a9a63484e809b0f8e448/memray-1.19.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74291aa9bbf54ff2ac5df2665c792d490c576720dd2cbad89af53528bda5443f", size = 9327619, upload-time = "2026-03-13T15:20:36.179Z" }, - { url = "https://files.pythonhosted.org/packages/ce/66/572f819ff58d0f0fefeeeeaa7206f192107f39027a92fd90af1c1cbff61b/memray-1.19.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:716a1b2569e049d0cb769015e5be9138bd97bd157e67920cc9e215e011fbb9cd", size = 12158374, upload-time = "2026-03-13T15:20:39.213Z" }, - { url = "https://files.pythonhosted.org/packages/63/bf/b8f28adbd3e1eeeb88e188053a26164b195ebcf66f8af6b30003a83f5660/memray-1.19.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:c8d35a9f5b222165c5aedbfc18b79dc5161a724963a4fca8d1053faa0b571195", size = 2181644, upload-time = "2026-03-13T15:20:41.756Z" }, - { url = "https://files.pythonhosted.org/packages/21/66/0791e5514b475d6300d13ebe87839db1606b2dc2fbe00fecce4da2fb405d/memray-1.19.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3735567011cc22339aee2c59b5fc94d1bdd4a23f9990e02a2c3cccc9c3cf6de4", size = 2164670, upload-time = "2026-03-13T15:20:44.14Z" }, - { url = "https://files.pythonhosted.org/packages/0f/aa/086878e99693b174b0d04d0b267231862fb6a3cfc35cab2920284c2a2e38/memray-1.19.2-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ab78af759eebcb8d8ecef173042515711d2dcc9600d5dd446d1592b24a89b7d9", size = 9777844, upload-time = "2026-03-13T15:20:46.266Z" }, - { url = "https://files.pythonhosted.org/packages/40/a6/40247667e72b5d8322c5dc2ef30513238b3480be1e482faaaf9cc573ff38/memray-1.19.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f3ae7983297d168cdcc2d05cd93a4934b9b6fe0d341a91ac5b71bf45f9cec06c", size = 10021548, upload-time = "2026-03-13T15:20:49.079Z" }, - { url = "https://files.pythonhosted.org/packages/b3/bb/50603e8f7fe950b3f6a6e09a80413a8f25c4a9d360d8b3b027a8841e1fe8/memray-1.19.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08a4316d7a92eb415024b46988844ed0fd44b2d02ca00fa4a21f2481c1f803e6", size = 9400168, upload-time = "2026-03-13T15:20:51.801Z" }, - { url = "https://files.pythonhosted.org/packages/e2/89/a21e0b639496ed59d2a733e60869ff2e685c5a78891474a494e09a17dc7c/memray-1.19.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dbdb14fd31e2a031312755dc76146aeff9d0889e82ccffe231f1f20f50526f57", size = 12234413, upload-time = "2026-03-13T15:20:54.454Z" }, - { url = "https://files.pythonhosted.org/packages/13/4e/8685c202ddd76860cd8fc5f7f552115ea6f317e9f5f16219a56f336e351e/memray-1.19.2-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:22d4482f559ffa91a9727693e7e338856bee5e316f922839bf8b96e0f9b8a4de", size = 2183484, upload-time = "2026-03-13T15:20:56.696Z" }, - { url = "https://files.pythonhosted.org/packages/89/79/602f55d5466f1f587cdddf0324f82752bd0319ea814bc7cca2efb8593bc8/memray-1.19.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fd1476868177ee8d9f7f85e5a085a20cc3c3a8228a23ced72749265885d55ca", size = 2162900, upload-time = "2026-03-13T15:20:58.174Z" }, - { url = "https://files.pythonhosted.org/packages/02/1b/402207971653b9861bbbe449cbed7d82e7bb9b953dd6ac93dd4d78e76fa2/memray-1.19.2-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:23375d50faa199e1c1bc2e89f08691f6812478fddb49a1b82bebe6ef5a56df2c", size = 9731991, upload-time = "2026-03-13T15:21:00.299Z" }, - { url = "https://files.pythonhosted.org/packages/3f/7d/895ce73fcf9ab0a2b675ed49bbc91cbca14bda187e2b4df86ccefeb1c9bc/memray-1.19.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8ef3d8e4fba0b26280b550278a0660554283135cbccc34e2d49ba82a1945eb61", size = 9997104, upload-time = "2026-03-13T15:21:02.959Z" }, - { url = "https://files.pythonhosted.org/packages/a0/b9/586bf51a1321cde736d886ca8ac3d4b1f910e4f3f813d7c8eb22498ee16f/memray-1.19.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4d6cf9597ae5d60f7893a0b7b6b9af9c349121446b3c1e7b9ac1d8b5d45a505", size = 9373508, upload-time = "2026-03-13T15:21:05.945Z" }, - { url = "https://files.pythonhosted.org/packages/5d/f1/7cb51edeeceaaee770d4222e833369fbc927227d27e0a917b5ad6f4b2f85/memray-1.19.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:716a0a0e9048d21da98f9107fa030a76138eb694a16a81ad15eace54fddef4cd", size = 12222756, upload-time = "2026-03-13T15:21:08.9Z" }, - { url = "https://files.pythonhosted.org/packages/34/10/cbf57c122988d6e3bd148aa374e91e0e2f156cc7db1ac6397eb6db3946d1/memray-1.19.2-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:13aa87ad34cc88b3f31f7205e0a4543c391032e8600dc0c0cbf22555ff816d97", size = 2182910, upload-time = "2026-03-13T15:21:11.357Z" }, - { url = "https://files.pythonhosted.org/packages/5c/0e/7979dfe7e2b034431e44e3bab86356d9bc2c4f3ed0eb1594cb0ceb38c859/memray-1.19.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d6b249618a3e4fa8e10291445a2b2dfaf6f188e7cc1765966aac8fb52cb22066", size = 2161575, upload-time = "2026-03-13T15:21:13.051Z" }, - { url = "https://files.pythonhosted.org/packages/f9/92/2f0ca3936cdf4c59bc8c59fc8738ce8854ba24fd8519988f2ece0eba10fa/memray-1.19.2-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:34985e5e638ef8d4d54de8173c5e4481c478930f545bd0eb4738a631beb63d04", size = 9732172, upload-time = "2026-03-13T15:21:15.115Z" }, - { url = "https://files.pythonhosted.org/packages/52/23/de78510b4e3a0668b793d8b5dff03f2af20eef97943ca5b3263effff799c/memray-1.19.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee0fcfafd1e8535bdc0d0ed75bcdd48d436a6f62d467df91871366cbb3bbaebc", size = 9999447, upload-time = "2026-03-13T15:21:18.099Z" }, - { url = "https://files.pythonhosted.org/packages/00/0d/b0e50537470f93bddfa2c134177fe9332c20be44a571588866776ff92b82/memray-1.19.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:846185c393ff0dc6bca55819b1c83b510b77d8d561b7c0c50f4873f69579e35d", size = 9379158, upload-time = "2026-03-13T15:21:21.003Z" }, - { url = "https://files.pythonhosted.org/packages/5c/53/78f6de5c7208821b15cfbbb9da44ab4a5a881a7cc5075f9435a1700320e8/memray-1.19.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8cc31327ed71e9f6ef7e9ed558e764f0e9c3f01da13ad8547734eb65fbeade1d", size = 12226753, upload-time = "2026-03-13T15:21:24.041Z" }, - { url = "https://files.pythonhosted.org/packages/e1/f4/3d8205b9f46657d26d54d1e644f27d09955b737189354a01907d8a08c7e2/memray-1.19.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:410377c0eae8d544421f74b919a18e119279fe1a2fa5ff381404b55aeb4c6514", size = 2184823, upload-time = "2026-03-13T15:21:27.176Z" }, - { url = "https://files.pythonhosted.org/packages/fb/07/7a342801317eff410a8267b55cb7514e156ee1f574e690852eb240bbe9fd/memray-1.19.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a53dc4032581ed075fcb62a4acc0ced14fb90a8269159d4e53dfac7af269c255", size = 2163669, upload-time = "2026-03-13T15:21:29.123Z" }, - { url = "https://files.pythonhosted.org/packages/d4/00/2c342b1472f9f03018bb88c80760cdfa6979404d63c4300c607fd0562607/memray-1.19.2-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:a7630865fbf3823aa2d1a6f7536f7aec88cf8ccf5b2498aad44adbc733f6bd2e", size = 9732615, upload-time = "2026-03-13T15:21:31.038Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ae/2cf960526c9b1f6d46977fc70e11de29ca6b9eafeeb42d1cec7d3bcb056a/memray-1.19.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c23e2b4be22a23cf5cae08854549e3460869a36c5f4bedc739b646ac97da4a60", size = 9979299, upload-time = "2026-03-13T15:21:34.072Z" }, - { url = "https://files.pythonhosted.org/packages/e1/78/73ee3d0ebee3c38fbb2d51766854d2932beec6481063532a6019bf340a2d/memray-1.19.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:95b6c02ca7f8555b5bee1c54c50cbbcf2033e07ebca95dade2ac3a27bb36b320", size = 9375722, upload-time = "2026-03-13T15:21:36.884Z" }, - { url = "https://files.pythonhosted.org/packages/3b/c6/2f02475e85ccd32fa306736986f1f77f99365066ecdc859f5078148ebc40/memray-1.19.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:907470e2684568eb91a993ae69a08b1430494c8f2f6ef489b4b78519d9dae3d0", size = 12220041, upload-time = "2026-03-13T15:21:40.16Z" }, - { url = "https://files.pythonhosted.org/packages/76/12/01bb32188c011e6d802469e04c1d7c8054eb8300164e2269c830f5b26a8e/memray-1.19.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:124138f35fea36c434256c417f1b8cb32f78769f208530c1e56bf2c2b7654120", size = 2201353, upload-time = "2026-03-13T15:21:42.607Z" }, - { url = "https://files.pythonhosted.org/packages/e5/e0/d9b59f8be00f27440f60b95da5db6515a1c44c481651b8d2fa8f3468fc35/memray-1.19.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:240192dc98ff0b3501055521bfd73566d339808b11bd5af10865afe6ae18abef", size = 2180420, upload-time = "2026-03-13T15:21:44.623Z" }, - { url = "https://files.pythonhosted.org/packages/a5/5c/30aca63f4b88dca79ba679675200938652c816edee34c12565d2f17ea936/memray-1.19.2-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:edb7a3c2a9e97fb409b352f6c316598c7c0c3c22732e73704d25b9eb75ae2f2d", size = 9697953, upload-time = "2026-03-13T15:21:47.088Z" }, - { url = "https://files.pythonhosted.org/packages/9f/02/9e4a68bdd5ebc9079f97bdf287cc0ccc51c18e9edc205de7d41648315809/memray-1.19.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b6a43db4c1466446a905a77944813253231ac0269f758c6c6bc03ceb1821c1b6", size = 9944517, upload-time = "2026-03-13T15:21:50.125Z" }, - { url = "https://files.pythonhosted.org/packages/4a/f0/3adad59ebed6841c2f88b43c9b90cc9c03ff086129a8aef3cff23c92d6ac/memray-1.19.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cf951dae8d27d502fbc549f6784460a70cce05b1e71bf5446d8692a74051f14f", size = 9365528, upload-time = "2026-03-13T15:21:53.141Z" }, - { url = "https://files.pythonhosted.org/packages/45/0e/083e00fe74e576b463e7b00e4214b8962f27bd70c5c77e494c0211a77342/memray-1.19.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8033b78232555bb1856b3298bef2898ec8b334d3d465c1822c665206d1fa910a", size = 12143894, upload-time = "2026-03-13T15:21:56.486Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/96/04/5b886a36df947599e0f37cd46e6e44e565299815f044e2303ab2ae9f8870/memray-1.19.3.tar.gz", hash = "sha256:4e0fb29ff0a50c0ec9dc84294d8f2c83419feba561a37628b304c2ae4fe73d03", size = 2417089, upload-time = "2026-04-08T18:49:32.409Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/9a/262e81a1c5dba8c024049cc0d4b72bf695b5be38f92eaed0f3d6a720cf4e/memray-1.19.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:e4a7885ab920df180e40c6dd29b6ac09a0d58d92055a2861372a9d50f9e02ab3", size = 2182755, upload-time = "2026-04-08T18:47:39.098Z" }, + { url = "https://files.pythonhosted.org/packages/81/75/a4331a5ba7f545acfddd6ce8bf13493273adaf52a5b7356f83bac36449c5/memray-1.19.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82ec3b737207ba0185e9a2e1cec775e648839b9ccd9a38cb95256270ea33dd43", size = 2160580, upload-time = "2026-04-08T18:47:41.112Z" }, + { url = "https://files.pythonhosted.org/packages/7c/c3/aacfb92ac6b6fd382c4a409c6c65008b8d80f009ff5f306de0df99c61672/memray-1.19.3-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8203b75c26117564a27b685317ad73cf82a335e643d254c60e0d20215f1461f2", size = 9722985, upload-time = "2026-04-08T18:47:43.244Z" }, + { url = "https://files.pythonhosted.org/packages/40/07/34625d678f9ec222e90fadebe7612b1914e9efcc8d1e7477fe5ed84c8e5e/memray-1.19.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d66e842814a762d022b04d620cfd0a4ba3c6ad5a09148f031c795396c258819b", size = 9954029, upload-time = "2026-04-08T18:47:45.591Z" }, + { url = "https://files.pythonhosted.org/packages/dd/59/cb70f0664f89e6dd30f28a1280c117fa8dd758f0a9adbeadb8cabde3733c/memray-1.19.3-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:507d0f6b1041a9e9966242aa7529212a8053a5c3e3bd02997e5f50a0b6dff637", size = 9341828, upload-time = "2026-04-08T18:47:47.825Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c7/502f279872554bd5eaec4c024b2bafc50f9e22d6e3259850a365e34d7226/memray-1.19.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1e9b975aebae3e1712508971719e4186d1039eb1e0677453ef63d87396526d1b", size = 12176485, upload-time = "2026-04-08T18:47:50.823Z" }, + { url = "https://files.pythonhosted.org/packages/6e/42/20f595239918edb3fd967f47df7b89d1b728c1d04f34c616b78f17e85305/memray-1.19.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:7919d48b8e6df45a1b332fae484a14d427619c123a254ca23468ec232bb4152b", size = 2183379, upload-time = "2026-04-08T18:47:52.846Z" }, + { url = "https://files.pythonhosted.org/packages/53/e7/8371761d845e126bbd3230e0137fc147db5f6c35cd6b6150b86ed80fe34b/memray-1.19.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6d5b1484dd32752dd9a194571dbfe8de175ca7159f4b0a24efc7e954710ea0b0", size = 2161168, upload-time = "2026-04-08T18:47:54.614Z" }, + { url = "https://files.pythonhosted.org/packages/cf/15/5f87e8a2f73c6e7e79c48efbc9d5dd570ffd74754412115b6cd32c43f138/memray-1.19.3-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:c3e9d2c0172ff0419832a510ac6305504712bf268059cdfd6b4e948f6ba1ccf5", size = 9789479, upload-time = "2026-04-08T18:47:56.578Z" }, + { url = "https://files.pythonhosted.org/packages/76/09/32caf5915b487a705fb7c41bfca5dfe65486995615143493e6b43773da8d/memray-1.19.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:96de36ae809eaf8484bdbd937ce890b3b206269f66a7e1dea004fd115a712d24", size = 10035022, upload-time = "2026-04-08T18:47:58.739Z" }, + { url = "https://files.pythonhosted.org/packages/64/2a/e01de8c939018dd99dc61627c7a706f25bec6f1665f071a8482e888b3d76/memray-1.19.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:003bf98ffa7b022ddbac8b832a2c4e63e2a7f67d0c69d38b1712bc3347e7066b", size = 9414903, upload-time = "2026-04-08T18:48:00.888Z" }, + { url = "https://files.pythonhosted.org/packages/38/09/ca69127bba2ecd5d2a9b62de06846c91d46dacb814d329deaf09e601dd7f/memray-1.19.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b49362844937831dc0f324fbad28cfd1cd7006a1e8dc1e950891a3b9cc02dcc4", size = 12252069, upload-time = "2026-04-08T18:48:03.563Z" }, + { url = "https://files.pythonhosted.org/packages/fa/79/095c09f62f2ca527e4b5e71c38e7c9686f06c15a39f69f691428c45bae83/memray-1.19.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:dcbfa513332366544a2fdc74f0e385f3a11a2233ca9de5aac986e396ce0a2293", size = 2185040, upload-time = "2026-04-08T18:48:05.98Z" }, + { url = "https://files.pythonhosted.org/packages/2e/26/8328966c9b1cecbf43e8c96a210178f68fb1df8a62dd4f1735158aa6610b/memray-1.19.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4df9b00262fe48485c2afc4a52c88640d729d3bf999b3c633052d40c0ee970d1", size = 2163887, upload-time = "2026-04-08T18:48:07.455Z" }, + { url = "https://files.pythonhosted.org/packages/1a/eb/6ed7c46c2e6aec4d18926662114e88ba557f2e88c50fd5737b7989d67f3c/memray-1.19.3-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4a710509a5728a6f3b79eca615b538f9fa20452b21c0ba5265bdfb5fd4ff5f1d", size = 9743964, upload-time = "2026-04-08T18:48:09.213Z" }, + { url = "https://files.pythonhosted.org/packages/1c/60/668ad1dd30744564ef2d3e444bf39e10c41f1820240e949d0a3fadea9101/memray-1.19.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:578349f78268d2561275c4fb78c7ebe215f5264ad408d46207795ae58ec5d79e", size = 10013567, upload-time = "2026-04-08T18:48:11.513Z" }, + { url = "https://files.pythonhosted.org/packages/7a/aa/e5e969d50e57ef3ae41c6996626381afe3c9933d1924844d326f05240596/memray-1.19.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbbe64058ea329e7ff4f2c8067e6400b7db7d44a3f897a36c21f1a54e9b0c1ee", size = 9387646, upload-time = "2026-04-08T18:48:13.803Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ea/b23b30e31f365687004df304b9e46f19de4f5b860e78b363dd5d51f618f9/memray-1.19.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1a60d44b18ac5c1f6dde15e5d5f2dc75b5dfa55f450b5b682bbb1274564bcb41", size = 12237978, upload-time = "2026-04-08T18:48:16.478Z" }, + { url = "https://files.pythonhosted.org/packages/d7/fd/e5637a682cb0af3b9e79017b98b8db5f4bf65c24d9e9fea10dec2495ca13/memray-1.19.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:1c7474aa70145eb2be1479b5465022d41a01467dbe4f8487d4fb4c3d38fd6ba9", size = 2184361, upload-time = "2026-04-08T18:48:18.775Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/fcd190a9de788363856d475b595b8a831fefc5c0ee282d27e849dda57d1c/memray-1.19.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ee7f3f0e3f7ee4f5c82692f886ffbabddc885bc9ab3a507732a1aa2155e16ed1", size = 2162568, upload-time = "2026-04-08T18:48:20.691Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/72d70d93f911974652e19f50024142ca674cb19d4f34a91cb2b2b3e065af/memray-1.19.3-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:c1842b2a0033ca44d11c40c9afd5b6a8a29f00e53ea151da4bb81f6dfd194b79", size = 9743474, upload-time = "2026-04-08T18:48:22.544Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ed/d2390f02d978e31666f2821574940f553f27fd1cf38003b592038441a9b8/memray-1.19.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51bea540d8a79c83720bc74d5f9508911572dd77b5fb0fc46d2fe287d96a2dc7", size = 10012845, upload-time = "2026-04-08T18:48:25.455Z" }, + { url = "https://files.pythonhosted.org/packages/34/0f/78eb8d0973e11d0780fabbd048cab184bd4f28788f211d6d7eb97aed7d04/memray-1.19.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:502b07e65a972c3d47e39b0c9f706189f8b667953f68f80672f0537d2ffd9633", size = 9391464, upload-time = "2026-04-08T18:48:28.192Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b7/e209d3fa09f096d7d4b7dd3be7948cc36879aa1ef75a349cf88a7ad74d00/memray-1.19.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e9dc493402446ff495edaa90c6b587a32ace14e2d4a022051458b535a029cada", size = 12244789, upload-time = "2026-04-08T18:48:30.418Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d5/36ae02ef5c55cc9d9febb89fb39b78135eaf76d71458703d91cde401142f/memray-1.19.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f62ca641421c0856b38b95c2bc39bdd1493330a94d526efd817d2135a2c1600b", size = 2186101, upload-time = "2026-04-08T18:48:32.663Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e2/b08b27e84fff1ea039508baaac252c3facbd3a81930e1a8108fd3db1dfcb/memray-1.19.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a4335e51dac85891434de4de603f58be1296c2fa463dbf4075b7230820c2a58b", size = 2164551, upload-time = "2026-04-08T18:48:34.86Z" }, + { url = "https://files.pythonhosted.org/packages/34/48/3a0422d71f43a361782517f6c0b93bdc32e4b211aaa7290c3038a91f991b/memray-1.19.3-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:03f0e1c3584e19951471413f858b70ecb4f1b5d2e3e4bf0c147c104ac79a8548", size = 9743615, upload-time = "2026-04-08T18:48:36.894Z" }, + { url = "https://files.pythonhosted.org/packages/4b/52/f9ee7911819085e174fe07d1bab27691dc1486be39bded35baebda792069/memray-1.19.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:90e634b79be3c332d0d0ab3e1da6ccce6acd20c5fa847f505230ff49d9450a62", size = 9994310, upload-time = "2026-04-08T18:48:39.588Z" }, + { url = "https://files.pythonhosted.org/packages/aa/64/a1f75b5a105cc325b7719a4ed1690c45e751098d17a45902668fd9e0af67/memray-1.19.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4be4535a98c2c93c3195a769c342da12564c8bfd4f5056c3527d237845fd354", size = 9386965, upload-time = "2026-04-08T18:48:41.849Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ad/01178b4c2f61b1b64995f0de9ada899f91abe4de67db793df7d428834456/memray-1.19.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2e3c6433d246063cc33d1ae25104120643492f0750ed5f7ac660d92aba064da6", size = 12238366, upload-time = "2026-04-08T18:48:44.14Z" }, + { url = "https://files.pythonhosted.org/packages/e8/21/8034941ba5aeb9f73e05becc40661af54d548c2047e4058948a3d94acd5d/memray-1.19.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e034252330961dadfe83ac0f111c9a1d3d8fb8f1358c9b992ed664b6a8b2d2a9", size = 2202163, upload-time = "2026-04-08T18:48:46.689Z" }, + { url = "https://files.pythonhosted.org/packages/c2/62/ba34b1cf5a8c89f6f4b24e8471a6e6e011e50a86a0d697407320eeaf5b65/memray-1.19.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6ee43e6132fd457d0865b6a1d0de3acdb220e897625a32a0d609beaebb8abd20", size = 2181584, upload-time = "2026-04-08T18:48:48.516Z" }, + { url = "https://files.pythonhosted.org/packages/89/f7/901e83b6bf71d968bcfdcd5b081d8c5940ec7b5b9d28d67d5d4027d72529/memray-1.19.3-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:78eacb4e1c1b66cf7c4dd6dd27b0c88fb4598b63f3096e014d0a2b91ab70fb6f", size = 9706760, upload-time = "2026-04-08T18:48:50.161Z" }, + { url = "https://files.pythonhosted.org/packages/9e/18/a556d0e93d69786edd5c62b8d71bc04f8454b7655b23351a3d95a6d0bc62/memray-1.19.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7c33442360bba89fd34c4b985cd505abbf2bbec6a40bdfdf50e1981a4afd9625", size = 9958651, upload-time = "2026-04-08T18:48:52.88Z" }, + { url = "https://files.pythonhosted.org/packages/0a/20/f9fea6a3bb8cbc835567ddf89eb524c6fb4c01130b9a4a2b88e65d0c7aca/memray-1.19.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:63868a883a6ca926ed1e9200a0d8f3bedde6e1af2a8d4b6ef0cf85160a3b28cd", size = 9382102, upload-time = "2026-04-08T18:48:55.787Z" }, + { url = "https://files.pythonhosted.org/packages/41/4a/035e5bdeddbd51a2ba1be53f1fc979268c8ce51640b042db4cbee305849b/memray-1.19.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:96ee0a76e4ca57e2ad48a8eccc28531503029884a791bb3556cc9ddac74e148d", size = 12162201, upload-time = "2026-04-08T18:48:57.952Z" }, ] [[package]] @@ -14590,21 +14599,21 @@ wheels = [ [[package]] name = "microsoft-kiota-abstractions" -version = "1.9.10" +version = "1.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, { name = "std-uritemplate" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/45/e1/39de28380fc0eddf12f66099469fb7561bc38f577ea06e3a074751ebbcd9/microsoft_kiota_abstractions-1.9.10.tar.gz", hash = "sha256:8eb62d64c35ad0eeb4e8bcdbb143c0b308dc4a494e757f8e44cb959d34f44ecf", size = 24473, upload-time = "2026-03-12T17:27:15.398Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/28/d22b26bc7b6d6947250de92f87d536d7e271de638660c9571821efac3302/microsoft_kiota_abstractions-1.10.1.tar.gz", hash = "sha256:ff922f6ac7e4a538d253e5bacb18f5c8c837d0273fb436eec2f0500c70230d96", size = 24465, upload-time = "2026-04-08T16:16:53.598Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/59/bf0cb26c80fbd3fa882df8474ad87e9dbd742656c376388c427c4e314171/microsoft_kiota_abstractions-1.9.10-py3-none-any.whl", hash = "sha256:cd169067ebe48e6feea1258630807034239e0c61c2abe5fd66896a58177e8f05", size = 44462, upload-time = "2026-03-12T17:27:16.532Z" }, + { url = "https://files.pythonhosted.org/packages/37/83/a099731bb11df9f3e2c39364a94579523aaa20c315a89ee69d8b7c851436/microsoft_kiota_abstractions-1.10.1-py3-none-any.whl", hash = "sha256:31d3f0581884eb221899f355834d86ceba6289b4b9df23e63d01f02aac6c4d0b", size = 44456, upload-time = "2026-04-08T16:16:54.646Z" }, ] [[package]] name = "microsoft-kiota-authentication-azure" -version = "1.9.10" +version = "1.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -14613,14 +14622,14 @@ dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d5/53/7760f979c141ec590f0c1cfcb92b3e410eb2909cc19feb42f3fce78db171/microsoft_kiota_authentication_azure-1.9.10.tar.gz", hash = "sha256:b9f10a9fa86e36114abfee448d2dab91a502d6a55d349a306e2e41a1218fe1ad", size = 4999, upload-time = "2026-03-12T17:27:26.323Z" } +sdist = { url = "https://files.pythonhosted.org/packages/52/b6/8bccdf62dedae77ad2bc77f27292880420d5190cea163d77312ee8e69551/microsoft_kiota_authentication_azure-1.10.1.tar.gz", hash = "sha256:7de150868dab399b4ac36cb17a0ae726ff616079cee9b0a72e7d5e06f5c652e9", size = 4992, upload-time = "2026-04-08T16:17:05.891Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/4a/e7852f9358d897ada1eec4e825c815761befe36df4defa79f1ae6c7b588c/microsoft_kiota_authentication_azure-1.9.10-py3-none-any.whl", hash = "sha256:b5d98b0d17173c61c0c7ab4274ea4ca69253b3c13424137758034506694964e9", size = 6961, upload-time = "2026-03-12T17:27:27.238Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/325df634219d113d2418c76883f5cf9debf0ebb1ff04fb04438f7bc56284/microsoft_kiota_authentication_azure-1.10.1-py3-none-any.whl", hash = "sha256:0f82de6dbfc55d3b1df5c42d5c82631014f9db9c45ba0d0a2cdf13853f78649d", size = 6953, upload-time = "2026-04-08T16:17:06.548Z" }, ] [[package]] name = "microsoft-kiota-http" -version = "1.9.10" +version = "1.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx", extra = ["http2"] }, @@ -14628,33 +14637,33 @@ dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a7/e5/20972b620bd8cca086c284e97b285d437c108a23fee122ad7b92bd246c1a/microsoft_kiota_http-1.9.10.tar.gz", hash = "sha256:af1838d091f76426c974897357093ed977ce66f1d808cb161c190de873bb5833", size = 21493, upload-time = "2026-03-12T17:27:35.393Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/2c/564a5cd50eb90f05bad0c970f832ad71d382bbe9003f0272c859492a01f7/microsoft_kiota_http-1.10.1.tar.gz", hash = "sha256:ee8eec8e35c467a22aedbe5f9b6699bc79411cc8f207705044e58ced22c588da", size = 21487, upload-time = "2026-04-08T16:17:15.585Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/f4/78ce18330a626138b2ff6bb62574adac01e8b9ee87c1349ddfeb9cab0556/microsoft_kiota_http-1.9.10-py3-none-any.whl", hash = "sha256:6127032c8d94f8607e4d36d0822b88bc8689ab368b4c00d6c7beb7d2d0f2ab10", size = 31960, upload-time = "2026-03-12T17:27:36.1Z" }, + { url = "https://files.pythonhosted.org/packages/11/ea/4ee59599c57561663d9f4d44e5de674f77ad1f7432242aba042768403c31/microsoft_kiota_http-1.10.1-py3-none-any.whl", hash = "sha256:77944e25594a65cced34702fa953bfd631eec1492ae4bef3d398eabc4ed8a6bc", size = 31951, upload-time = "2026-04-08T16:17:16.319Z" }, ] [[package]] name = "microsoft-kiota-serialization-json" -version = "1.9.10" +version = "1.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "microsoft-kiota-abstractions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/67/0e/55afd533a764ba77da988b7ca4242c84867a3a25f2ff0bf4c2b24b5e8fca/microsoft_kiota_serialization_json-1.9.10.tar.gz", hash = "sha256:6063028f30dd67afa2db20a72d9bde5e5d26d468f8bdedadd1445cf7c7630e17", size = 9746, upload-time = "2026-03-12T17:27:53.015Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7a/ea/36cee5e86b072911da8a4f8b178d101779507381ddb52b34f6e175e2686a/microsoft_kiota_serialization_json-1.10.1.tar.gz", hash = "sha256:71792246fd1f28f73ffb5d916a63763062f84055f197d282ed59c37181ba09c9", size = 9915, upload-time = "2026-04-08T16:17:34.568Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/56/d14c0185c8092abde1a60ad2bdd4480bb2ddb551ce71c6de1e6133a4d8d1/microsoft_kiota_serialization_json-1.9.10-py3-none-any.whl", hash = "sha256:0545ae910160b19caaa8c30c90c7416e1966294fbd6cc5af01f0e116a18f223a", size = 11452, upload-time = "2026-03-12T17:27:53.909Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c6/39c3c653dee9dc36b879f05a1ad270aa218fd7434ec866b3e0b8942f56e9/microsoft_kiota_serialization_json-1.10.1-py3-none-any.whl", hash = "sha256:42b56b49afb412e77dbcdd825660723f1a9355fb438f3e2dcb7a161670b17499", size = 11600, upload-time = "2026-04-08T16:17:35.274Z" }, ] [[package]] name = "microsoft-kiota-serialization-text" -version = "1.9.10" +version = "1.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "microsoft-kiota-abstractions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/a6/28a4a8d5c01f08e363135fc9585cab3c02d1b1a69c3c16032e6abb35dfed/microsoft_kiota_serialization_text-1.9.10.tar.gz", hash = "sha256:cfc433c2a95ea3c3ec43c8b09002fbf65c998c5c0571205df161fe0e9d5d8de7", size = 7326, upload-time = "2026-03-12T17:28:01.621Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/d0/a3f5087c9eab68c581e607287813498ca4c0f324c1ded31251aa9a2ed0df/microsoft_kiota_serialization_text-1.10.1.tar.gz", hash = "sha256:bb2502cf09b740345c4b221d1a38ffb14667a8dc8e572092de1b3ffd80f47732", size = 7316, upload-time = "2026-04-08T16:17:44.312Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/bf/dd36e4a6d1cff3f2d30f03e2479cd38210e32d4715bb6a9f0e2737f13604/microsoft_kiota_serialization_text-1.9.10-py3-none-any.whl", hash = "sha256:742890cfd4450d12f58d42da7cfa474fe1ee5d6442e016bf70ab76e5c876c0ea", size = 8896, upload-time = "2026-03-12T17:28:02.328Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e9/330603879b363b2bb6ffed81e43ab9c619c6d39d67f285be0fc5b4e6913e/microsoft_kiota_serialization_text-1.10.1-py3-none-any.whl", hash = "sha256:43e3d4e8ae4866440c031ae5dbf6d63a00a38ec62a61ac7eafc047de31b20269", size = 8887, upload-time = "2026-04-08T16:17:44.947Z" }, ] [[package]] @@ -14785,11 +14794,11 @@ wheels = [ [[package]] name = "more-itertools" -version = "11.0.1" +version = "11.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/24/e0acc4bf54cba50c1d432c70a72a3df96db4a321b2c4c68432a60759044f/more_itertools-11.0.1.tar.gz", hash = "sha256:fefaf25b7ab08f0b45fa9f1892cae93b9fc0089ef034d39213bce15f1cc9e199", size = 144739, upload-time = "2026-04-02T16:17:45.061Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/f7/139d22fef48ac78127d18e01d80cf1be40236ae489769d17f35c3d425293/more_itertools-11.0.2.tar.gz", hash = "sha256:392a9e1e362cbc106a2457d37cabf9b36e5e12efd4ebff1654630e76597df804", size = 144659, upload-time = "2026-04-09T15:01:33.297Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/f4/5e52c7319b8087acef603ed6e50dc325c02eaa999355414830468611f13c/more_itertools-11.0.1-py3-none-any.whl", hash = "sha256:eaf287826069452a8f61026c597eae2428b2d1ba2859083abbf240b46842ce6d", size = 72182, upload-time = "2026-04-02T16:17:43.724Z" }, + { url = "https://files.pythonhosted.org/packages/cb/98/6af411189d9413534c3eb691182bff1f5c6d44ed2f93f2edfe52a1bbceb8/more_itertools-11.0.2-py3-none-any.whl", hash = "sha256:6e35b35f818b01f691643c6c611bc0902f2e92b46c18fffa77ae1e7c46e912e4", size = 71939, upload-time = "2026-04-09T15:01:32.21Z" }, ] [[package]] @@ -14840,16 +14849,16 @@ wheels = [ [[package]] name = "msal" -version = "1.35.1" +version = "1.36.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyjwt", extra = ["crypto"] }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3c/aa/5a646093ac218e4a329391d5a31e5092a89db7d2ef1637a90b82cd0b6f94/msal-1.35.1.tar.gz", hash = "sha256:70cac18ab80a053bff86219ba64cfe3da1f307c74b009e2da57ef040eb1b5656", size = 165658, upload-time = "2026-03-04T23:38:51.812Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/cb/b02b0f748ac668922364ccb3c3bff5b71628a05f5adfec2ba2a5c3031483/msal-1.36.0.tar.gz", hash = "sha256:3f6a4af2b036b476a4215111c4297b4e6e236ed186cd804faefba23e4990978b", size = 174217, upload-time = "2026-04-09T10:20:33.525Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/86/16815fddf056ca998853c6dc525397edf0b43559bb4073a80d2bc7fe8009/msal-1.35.1-py3-none-any.whl", hash = "sha256:8f4e82f34b10c19e326ec69f44dc6b30171f2f7098f3720ea8a9f0c11832caa3", size = 119909, upload-time = "2026-03-04T23:38:50.452Z" }, + { url = "https://files.pythonhosted.org/packages/2a/d3/414d1f0a5f6f4fe5313c2b002c54e78a3332970feb3f5fed14237aa17064/msal-1.36.0-py3-none-any.whl", hash = "sha256:36ecac30e2ff4322d956029aabce3c82301c29f0acb1ad89b94edcabb0e58ec4", size = 121547, upload-time = "2026-04-09T10:20:32.336Z" }, ] [[package]] @@ -14956,58 +14965,58 @@ wheels = [ [[package]] name = "msgspec" -version = "0.20.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ea/9c/bfbd12955a49180cbd234c5d29ec6f74fe641698f0cd9df154a854fc8a15/msgspec-0.20.0.tar.gz", hash = "sha256:692349e588fde322875f8d3025ac01689fead5901e7fb18d6870a44519d62a29", size = 317862, upload-time = "2025-11-24T03:56:28.934Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/5e/151883ba2047cca9db8ed2f86186b054ad200bc231352df15b0c1dd75b1f/msgspec-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:23a6ec2a3b5038c233b04740a545856a068bc5cb8db184ff493a58e08c994fbf", size = 195191, upload-time = "2025-11-24T03:55:08.549Z" }, - { url = "https://files.pythonhosted.org/packages/50/88/a795647672f547c983eff0823b82aaa35db922c767e1b3693e2dcf96678d/msgspec-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cde2c41ed3eaaef6146365cb0d69580078a19f974c6cb8165cc5dcd5734f573e", size = 188513, upload-time = "2025-11-24T03:55:10.008Z" }, - { url = "https://files.pythonhosted.org/packages/4b/91/eb0abb0e0de142066cebfe546dc9140c5972ea824aa6ff507ad0b6a126ac/msgspec-0.20.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5da0daa782f95d364f0d95962faed01e218732aa1aa6cad56b25a5d2092e75a4", size = 216370, upload-time = "2025-11-24T03:55:11.566Z" }, - { url = "https://files.pythonhosted.org/packages/15/2a/48e41d9ef0a24b1c6e67cbd94a676799e0561bfbc163be1aaaff5ca853f5/msgspec-0.20.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9369d5266144bef91be2940a3821e03e51a93c9080fde3ef72728c3f0a3a8bb7", size = 222653, upload-time = "2025-11-24T03:55:13.159Z" }, - { url = "https://files.pythonhosted.org/packages/90/c9/14b825df203d980f82a623450d5f39e7f7a09e6e256c52b498ea8f29d923/msgspec-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:90fb865b306ca92c03964a5f3d0cd9eb1adda14f7e5ac7943efd159719ea9f10", size = 222337, upload-time = "2025-11-24T03:55:14.777Z" }, - { url = "https://files.pythonhosted.org/packages/8b/d7/39a5c3ddd294f587d6fb8efccc8361b6aa5089974015054071e665c9d24b/msgspec-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e8112cd48b67dfc0cfa49fc812b6ce7eb37499e1d95b9575061683f3428975d3", size = 225565, upload-time = "2025-11-24T03:55:16.4Z" }, - { url = "https://files.pythonhosted.org/packages/98/bd/5db3c14d675ee12842afb9b70c94c64f2c873f31198c46cbfcd7dffafab0/msgspec-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:666b966d503df5dc27287675f525a56b6e66a2b8e8ccd2877b0c01328f19ae6c", size = 188412, upload-time = "2025-11-24T03:55:17.747Z" }, - { url = "https://files.pythonhosted.org/packages/76/c7/06cc218bc0c86f0c6c6f34f7eeea6cfb8b835070e8031e3b0ef00f6c7c69/msgspec-0.20.0-cp310-cp310-win_arm64.whl", hash = "sha256:099e3e85cd5b238f2669621be65f0728169b8c7cb7ab07f6137b02dc7feea781", size = 173951, upload-time = "2025-11-24T03:55:19.335Z" }, - { url = "https://files.pythonhosted.org/packages/03/59/fdcb3af72f750a8de2bcf39d62ada70b5eb17b06d7f63860e0a679cb656b/msgspec-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:09e0efbf1ac641fedb1d5496c59507c2f0dc62a052189ee62c763e0aae217520", size = 193345, upload-time = "2025-11-24T03:55:20.613Z" }, - { url = "https://files.pythonhosted.org/packages/5a/15/3c225610da9f02505d37d69a77f4a2e7daae2a125f99d638df211ba84e59/msgspec-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23ee3787142e48f5ee746b2909ce1b76e2949fbe0f97f9f6e70879f06c218b54", size = 186867, upload-time = "2025-11-24T03:55:22.4Z" }, - { url = "https://files.pythonhosted.org/packages/81/36/13ab0c547e283bf172f45491edfdea0e2cecb26ae61e3a7b1ae6058b326d/msgspec-0.20.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:81f4ac6f0363407ac0465eff5c7d4d18f26870e00674f8fcb336d898a1e36854", size = 215351, upload-time = "2025-11-24T03:55:23.958Z" }, - { url = "https://files.pythonhosted.org/packages/6b/96/5c095b940de3aa6b43a71ec76275ac3537b21bd45c7499b5a17a429110fa/msgspec-0.20.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb4d873f24ae18cd1334f4e37a178ed46c9d186437733351267e0a269bdf7e53", size = 219896, upload-time = "2025-11-24T03:55:25.356Z" }, - { url = "https://files.pythonhosted.org/packages/98/7a/81a7b5f01af300761087b114dafa20fb97aed7184d33aab64d48874eb187/msgspec-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b92b8334427b8393b520c24ff53b70f326f79acf5f74adb94fd361bcff8a1d4e", size = 220389, upload-time = "2025-11-24T03:55:26.99Z" }, - { url = "https://files.pythonhosted.org/packages/70/c0/3d0cce27db9a9912421273d49eab79ce01ecd2fed1a2f1b74af9b445f33c/msgspec-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:562c44b047c05cc0384e006fae7a5e715740215c799429e0d7e3e5adf324285a", size = 223348, upload-time = "2025-11-24T03:55:28.311Z" }, - { url = "https://files.pythonhosted.org/packages/89/5e/406b7d578926b68790e390d83a1165a9bfc2d95612a1a9c1c4d5c72ea815/msgspec-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:d1dcc93a3ce3d3195985bfff18a48274d0b5ffbc96fa1c5b89da6f0d9af81b29", size = 188713, upload-time = "2025-11-24T03:55:29.553Z" }, - { url = "https://files.pythonhosted.org/packages/47/87/14fe2316624ceedf76a9e94d714d194cbcb699720b210ff189f89ca4efd7/msgspec-0.20.0-cp311-cp311-win_arm64.whl", hash = "sha256:aa387aa330d2e4bd69995f66ea8fdc87099ddeedf6fdb232993c6a67711e7520", size = 174229, upload-time = "2025-11-24T03:55:31.107Z" }, - { url = "https://files.pythonhosted.org/packages/d9/6f/1e25eee957e58e3afb2a44b94fa95e06cebc4c236193ed0de3012fff1e19/msgspec-0.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2aba22e2e302e9231e85edc24f27ba1f524d43c223ef5765bd8624c7df9ec0a5", size = 196391, upload-time = "2025-11-24T03:55:32.677Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ee/af51d090ada641d4b264992a486435ba3ef5b5634bc27e6eb002f71cef7d/msgspec-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:716284f898ab2547fedd72a93bb940375de9fbfe77538f05779632dc34afdfde", size = 188644, upload-time = "2025-11-24T03:55:33.934Z" }, - { url = "https://files.pythonhosted.org/packages/49/d6/9709ee093b7742362c2934bfb1bbe791a1e09bed3ea5d8a18ce552fbfd73/msgspec-0.20.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:558ed73315efa51b1538fa8f1d3b22c8c5ff6d9a2a62eff87d25829b94fc5054", size = 218852, upload-time = "2025-11-24T03:55:35.575Z" }, - { url = "https://files.pythonhosted.org/packages/5c/a2/488517a43ccf5a4b6b6eca6dd4ede0bd82b043d1539dd6bb908a19f8efd3/msgspec-0.20.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:509ac1362a1d53aa66798c9b9fd76872d7faa30fcf89b2fba3bcbfd559d56eb0", size = 224937, upload-time = "2025-11-24T03:55:36.859Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e8/49b832808aa23b85d4f090d1d2e48a4e3834871415031ed7c5fe48723156/msgspec-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1353c2c93423602e7dea1aa4c92f3391fdfc25ff40e0bacf81d34dbc68adb870", size = 222858, upload-time = "2025-11-24T03:55:38.187Z" }, - { url = "https://files.pythonhosted.org/packages/9f/56/1dc2fa53685dca9c3f243a6cbecd34e856858354e455b77f47ebd76cf5bf/msgspec-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cb33b5eb5adb3c33d749684471c6a165468395d7aa02d8867c15103b81e1da3e", size = 227248, upload-time = "2025-11-24T03:55:39.496Z" }, - { url = "https://files.pythonhosted.org/packages/5a/51/aba940212c23b32eedce752896205912c2668472ed5b205fc33da28a6509/msgspec-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:fb1d934e435dd3a2b8cf4bbf47a8757100b4a1cfdc2afdf227541199885cdacb", size = 190024, upload-time = "2025-11-24T03:55:40.829Z" }, - { url = "https://files.pythonhosted.org/packages/41/ad/3b9f259d94f183daa9764fef33fdc7010f7ecffc29af977044fa47440a83/msgspec-0.20.0-cp312-cp312-win_arm64.whl", hash = "sha256:00648b1e19cf01b2be45444ba9dc961bd4c056ffb15706651e64e5d6ec6197b7", size = 175390, upload-time = "2025-11-24T03:55:42.05Z" }, - { url = "https://files.pythonhosted.org/packages/8a/d1/b902d38b6e5ba3bdddbec469bba388d647f960aeed7b5b3623a8debe8a76/msgspec-0.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c1ff8db03be7598b50dd4b4a478d6fe93faae3bd54f4f17aa004d0e46c14c46", size = 196463, upload-time = "2025-11-24T03:55:43.405Z" }, - { url = "https://files.pythonhosted.org/packages/57/b6/eff0305961a1d9447ec2b02f8c73c8946f22564d302a504185b730c9a761/msgspec-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f6532369ece217fd37c5ebcfd7e981f2615628c21121b7b2df9d3adcf2fd69b8", size = 188650, upload-time = "2025-11-24T03:55:44.761Z" }, - { url = "https://files.pythonhosted.org/packages/99/93/f2ec1ae1de51d3fdee998a1ede6b2c089453a2ee82b5c1b361ed9095064a/msgspec-0.20.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9a1697da2f85a751ac3cc6a97fceb8e937fc670947183fb2268edaf4016d1ee", size = 218834, upload-time = "2025-11-24T03:55:46.441Z" }, - { url = "https://files.pythonhosted.org/packages/28/83/36557b04cfdc317ed8a525c4993b23e43a8fbcddaddd78619112ca07138c/msgspec-0.20.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7fac7e9c92eddcd24c19d9e5f6249760941485dff97802461ae7c995a2450111", size = 224917, upload-time = "2025-11-24T03:55:48.06Z" }, - { url = "https://files.pythonhosted.org/packages/8f/56/362037a1ed5be0b88aced59272442c4b40065c659700f4b195a7f4d0ac88/msgspec-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f953a66f2a3eb8d5ea64768445e2bb301d97609db052628c3e1bcb7d87192a9f", size = 222821, upload-time = "2025-11-24T03:55:49.388Z" }, - { url = "https://files.pythonhosted.org/packages/92/75/fa2370ec341cedf663731ab7042e177b3742645c5dd4f64dc96bd9f18a6b/msgspec-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:247af0313ae64a066d3aea7ba98840f6681ccbf5c90ba9c7d17f3e39dbba679c", size = 227227, upload-time = "2025-11-24T03:55:51.125Z" }, - { url = "https://files.pythonhosted.org/packages/f1/25/5e8080fe0117f799b1b68008dc29a65862077296b92550632de015128579/msgspec-0.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:67d5e4dfad52832017018d30a462604c80561aa62a9d548fc2bd4e430b66a352", size = 189966, upload-time = "2025-11-24T03:55:52.458Z" }, - { url = "https://files.pythonhosted.org/packages/79/b6/63363422153937d40e1cb349c5081338401f8529a5a4e216865decd981bf/msgspec-0.20.0-cp313-cp313-win_arm64.whl", hash = "sha256:91a52578226708b63a9a13de287b1ec3ed1123e4a088b198143860c087770458", size = 175378, upload-time = "2025-11-24T03:55:53.721Z" }, - { url = "https://files.pythonhosted.org/packages/bb/18/62dc13ab0260c7d741dda8dc7f481495b93ac9168cd887dda5929880eef8/msgspec-0.20.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:eead16538db1b3f7ec6e3ed1f6f7c5dec67e90f76e76b610e1ffb5671815633a", size = 196407, upload-time = "2025-11-24T03:55:55.001Z" }, - { url = "https://files.pythonhosted.org/packages/dd/1d/b9949e4ad6953e9f9a142c7997b2f7390c81e03e93570c7c33caf65d27e1/msgspec-0.20.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:703c3bb47bf47801627fb1438f106adbfa2998fe586696d1324586a375fca238", size = 188889, upload-time = "2025-11-24T03:55:56.311Z" }, - { url = "https://files.pythonhosted.org/packages/1e/19/f8bb2dc0f1bfe46cc7d2b6b61c5e9b5a46c62298e8f4d03bbe499c926180/msgspec-0.20.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6cdb227dc585fb109305cee0fd304c2896f02af93ecf50a9c84ee54ee67dbb42", size = 219691, upload-time = "2025-11-24T03:55:57.908Z" }, - { url = "https://files.pythonhosted.org/packages/b8/8e/6b17e43f6eb9369d9858ee32c97959fcd515628a1df376af96c11606cf70/msgspec-0.20.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:27d35044dd8818ac1bd0fedb2feb4fbdff4e3508dd7c5d14316a12a2d96a0de0", size = 224918, upload-time = "2025-11-24T03:55:59.322Z" }, - { url = "https://files.pythonhosted.org/packages/1c/db/0e833a177db1a4484797adba7f429d4242585980b90882cc38709e1b62df/msgspec-0.20.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b4296393a29ee42dd25947981c65506fd4ad39beaf816f614146fa0c5a6c91ae", size = 223436, upload-time = "2025-11-24T03:56:00.716Z" }, - { url = "https://files.pythonhosted.org/packages/c3/30/d2ee787f4c918fd2b123441d49a7707ae9015e0e8e1ab51aa7967a97b90e/msgspec-0.20.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:205fbdadd0d8d861d71c8f3399fe1a82a2caf4467bc8ff9a626df34c12176980", size = 227190, upload-time = "2025-11-24T03:56:02.371Z" }, - { url = "https://files.pythonhosted.org/packages/ff/37/9c4b58ff11d890d788e700b827db2366f4d11b3313bf136780da7017278b/msgspec-0.20.0-cp314-cp314-win_amd64.whl", hash = "sha256:7dfebc94fe7d3feec6bc6c9df4f7e9eccc1160bb5b811fbf3e3a56899e398a6b", size = 193950, upload-time = "2025-11-24T03:56:03.668Z" }, - { url = "https://files.pythonhosted.org/packages/e9/4e/cab707bf2fa57408e2934e5197fc3560079db34a1e3cd2675ff2e47e07de/msgspec-0.20.0-cp314-cp314-win_arm64.whl", hash = "sha256:2ad6ae36e4a602b24b4bf4eaf8ab5a441fec03e1f1b5931beca8ebda68f53fc0", size = 179018, upload-time = "2025-11-24T03:56:05.038Z" }, - { url = "https://files.pythonhosted.org/packages/4c/06/3da3fc9aaa55618a8f43eb9052453cfe01f82930bca3af8cea63a89f3a11/msgspec-0.20.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f84703e0e6ef025663dd1de828ca028774797b8155e070e795c548f76dde65d5", size = 200389, upload-time = "2025-11-24T03:56:06.375Z" }, - { url = "https://files.pythonhosted.org/packages/83/3b/cc4270a5ceab40dfe1d1745856951b0a24fd16ac8539a66ed3004a60c91e/msgspec-0.20.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7c83fc24dd09cf1275934ff300e3951b3adc5573f0657a643515cc16c7dee131", size = 193198, upload-time = "2025-11-24T03:56:07.742Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ae/4c7905ac53830c8e3c06fdd60e3cdcfedc0bbc993872d1549b84ea21a1bd/msgspec-0.20.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f13ccb1c335a124e80c4562573b9b90f01ea9521a1a87f7576c2e281d547f56", size = 225973, upload-time = "2025-11-24T03:56:09.18Z" }, - { url = "https://files.pythonhosted.org/packages/d9/da/032abac1de4d0678d99eaeadb1323bd9d247f4711c012404ba77ed6f15ca/msgspec-0.20.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17c2b5ca19f19306fc83c96d85e606d2cc107e0caeea85066b5389f664e04846", size = 229509, upload-time = "2025-11-24T03:56:10.898Z" }, - { url = "https://files.pythonhosted.org/packages/69/52/fdc7bdb7057a166f309e0b44929e584319e625aaba4771b60912a9321ccd/msgspec-0.20.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d931709355edabf66c2dd1a756b2d658593e79882bc81aae5964969d5a291b63", size = 230434, upload-time = "2025-11-24T03:56:12.48Z" }, - { url = "https://files.pythonhosted.org/packages/cb/fe/1dfd5f512b26b53043884e4f34710c73e294e7cc54278c3fe28380e42c37/msgspec-0.20.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:565f915d2e540e8a0c93a01ff67f50aebe1f7e22798c6a25873f9fda8d1325f8", size = 231758, upload-time = "2025-11-24T03:56:13.765Z" }, - { url = "https://files.pythonhosted.org/packages/97/f6/9ba7121b8e0c4e0beee49575d1dbc804e2e72467692f0428cf39ceba1ea5/msgspec-0.20.0-cp314-cp314t-win_amd64.whl", hash = "sha256:726f3e6c3c323f283f6021ebb6c8ccf58d7cd7baa67b93d73bfbe9a15c34ab8d", size = 206540, upload-time = "2025-11-24T03:56:15.029Z" }, - { url = "https://files.pythonhosted.org/packages/c8/3e/c5187de84bb2c2ca334ab163fcacf19a23ebb1d876c837f81a1b324a15bf/msgspec-0.20.0-cp314-cp314t-win_arm64.whl", hash = "sha256:93f23528edc51d9f686808a361728e903d6f2be55c901d6f5c92e44c6d546bfc", size = 183011, upload-time = "2025-11-24T03:56:16.442Z" }, +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/ae/d8fab0915716e70910012c0410d16b5eedf542493d19aa80c155215208bf/msgspec-0.21.0.tar.gz", hash = "sha256:9a37c1fb022f895bb24dfac597e449e19eb0cbe62447a832601cb19bb480b51d", size = 318712, upload-time = "2026-04-08T19:57:50.919Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/9c/c3187ff89776871691311a0662d4c9427b9a06ab6a252d78f73b0ec696d3/msgspec-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0384bb318fa101459cf40a7d67250d5ac68ad2b1c370ecd5e55568f5dde2ed74", size = 194943, upload-time = "2026-04-08T19:56:43.53Z" }, + { url = "https://files.pythonhosted.org/packages/64/a5/18e0204ee6a26a2b2a42d12b82b697c75126f34e7d5896370b8bacbc28a8/msgspec-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b931ce7657a5e00a9053cc2ce37c24ce4daaec684706f278b29a0cdfd870d188", size = 188096, upload-time = "2026-04-08T19:56:45.13Z" }, + { url = "https://files.pythonhosted.org/packages/23/13/aaedca729b3d9b60802b627a21cdf541eba455a90241b5545481db3df3db/msgspec-0.21.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d52f848fed3841c75d902ab975ebb8abf5fed4f37bdef9b8dfc9c4d35c704cae", size = 216349, upload-time = "2026-04-08T19:56:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/db/23/fd0178c083e1876530f0b6aef2dedec893cfc2d3d54cce1996c4d0883514/msgspec-0.21.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f920711fdcfe4d2aba3e1b4b6b0f67f0eb07beca22881d5bd234e7c8d9407a3a", size = 222422, upload-time = "2026-04-08T19:56:47.751Z" }, + { url = "https://files.pythonhosted.org/packages/e7/50/2086b5ac8e4f59ef05b213112cbed31369fa3cb7bf3471f00e79912740d9/msgspec-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5b0c658073659562abb6414ed21c0b160b6201018def0d933d961d05bc4cf212", size = 222079, upload-time = "2026-04-08T19:56:49.016Z" }, + { url = "https://files.pythonhosted.org/packages/27/7e/05149e0b19b3fa3fdcafffcaeaae13fadeeb4d874557161f14421dbfdddf/msgspec-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d5b575124b8c4381baecfa26eacaaae119685763d3e399ab7abc2f1af88a2e53", size = 225331, upload-time = "2026-04-08T19:56:50.162Z" }, + { url = "https://files.pythonhosted.org/packages/77/9e/b5ec50a1051e74da5785aea618f7fa4819a09ce09df24c9f6348d9afdfb6/msgspec-0.21.0-cp310-cp310-win_amd64.whl", hash = "sha256:a4c84fac795cc8a2e35a70de63608b502fda2c3864eacae032e650c65b0a46f9", size = 188139, upload-time = "2026-04-08T19:56:51.498Z" }, + { url = "https://files.pythonhosted.org/packages/99/ca/5ef87156ebe095516e1e467abaea9b6c50a7f9c51168583f7cc49779c0ef/msgspec-0.21.0-cp310-cp310-win_arm64.whl", hash = "sha256:9b676a2448461e167d8b5fc79ddd4f9bbe806322b2fd7e88c631e99f32a16842", size = 173931, upload-time = "2026-04-08T19:56:53.572Z" }, + { url = "https://files.pythonhosted.org/packages/b2/34/a66dea16444967e3fc0991aff57ef473e2214e5bbdbe3c2b3139d2ccec7b/msgspec-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0634e676eb334fde291310f1d0f23bf48332977c2d0ebdaf98dfcd9437091782", size = 192890, upload-time = "2026-04-08T19:56:54.892Z" }, + { url = "https://files.pythonhosted.org/packages/bc/16/418ba970f74707e2590954f7fda0b44c1d2242d3835aecf914f1dd3080e6/msgspec-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:47220291d6cbc7980098d0e7593e77d86158ff08b9e61d64b2559928e5457828", size = 186383, upload-time = "2026-04-08T19:56:56.424Z" }, + { url = "https://files.pythonhosted.org/packages/4c/68/a745bfbaf6cf88db27294e242aa02cb392bb9b8efeb076c0e2abdeaa51b8/msgspec-0.21.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79a582748a2461204347d89adb5e500a0064d6d81c62e19342b5755bfcce23d2", size = 214968, upload-time = "2026-04-08T19:56:57.814Z" }, + { url = "https://files.pythonhosted.org/packages/68/da/fda01c754dc85aed67ac0b7d3b213ab50b5b39f15f5eb072b2baf0edb689/msgspec-0.21.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f2a80db664c75f336cff5e17df7861c23fa47bec6f96c2c3f94be773cc675821", size = 219652, upload-time = "2026-04-08T19:56:59.118Z" }, + { url = "https://files.pythonhosted.org/packages/f5/ff/8edf835d8e54b6d7431950cfce3c9f66c5bad3eb0651c4792989c0769845/msgspec-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:74de7d8831e4cb6e39ccc92d100fe50cecd2b2a8729089505437633e4fa52ffa", size = 220085, upload-time = "2026-04-08T19:57:00.518Z" }, + { url = "https://files.pythonhosted.org/packages/e9/4e/c21b1f7927cd00f56eaf0c8f182b96cd81707f153dce872876ed8b97bbca/msgspec-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e67b0bbc71b8146c159682747e625411349bd051905a474ca832dc828174dfb8", size = 223025, upload-time = "2026-04-08T19:57:01.911Z" }, + { url = "https://files.pythonhosted.org/packages/ee/06/924ab2c12b55b479e41039345e988bf935aabea92fbe90b7faf93166740c/msgspec-0.21.0-cp311-cp311-win_amd64.whl", hash = "sha256:03c472124cbbbcfbf0d2f429f62a8fb2d12b6633448a884dd1a875ab32aa59b4", size = 188362, upload-time = "2026-04-08T19:57:03.362Z" }, + { url = "https://files.pythonhosted.org/packages/46/10/4e85bba53b8f4514608578afcf82ae13cae1a043f87ad639c619aef955cf/msgspec-0.21.0-cp311-cp311-win_arm64.whl", hash = "sha256:b84ee1e334953e02aefce8bcde73e2a89e03e193aa9851e2e49810e00a9fd088", size = 174268, upload-time = "2026-04-08T19:57:04.855Z" }, + { url = "https://files.pythonhosted.org/packages/66/57/93fb97be49db1ff62aeda477e1fef6eab739df17a05234e476b644234fdc/msgspec-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:797d8f563c29ccc2047e699099cf8ab72dc41858c5bdd100d4689a0310072bff", size = 195880, upload-time = "2026-04-08T19:57:06.419Z" }, + { url = "https://files.pythonhosted.org/packages/7f/d1/3af0f8b31768552068a890e406488b1ce91ef935eb8ff001f1f130a0a3f3/msgspec-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c978ea4d2afa8f06fec2fab47f478f187e5523569c4613d135f4d9db4831de7", size = 188262, upload-time = "2026-04-08T19:57:07.648Z" }, + { url = "https://files.pythonhosted.org/packages/a4/69/a978335a9724a69ac4428e06be1cb8ce7e737453857575028159bd264ded/msgspec-0.21.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46e5e9b23bfa453572d8290541327d84cac1f74bbf45b88053dfea3b92d2608b", size = 218640, upload-time = "2026-04-08T19:57:09.203Z" }, + { url = "https://files.pythonhosted.org/packages/7b/34/3cb2b8a506850b8667c1167eb817a0b6605ebdf0027d301815ca2404f72b/msgspec-0.21.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ff68f1f12aa3fa1335b79a5bb8b9158cfea2944b4cf8253d05fe28ab6d3510f", size = 224786, upload-time = "2026-04-08T19:57:10.679Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4e/690f1487f72f37ca4482d4c63dceaf48d2b68db76d374108d7f0a15cc72c/msgspec-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6067127b5e44430a59fddff8d934a7a37ce96862cb25994415b68db7d4457bd5", size = 222514, upload-time = "2026-04-08T19:57:11.974Z" }, + { url = "https://files.pythonhosted.org/packages/83/95/4199f819d2b82db9c7d6de235591c02eebe4796672184eccad7f2b67d4e1/msgspec-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:11043d534a1bfcd08f1d4d5b50ba60015527b4c8517ec12c2213899e81913584", size = 227101, upload-time = "2026-04-08T19:57:13.278Z" }, + { url = "https://files.pythonhosted.org/packages/98/f5/56aaed6427a671d011030835f35fe2d4ed46ead4d2b03ffc6c356fd15e4b/msgspec-0.21.0-cp312-cp312-win_amd64.whl", hash = "sha256:c010790508a9fbe1b9328240ca8840130629b0055c52f58838d22d57ece10667", size = 189713, upload-time = "2026-04-08T19:57:15.055Z" }, + { url = "https://files.pythonhosted.org/packages/0c/fa/679f36fd5c98a676c6e2dcd25946d77ff7c28465ae9aba203a93d71774fd/msgspec-0.21.0-cp312-cp312-win_arm64.whl", hash = "sha256:19646187cdf5b94534c8697035c6f86b41b765260074203b40553c2fc51ac00b", size = 175137, upload-time = "2026-04-08T19:57:16.54Z" }, + { url = "https://files.pythonhosted.org/packages/03/bc/41bc2f0d9374117287a561cf8ec722bfe103ba35423580af572f74c73e99/msgspec-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8843a8953109ccb56d484d238aaa93fd64bd892bacaa73f15891d12a03c75220", size = 195915, upload-time = "2026-04-08T19:57:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/5c/85/a40a8202c718bc7d87bce4f5fe0189252fbcef8021936e34189ed4453ffb/msgspec-0.21.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ec3fc07f61c915d3001a4733a6bebcbfb35298601495e939fb38d645e3c8ffce", size = 188286, upload-time = "2026-04-08T19:57:18.959Z" }, + { url = "https://files.pythonhosted.org/packages/c6/e5/c775da2cc45758c0c001db89d49ad95978a971de7ed82efecb72e7f0c5d0/msgspec-0.21.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef540261ad9cbe1662ba1e6ebc64230532cf23d0c6c01ea7a7fcb383ec4c8008", size = 218639, upload-time = "2026-04-08T19:57:20.232Z" }, + { url = "https://files.pythonhosted.org/packages/75/de/f6ea46e9ba3edd5f69bc0298aa59611ad59bd32fab69a13c163fce47c2f9/msgspec-0.21.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f851f5d4356934086657dfae231115cbcfc5796e9aac604441d2a506f5c78d33", size = 224825, upload-time = "2026-04-08T19:57:21.429Z" }, + { url = "https://files.pythonhosted.org/packages/71/71/d188c26842138c3172d680020cfde078c3ef6b5b0fba9d16230333489a42/msgspec-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dad302178de0868b2ffa4de3a0072e51843106059dab5492c75743197c444736", size = 222517, upload-time = "2026-04-08T19:57:22.755Z" }, + { url = "https://files.pythonhosted.org/packages/03/ce/a7186a8024490fd41a190d139d423bd887821e79a82f97dab4283604ec35/msgspec-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0ceb9ef0b6ba4fef4c9da09595f9105cc02e8eb262df0d6220f22370ffdc2ec0", size = 227079, upload-time = "2026-04-08T19:57:24.08Z" }, + { url = "https://files.pythonhosted.org/packages/af/a7/bcf3562090f4759414cae67a92db937e163083e4b2aed4eb1a021aa9188b/msgspec-0.21.0-cp313-cp313-win_amd64.whl", hash = "sha256:57af1488174eb944b626b2f25838f214966284462458a2bfce44b9adfad725bf", size = 189627, upload-time = "2026-04-08T19:57:25.714Z" }, + { url = "https://files.pythonhosted.org/packages/2a/bb/2c7bda6c8d0378c17e5523a6cd0f1ce22ab43f6934ab5a7eec748a7e0cc0/msgspec-0.21.0-cp313-cp313-win_arm64.whl", hash = "sha256:b0088fbd0d2eec986df7cf4f17eec97c8a1aaccf9dd4e0b72f4794522fa83f65", size = 175167, upload-time = "2026-04-08T19:57:26.919Z" }, + { url = "https://files.pythonhosted.org/packages/f6/bc/2a705dcf966c604240c271c03480e8f36090c0b7c5dd4701d77d493a07f9/msgspec-0.21.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:21b4b4bbd6d6fe49628a9ad115b50b1546e706dec7aaf747afd32b9a75a6e0aa", size = 196007, upload-time = "2026-04-08T19:57:28.286Z" }, + { url = "https://files.pythonhosted.org/packages/35/12/8950cb18dd53c0c83fdd942e0196fe0b3f4cc38d7dbe199c01ee57d81c3e/msgspec-0.21.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e139825a8ca0c33496fd0f050d2ba89c93f0548e4ab877a0329ac45317451fb", size = 188544, upload-time = "2026-04-08T19:57:30.165Z" }, + { url = "https://files.pythonhosted.org/packages/41/14/862ed7c69ee77e1c9774988e6d57f6b0f782c95e91ec313d93785c61168d/msgspec-0.21.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a9126c287092a7225115f3372f91b2d38a36148a05cb8da3e827eaf61329ddc", size = 219612, upload-time = "2026-04-08T19:57:31.502Z" }, + { url = "https://files.pythonhosted.org/packages/00/d1/a516be3fb9c61dfea98fd262ce1aceaae2f7e665e750a1a8eaf96d5af5aa/msgspec-0.21.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b32866fc3faebe7e09b2fa151fb9858c36e9f133b4ee8132c0f6beea5f2b6c0", size = 224722, upload-time = "2026-04-08T19:57:32.874Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b8/b67dce3cac2604d199c3d3aac1df780b92856861482cbc8ca5f53dcde691/msgspec-0.21.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:98f5c4350979da05340782b267b9bea22bfddca10276f45fa374e0765c058303", size = 223319, upload-time = "2026-04-08T19:57:34.029Z" }, + { url = "https://files.pythonhosted.org/packages/78/7d/9a9bea17363025390bd0288f72298cf5323f9d39ddf3fcc1ebc6a4b7ef64/msgspec-0.21.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ec4542f7a2c354c8929aa2e2986b184ff84071d19a55d5e6a3b43c3b3a38b128", size = 226969, upload-time = "2026-04-08T19:57:35.304Z" }, + { url = "https://files.pythonhosted.org/packages/f3/66/3d57029a4329c67ac8dd00374279b823873b46c4fa797b8e6096e3a749b7/msgspec-0.21.0-cp314-cp314-win_amd64.whl", hash = "sha256:1ddc2de6af2adcd07b6d6f6745949eb58963e0f658a987313814954bb5489b26", size = 193594, upload-time = "2026-04-08T19:57:37.014Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e5/746a018d8da7f0d1b26cb6cc8662420fad578917bf4d73482c9cb0c25eca/msgspec-0.21.0-cp314-cp314-win_arm64.whl", hash = "sha256:0e032189438ee162fc66a528e0e26d578c8e5c30b0a8e1f1a78aa96cc27a36d1", size = 178893, upload-time = "2026-04-08T19:57:38.394Z" }, + { url = "https://files.pythonhosted.org/packages/91/eb/2c999c30b205da592ccaf650e5be56e22aefb65008b25e654eb428299f72/msgspec-0.21.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:549dc09f6796da9f0ac3c34c2bb9c10db85de723eb075dcf837f83968ecedc97", size = 199939, upload-time = "2026-04-08T19:57:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/88/31/8b94b749a69514357c54d7a5027b5280898ed28c39b3ede78427c3aa7bed/msgspec-0.21.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e14c3a27a97ca9bb03eb9d5612609b141068d98eeb210c08e5fbf2556d601e99", size = 192586, upload-time = "2026-04-08T19:57:41.101Z" }, + { url = "https://files.pythonhosted.org/packages/1c/8a/ab4d49c9ccbc4e12072d76323bb9ddf670b6c7634a508b8b3bbd31434954/msgspec-0.21.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d00088bd8bf00c3ed3e2f3fef78cad2ce871c5599df0624928c6762fc7671f6", size = 226075, upload-time = "2026-04-08T19:57:42.415Z" }, + { url = "https://files.pythonhosted.org/packages/57/34/2a2642df1cf93ba7a73912aedadd7fe8372f558ce41d3e9db5c3634352ec/msgspec-0.21.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c3d7545089ae92d0d6f2dd5dd96814446c58eff360af050f734fafed7f72c8f5", size = 229528, upload-time = "2026-04-08T19:57:43.721Z" }, + { url = "https://files.pythonhosted.org/packages/12/1f/a1faffbbb81e01c2d388aa8589b8d0efa54a1813c9234858978e1bc5fdb5/msgspec-0.21.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bceae6627c37eaac2379cabf9fa612ffe5fa64f23c90912019820423b0df7009", size = 230258, upload-time = "2026-04-08T19:57:45.064Z" }, + { url = "https://files.pythonhosted.org/packages/aa/f5/63bc93a66228853f0aa6c02d0dcec276be383ba0ab61b71a5915432affd0/msgspec-0.21.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5298b4a4ac55ed78234b8c206e6ab5aa5c5bf2573664c76205e89c54282df1e6", size = 231624, upload-time = "2026-04-08T19:57:46.687Z" }, + { url = "https://files.pythonhosted.org/packages/c1/32/a6415442eb243ee93e63adf85756630c64c4377e207f5f907de4e1d5b283/msgspec-0.21.0-cp314-cp314t-win_amd64.whl", hash = "sha256:640e15c6ef5003575f0c16c96bbd25f92b42c5f02e27d4d0c08de9551c288cbb", size = 206397, upload-time = "2026-04-08T19:57:47.967Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a4/7e7e36cf57a4870b5b223d2ea19c4b78c32e6e6dcd2612588ddf69a97c17/msgspec-0.21.0-cp314-cp314t-win_arm64.whl", hash = "sha256:91af695ec681bf6a114d7422b76c5b8b51ce698e89152a0fafaca6fad50478b0", size = 182950, upload-time = "2026-04-08T19:57:49.286Z" }, ] [[package]] @@ -15268,26 +15277,26 @@ wheels = [ [[package]] name = "mypy-boto3-redshift-data" -version = "1.42.3" +version = "1.42.87" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e6/80/91c059fcc5154f3474ab34263b8a8a8dcff2cc99456d5154b90bf66557ab/mypy_boto3_redshift_data-1.42.3.tar.gz", hash = "sha256:31bcbe85025c057aa60d8e700b552eb781107b1d4f9a34fc6e007cd6b4f934a5", size = 19217, upload-time = "2025-12-04T21:10:24.971Z" } +sdist = { url = "https://files.pythonhosted.org/packages/db/6b/847a4dace9a629a6aef051c409a22bb187ae617367b456ea08d7ad282ea8/mypy_boto3_redshift_data-1.42.87.tar.gz", hash = "sha256:2a315710adeb7183a068dd6e9f0d26171a96f1528fcec613f792903b80d3669f", size = 19342, upload-time = "2026-04-09T19:58:21.391Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/6b/9bc2f5f3c5826a91fc8f1ecb3af95e0eda7edaec221a1f9372eb716f98b5/mypy_boto3_redshift_data-1.42.3-py3-none-any.whl", hash = "sha256:9f00eeccb537169d96d3a8eb8ee91aca2da74c13d1d3e9693da85f23d76daf26", size = 26111, upload-time = "2025-12-04T21:10:23.56Z" }, + { url = "https://files.pythonhosted.org/packages/89/ec/b1228e152fb95dd079a84785f5645c609f78ddc205736aa3a4dd1c0c91a9/mypy_boto3_redshift_data-1.42.87-py3-none-any.whl", hash = "sha256:80b3a2aeb5a8de683e02a9ac84659bda4f8fc8c0d0a834223c5a4c0a7577e50d", size = 26222, upload-time = "2026-04-09T19:58:19.616Z" }, ] [[package]] name = "mypy-boto3-s3" -version = "1.42.80" +version = "1.42.85" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/81/4e/f0f2c0fca253daf2db6230f96899dd0b3b7b592d99f60f07e5b3cc058584/mypy_boto3_s3-1.42.80.tar.gz", hash = "sha256:f3c1d19e8f7346402e341d0395d492b67801f80614bad5d7fa8b5f4db5e4b65d", size = 76540, upload-time = "2026-03-31T19:37:26.133Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/5e/026461fef8e163ec261df1668ee88611124170bb4da3d1b144c970e7c9b4/mypy_boto3_s3-1.42.85.tar.gz", hash = "sha256:401e3a184ac0973bc08b556cc3b2655d8f2e56570b6ed87ce635210df4f666fb", size = 76543, upload-time = "2026-04-07T19:51:20.608Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/32/aa321332f62f6c8ce174ad3c3edab6235c0ab36c77dae930fea9e41e69bd/mypy_boto3_s3-1.42.80-py3-none-any.whl", hash = "sha256:23d59dee7650c18c62ebbdc96b11bbfd8b1547341f46c88d1aa8d140276a4276", size = 83751, upload-time = "2026-03-31T19:37:22.112Z" }, + { url = "https://files.pythonhosted.org/packages/c0/58/fb6373ca66898620ecb7b9ab92563f3f7277627994bc4ceba75c721de4a1/mypy_boto3_s3-1.42.85-py3-none-any.whl", hash = "sha256:b2cad995ea733b16ae3be5510fd6a0038aa44400c22d010d4def9286cf6eaf82", size = 83751, upload-time = "2026-04-07T19:51:17.727Z" }, ] [[package]] @@ -15373,7 +15382,7 @@ wheels = [ [[package]] name = "nbconvert" -version = "7.17.0" +version = "7.17.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "beautifulsoup4" }, @@ -15391,9 +15400,9 @@ dependencies = [ { name = "pygments" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/47/81f886b699450d0569f7bc551df2b1673d18df7ff25cc0c21ca36ed8a5ff/nbconvert-7.17.0.tar.gz", hash = "sha256:1b2696f1b5be12309f6c7d707c24af604b87dfaf6d950794c7b07acab96dda78", size = 862855, upload-time = "2026-01-29T16:37:48.478Z" } +sdist = { url = "https://files.pythonhosted.org/packages/01/b1/708e53fe2e429c103c6e6e159106bcf0357ac41aa4c28772bd8402339051/nbconvert-7.17.1.tar.gz", hash = "sha256:34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2", size = 865311, upload-time = "2026-04-08T00:44:14.914Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl", hash = "sha256:4f99a63b337b9a23504347afdab24a11faa7d86b405e5c8f9881cd313336d518", size = 261510, upload-time = "2026-01-29T16:37:46.322Z" }, + { url = "https://files.pythonhosted.org/packages/67/f8/bb0a9d5f46819c821dc1f004aa2cc29b1d91453297dbf5ff20470f00f193/nbconvert-7.17.1-py3-none-any.whl", hash = "sha256:aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8", size = 261927, upload-time = "2026-04-08T00:44:12.845Z" }, ] [[package]] @@ -15667,7 +15676,7 @@ wheels = [ [[package]] name = "openai" -version = "2.30.0" +version = "2.31.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -15679,9 +15688,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/15/52580c8fbc16d0675d516e8749806eda679b16de1e4434ea06fb6feaa610/openai-2.30.0.tar.gz", hash = "sha256:92f7661c990bda4b22a941806c83eabe4896c3094465030dd882a71abe80c885", size = 676084, upload-time = "2026-03-25T22:08:59.96Z" } +sdist = { url = "https://files.pythonhosted.org/packages/94/fe/64b3d035780b3188f86c4f6f1bc202e7bb74757ef028802112273b9dcacf/openai-2.31.0.tar.gz", hash = "sha256:43ca59a88fc973ad1848d86b98d7fac207e265ebbd1828b5e4bdfc85f79427a5", size = 684772, upload-time = "2026-04-08T21:01:41.797Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/9e/5bfa2270f902d5b92ab7d41ce0475b8630572e71e349b2a4996d14bdda93/openai-2.30.0-py3-none-any.whl", hash = "sha256:9a5ae616888eb2748ec5e0c5b955a51592e0b201a11f4262db920f2a78c5231d", size = 1146656, upload-time = "2026-03-25T22:08:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/66/bc/a8f7c3aa03452fedbb9af8be83e959adba96a6b4a35e416faffcc959c568/openai-2.31.0-py3-none-any.whl", hash = "sha256:44e1344d87e56a493d649b17e2fac519d1368cbb0745f59f1957c4c26de50a0a", size = 1153479, upload-time = "2026-04-08T21:01:39.217Z" }, ] [package.optional-dependencies] @@ -15752,7 +15761,7 @@ wheels = [ [[package]] name = "openlineage-integration-common" -version = "1.45.0" +version = "1.46.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -15761,12 +15770,12 @@ dependencies = [ { name = "pyyaml" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/66/ee30f0b1c7101ab62bdef5332d29f4203cf903adc01276c636ce9726e8d1/openlineage_integration_common-1.45.0-py3-none-any.whl", hash = "sha256:0338ace651697b2185b306a9987f742285e3fa94607d4fabebf7d57dd47c8d43", size = 57827, upload-time = "2026-03-11T15:40:05.073Z" }, + { url = "https://files.pythonhosted.org/packages/ab/52/d81eca43a980058b661868fdeb9f5d4af876d1dab982635c859756907fee/openlineage_integration_common-1.46.0-py3-none-any.whl", hash = "sha256:bdc50613b94346dd9f3441d079260282e7cc85cc16ea1469630a9c76912d5d92", size = 59006, upload-time = "2026-04-08T13:20:18.972Z" }, ] [[package]] name = "openlineage-python" -version = "1.45.0" +version = "1.46.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -15777,18 +15786,18 @@ dependencies = [ { name = "requests" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/9e/a3918a9d7ed883c744119269b1477489ccbe25d04cf90e193b006d1ba5e4/openlineage_python-1.45.0-py3-none-any.whl", hash = "sha256:cf66e7d517d3c8b510b39ad646d8fd0ca2f0cc92d7d6d601d93b2a859783f380", size = 103592, upload-time = "2026-03-11T15:40:06.556Z" }, + { url = "https://files.pythonhosted.org/packages/92/97/f5614980b5d43884ce7e71568239555b4e959bdf7098d9734e22c32ef5c6/openlineage_python-1.46.0-py3-none-any.whl", hash = "sha256:f6228a01d34990e76ede5b55b3f99169e54e2e624814c4493f064b9cb1bfba37", size = 112669, upload-time = "2026-04-08T13:20:20.024Z" }, ] [[package]] name = "openlineage-sql" -version = "1.45.0" +version = "1.46.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/17/5b/766d294e699871c4c831ee4741e81ecf2b03affe761bb7803233259cb654/openlineage_sql-1.45.0.tar.gz", hash = "sha256:a6707a3b604b028a4350e7fe703360852a777d4d54ac8b1fa0e7873a5ed2227a", size = 40389, upload-time = "2026-03-11T15:40:12.266Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/cb/2ce8509435620a20102df0dc1b84c8cd22e743e3b4c352a42b9ad5678389/openlineage_sql-1.46.0.tar.gz", hash = "sha256:af163a6d58d9e38f819af4ceaba15ff1046ffc46a886c29a0713459d800ad547", size = 40503, upload-time = "2026-04-08T13:20:25.804Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/f0/50afa3f02b28af18974fe8ecf17f9382c50c4cee557f38823240e3a3c9e5/openlineage_sql-1.45.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a9ee32250f051433cd63ad38afa4156781f92b893a8bd0ce0b15036ccedcc4d3", size = 4895465, upload-time = "2026-03-11T15:40:08.26Z" }, - { url = "https://files.pythonhosted.org/packages/9a/14/6724b3948f58dcd80bf1a0b68927680de0ee2fa71a3349262b36e4b52540/openlineage_sql-1.45.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5dfb07b2ec7e89363ebac65b35b5ad5e0368d84669f156652b348b1993ae4346", size = 2446317, upload-time = "2026-03-11T15:40:09.931Z" }, - { url = "https://files.pythonhosted.org/packages/10/6f/1d167ed8d2254c7a650aa4729390b54da3f92639dd7f5addaddf3df1a7a8/openlineage_sql-1.45.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:44612c3632f614cdee9d46b2c889453bd04d95c82764d75df6667bc90ff3cf40", size = 2611656, upload-time = "2026-03-11T15:40:11.01Z" }, + { url = "https://files.pythonhosted.org/packages/57/3b/8840eaab777c83bcb58cebfdf195398cab9de1d3a6db8c857fe9a38ae403/openlineage_sql-1.46.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:959620f4a5d0ab51586b4cb296f1b104fb6db1b46e48b37178d9e7c7996c813f", size = 4894095, upload-time = "2026-04-08T13:20:21.375Z" }, + { url = "https://files.pythonhosted.org/packages/b4/33/eb2f193f77a3ad91a1236b72f623285785de0d90759f4558acd3e8a85471/openlineage_sql-1.46.0-cp310-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7f238fcac444262f9db43c6ba6f4a1b841e216beb0883a5e75abe425e2c43bb7", size = 2443342, upload-time = "2026-04-08T13:20:23.332Z" }, + { url = "https://files.pythonhosted.org/packages/97/7e/103c62d8f5dbd7425432c849dc172174f8ccccf747067e8a3354ae3de802/openlineage_sql-1.46.0-cp310-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:adf147b14665730e381b362dd721cebff56feff57744681f128a7b3f48ecbe8b", size = 2612927, upload-time = "2026-04-08T13:20:24.556Z" }, ] [[package]] @@ -15834,45 +15843,45 @@ wheels = [ [[package]] name = "opentelemetry-api" -version = "1.40.0" +version = "1.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "importlib-metadata" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2c/1d/4049a9e8698361cc1a1aa03a6c59e4fa4c71e0c0f94a30f988a6876a2ae6/opentelemetry_api-1.40.0.tar.gz", hash = "sha256:159be641c0b04d11e9ecd576906462773eb97ae1b657730f0ecf64d32071569f", size = 70851, upload-time = "2026-03-04T14:17:21.555Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/8e/3778a7e87801d994869a9396b9fc2a289e5f9be91ff54a27d41eace494b0/opentelemetry_api-1.41.0.tar.gz", hash = "sha256:9421d911326ec12dee8bc933f7839090cad7a3f13fcfb0f9e82f8174dc003c09", size = 71416, upload-time = "2026-04-09T14:38:34.544Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/bf/93795954016c522008da367da292adceed71cca6ee1717e1d64c83089099/opentelemetry_api-1.40.0-py3-none-any.whl", hash = "sha256:82dd69331ae74b06f6a874704be0cfaa49a1650e1537d4a813b86ecef7d0ecf9", size = 68676, upload-time = "2026-03-04T14:17:01.24Z" }, + { url = "https://files.pythonhosted.org/packages/58/ee/99ab786653b3bda9c37ade7e24a7b607a1b1f696063172768417539d876d/opentelemetry_api-1.41.0-py3-none-any.whl", hash = "sha256:0e77c806e6a89c9e4f8d372034622f3e1418a11bdbe1c80a50b3d3397ad0fa4f", size = 69007, upload-time = "2026-04-09T14:38:11.833Z" }, ] [[package]] name = "opentelemetry-exporter-otlp" -version = "1.40.0" +version = "1.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-exporter-otlp-proto-grpc" }, { name = "opentelemetry-exporter-otlp-proto-http" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d0/37/b6708e0eff5c5fb9aba2e0ea09f7f3bcbfd12a592d2a780241b5f6014df7/opentelemetry_exporter_otlp-1.40.0.tar.gz", hash = "sha256:7caa0870b95e2fcb59d64e16e2b639ecffb07771b6cd0000b5d12e5e4fef765a", size = 6152, upload-time = "2026-03-04T14:17:23.235Z" } +sdist = { url = "https://files.pythonhosted.org/packages/65/b7/845565a2ab5d22c1486bc7729a06b05cd0964c61539d766e1f107c9eea0c/opentelemetry_exporter_otlp-1.41.0.tar.gz", hash = "sha256:97ff847321f8d4c919032a67d20d3137fb7b34eac0c47f13f71112858927fc5b", size = 6152, upload-time = "2026-04-09T14:38:35.895Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/fc/aea77c28d9f3ffef2fdafdc3f4a235aee4091d262ddabd25882f47ce5c5f/opentelemetry_exporter_otlp-1.40.0-py3-none-any.whl", hash = "sha256:48c87e539ec9afb30dc443775a1334cc5487de2f72a770a4c00b1610bf6c697d", size = 7023, upload-time = "2026-03-04T14:17:03.612Z" }, + { url = "https://files.pythonhosted.org/packages/e0/f2/f1076fff152858773f22cda146713f9ae3661795af6bacd411a76f2151ac/opentelemetry_exporter_otlp-1.41.0-py3-none-any.whl", hash = "sha256:443b6a45c990ae4c55e147f97049a86c5f5b704f3d78b48b44a073a886ec4d6e", size = 7022, upload-time = "2026-04-09T14:38:13.934Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.40.0" +version = "1.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-proto" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/51/bc/1559d46557fe6eca0b46c88d4c2676285f1f3be2e8d06bb5d15fbffc814a/opentelemetry_exporter_otlp_proto_common-1.40.0.tar.gz", hash = "sha256:1cbee86a4064790b362a86601ee7934f368b81cd4cc2f2e163902a6e7818a0fa", size = 20416, upload-time = "2026-03-04T14:17:23.801Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/28/e8eca94966fe9a1465f6094dc5ddc5398473682180279c94020bc23b4906/opentelemetry_exporter_otlp_proto_common-1.41.0.tar.gz", hash = "sha256:966bbce537e9edb166154779a7c4f8ab6b8654a03a28024aeaf1a3eacb07d6ee", size = 20411, upload-time = "2026-04-09T14:38:36.572Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/ca/8f122055c97a932311a3f640273f084e738008933503d0c2563cd5d591fc/opentelemetry_exporter_otlp_proto_common-1.40.0-py3-none-any.whl", hash = "sha256:7081ff453835a82417bf38dccf122c827c3cbc94f2079b03bba02a3165f25149", size = 18369, upload-time = "2026-03-04T14:17:04.796Z" }, + { url = "https://files.pythonhosted.org/packages/26/c4/78b9bf2d9c1d5e494f44932988d9d91c51a66b9a7b48adf99b62f7c65318/opentelemetry_exporter_otlp_proto_common-1.41.0-py3-none-any.whl", hash = "sha256:7a99177bf61f85f4f9ed2072f54d676364719c066f6d11f515acc6c745c7acf0", size = 18366, upload-time = "2026-04-09T14:38:15.135Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.40.0" +version = "1.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -15883,14 +15892,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8f/7f/b9e60435cfcc7590fa87436edad6822240dddbc184643a2a005301cc31f4/opentelemetry_exporter_otlp_proto_grpc-1.40.0.tar.gz", hash = "sha256:bd4015183e40b635b3dab8da528b27161ba83bf4ef545776b196f0fb4ec47740", size = 25759, upload-time = "2026-03-04T14:17:24.4Z" } +sdist = { url = "https://files.pythonhosted.org/packages/42/46/d75a3f8c91915f2e58f61d0a2e4ada63891e7c7a37a20ff7949ba184a6b2/opentelemetry_exporter_otlp_proto_grpc-1.41.0.tar.gz", hash = "sha256:f704201251c6f65772b11bddea1c948000554459101bdbb0116e0a01b70592f6", size = 25754, upload-time = "2026-04-09T14:38:37.423Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/6f/7ee0980afcbdcd2d40362da16f7f9796bd083bf7f0b8e038abfbc0300f5d/opentelemetry_exporter_otlp_proto_grpc-1.40.0-py3-none-any.whl", hash = "sha256:2aa0ca53483fe0cf6405087a7491472b70335bc5c7944378a0a8e72e86995c52", size = 20304, upload-time = "2026-03-04T14:17:05.942Z" }, + { url = "https://files.pythonhosted.org/packages/81/f6/b09e2e0c9f0b5750cebc6eaf31527b910821453cef40a5a0fe93550422b2/opentelemetry_exporter_otlp_proto_grpc-1.41.0-py3-none-any.whl", hash = "sha256:3a1a86bd24806ccf136ec9737dbfa4c09b069f9130ff66b0acb014f9c5255fd1", size = 20299, upload-time = "2026-04-09T14:38:17.01Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-http" -version = "1.40.0" +version = "1.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -15901,35 +15910,35 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/fa/73d50e2c15c56be4d000c98e24221d494674b0cc95524e2a8cb3856d95a4/opentelemetry_exporter_otlp_proto_http-1.40.0.tar.gz", hash = "sha256:db48f5e0f33217588bbc00274a31517ba830da576e59503507c839b38fa0869c", size = 17772, upload-time = "2026-03-04T14:17:25.324Z" } +sdist = { url = "https://files.pythonhosted.org/packages/19/63/d9f43cd75f3fabb7e01148c89cfa9491fc18f6580a6764c554ff7c953c46/opentelemetry_exporter_otlp_proto_http-1.41.0.tar.gz", hash = "sha256:dcd6e0686f56277db4eecbadd5262124e8f2cc739cadbc3fae3d08a12c976cf5", size = 24139, upload-time = "2026-04-09T14:38:38.128Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/3a/8865d6754e61c9fb170cdd530a124a53769ee5f740236064816eb0ca7301/opentelemetry_exporter_otlp_proto_http-1.40.0-py3-none-any.whl", hash = "sha256:a8d1dab28f504c5d96577d6509f80a8150e44e8f45f82cdbe0e34c99ab040069", size = 19960, upload-time = "2026-03-04T14:17:07.153Z" }, + { url = "https://files.pythonhosted.org/packages/64/b5/a214cd907eedc17699d1c2d602288ae17cb775526df04db3a3b3585329d2/opentelemetry_exporter_otlp_proto_http-1.41.0-py3-none-any.whl", hash = "sha256:a9c4ee69cce9c3f4d7ee736ad1b44e3c9654002c0816900abbafd9f3cf289751", size = 22673, upload-time = "2026-04-09T14:38:18.349Z" }, ] [[package]] name = "opentelemetry-exporter-prometheus" -version = "0.61b0" +version = "0.62b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, { name = "prometheus-client" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4a/20/9e818fd364d12e8d0cfdce4a3b2d82e24d98c4ceebb315de6b6770b5f214/opentelemetry_exporter_prometheus-0.61b0.tar.gz", hash = "sha256:7c4919bd8e79abd62b610767e80f42c9c3a06c5183f4dd9141eedeb57aea284b", size = 15136, upload-time = "2026-03-04T14:17:26.275Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/ec/fa8a722199dc2e75dc582779d62207b00b0bdb014b5635594afa0cf3ee43/opentelemetry_exporter_prometheus-0.62b0.tar.gz", hash = "sha256:4d1106566a9b3e8dff028e69e9f2dc90723e6b431c900ff8c72982fcf11dbae5", size = 15441, upload-time = "2026-04-09T14:38:38.934Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/4a/b65d40e94d1d930aee73a1a2857211ee6ab10ce3686cbdae5eea78cd9d34/opentelemetry_exporter_prometheus-0.61b0-py3-none-any.whl", hash = "sha256:3013b41f4370143d48d219a2351473761423e5882fa4c213811eaefacba39cb7", size = 13149, upload-time = "2026-03-04T14:17:08.983Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1e/43645fadd561471af2aec95906a3dd54af1a8e7782322310e802a810ad3a/opentelemetry_exporter_prometheus-0.62b0-py3-none-any.whl", hash = "sha256:cd7e8acae3be5f425ffa2e0864eea474fa7a40706f786de7a2d23846573d8f75", size = 13278, upload-time = "2026-04-09T14:38:19.367Z" }, ] [[package]] name = "opentelemetry-proto" -version = "1.40.0" +version = "1.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4c/77/dd38991db037fdfce45849491cb61de5ab000f49824a00230afb112a4392/opentelemetry_proto-1.40.0.tar.gz", hash = "sha256:03f639ca129ba513f5819810f5b1f42bcb371391405d99c168fe6937c62febcd", size = 45667, upload-time = "2026-03-04T14:17:31.194Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/d9/08e3dc6156878713e8c811682bc76151f5fe1a3cb7f3abda3966fd56e71e/opentelemetry_proto-1.41.0.tar.gz", hash = "sha256:95d2e576f9fb1800473a3e4cfcca054295d06bdb869fda4dc9f4f779dc68f7b6", size = 45669, upload-time = "2026-04-09T14:38:45.978Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/b2/189b2577dde745b15625b3214302605b1353436219d42b7912e77fa8dc24/opentelemetry_proto-1.40.0-py3-none-any.whl", hash = "sha256:266c4385d88923a23d63e353e9761af0f47a6ed0d486979777fe4de59dc9b25f", size = 72073, upload-time = "2026-03-04T14:17:16.673Z" }, + { url = "https://files.pythonhosted.org/packages/49/8c/65ef7a9383a363864772022e822b5d5c6988e6f9dabeebb9278f5b86ebc3/opentelemetry_proto-1.41.0-py3-none-any.whl", hash = "sha256:b970ab537309f9eed296be482c3e7cca05d8aca8165346e929f658dbe153b247", size = 72074, upload-time = "2026-04-09T14:38:29.38Z" }, ] [[package]] @@ -15949,29 +15958,29 @@ wheels = [ [[package]] name = "opentelemetry-sdk" -version = "1.40.0" +version = "1.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/fd/3c3125b20ba18ce2155ba9ea74acb0ae5d25f8cd39cfd37455601b7955cc/opentelemetry_sdk-1.40.0.tar.gz", hash = "sha256:18e9f5ec20d859d268c7cb3c5198c8d105d073714db3de50b593b8c1345a48f2", size = 184252, upload-time = "2026-03-04T14:17:31.87Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/0e/a586df1186f9f56b5a0879d52653effc40357b8e88fc50fe300038c3c08b/opentelemetry_sdk-1.41.0.tar.gz", hash = "sha256:7bddf3961131b318fc2d158947971a8e37e38b1cd23470cfb72b624e7cc108bd", size = 230181, upload-time = "2026-04-09T14:38:47.225Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/c5/6a852903d8bfac758c6dc6e9a68b015d3c33f2f1be5e9591e0f4b69c7e0a/opentelemetry_sdk-1.40.0-py3-none-any.whl", hash = "sha256:787d2154a71f4b3d81f20524a8ce061b7db667d24e46753f32a7bc48f1c1f3f1", size = 141951, upload-time = "2026-03-04T14:17:17.961Z" }, + { url = "https://files.pythonhosted.org/packages/2c/13/a7825118208cb32e6a4edcd0a99f925cbef81e77b3b0aedfd9125583c543/opentelemetry_sdk-1.41.0-py3-none-any.whl", hash = "sha256:a596f5687964a3e0d7f8edfdcf5b79cbca9c93c7025ebf5fb00f398a9443b0bd", size = 180214, upload-time = "2026-04-09T14:38:30.657Z" }, ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.61b0" +version = "0.62b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6d/c0/4ae7973f3c2cfd2b6e321f1675626f0dab0a97027cc7a297474c9c8f3d04/opentelemetry_semantic_conventions-0.61b0.tar.gz", hash = "sha256:072f65473c5d7c6dc0355b27d6c9d1a679d63b6d4b4b16a9773062cb7e31192a", size = 145755, upload-time = "2026-03-04T14:17:32.664Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/b0/c14f723e86c049b7bf8ff431160d982519b97a7be2857ed2247377397a24/opentelemetry_semantic_conventions-0.62b0.tar.gz", hash = "sha256:cbfb3c8fc259575cf68a6e1b94083cc35adc4a6b06e8cf431efa0d62606c0097", size = 145753, upload-time = "2026-04-09T14:38:48.274Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/37/cc6a55e448deaa9b27377d087da8615a3416d8ad523d5960b78dbeadd02a/opentelemetry_semantic_conventions-0.61b0-py3-none-any.whl", hash = "sha256:fa530a96be229795f8cef353739b618148b0fe2b4b3f005e60e262926c4d38e2", size = 231621, upload-time = "2026-03-04T14:17:19.33Z" }, + { url = "https://files.pythonhosted.org/packages/58/6c/5e86fa1759a525ef91c2d8b79d668574760ff3f900d114297765eb8786cb/opentelemetry_semantic_conventions-0.62b0-py3-none-any.whl", hash = "sha256:0ddac1ce59eaf1a827d9987ab60d9315fb27aea23304144242d1fcad9e16b489", size = 231619, upload-time = "2026-04-09T14:38:32.394Z" }, ] [[package]] @@ -16155,23 +16164,24 @@ wheels = [ [[package]] name = "pagefind" -version = "1.5.0b2" +version = "1.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c8/1b/d88d8d7fe3628e705c154b5b14bd4ddc5204b5fd155ce1aee48099fc6485/pagefind-1.5.0b2.tar.gz", hash = "sha256:b838d2c5a4ec5836294fa54af66b4210568a97635093c43b915d67ccb589378f", size = 46166, upload-time = "2026-04-03T23:51:23.398Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/b3/9795c226d2be6781962d8baad83edc8dfe44ff788b34f8606843fa9fe2e1/pagefind-1.5.0.tar.gz", hash = "sha256:145528046a860b932a014493af22cc1c48f00cf5414daaf83581b02cea20ca51", size = 52596, upload-time = "2026-04-06T08:44:35.572Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/ff/7f5f9a551f53c0c2f247d216b0e9ba6f50954abb6266edc495a1e2f4082a/pagefind-1.5.0b2-py3-none-any.whl", hash = "sha256:2798b4f75134ba57197b93a6d7eb8e726be8d0eb86932f5ace72c0e5c8f1e637", size = 10121, upload-time = "2026-04-03T23:50:54.089Z" }, + { url = "https://files.pythonhosted.org/packages/d6/92/3dfc9e9a0c756b65948c1ea8fa62745e9a4cab9395971d86d97064a7ebf3/pagefind-1.5.0-py3-none-any.whl", hash = "sha256:7336e0eecd3638ed85b48967849c6406caa617d83737015c3be10395fb3af3ba", size = 10102, upload-time = "2026-04-06T08:43:59.161Z" }, ] [[package]] name = "pagefind-bin" -version = "1.5.0b2" +version = "1.5.0" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/18/ed35f18d2cbcd1e49fec1c74ee88ee144cd38c5d01c794b567e9e274e723/pagefind_bin-1.5.0b2-py3-none-macosx_12_0_arm64.whl", hash = "sha256:19deda91cebca3dbff97760e878a582256adfe5068caaf47ee88a99b3c0a84c5", size = 4974364, upload-time = "2026-04-03T23:50:55.709Z" }, - { url = "https://files.pythonhosted.org/packages/30/8c/69e32f7f3f96e3935356680fec29a1ab6beb505fe81f9a2be8cd28715229/pagefind_bin-1.5.0b2-py3-none-macosx_12_0_x86_64.whl", hash = "sha256:358fcf9dfb4ab215a148fe72263cbb4d38d209d641616092eaa628d0ad3f0e19", size = 5049366, upload-time = "2026-04-03T23:50:57.559Z" }, - { url = "https://files.pythonhosted.org/packages/87/2b/67b08d306998f8d238578b2dd487852e0a7c696a61b390c48ae70ecb6da1/pagefind_bin-1.5.0b2-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:77f04afd54c10f64c488e14f1e306ffaab3989dcb802db2312612699705c6fd6", size = 5269428, upload-time = "2026-04-03T23:50:59.222Z" }, - { url = "https://files.pythonhosted.org/packages/8c/c6/fb2ae4acb0e7670f6b02759efc3afa3052dec5e8a73f09763ec25858663e/pagefind_bin-1.5.0b2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:97c6c874b10414a0bf547b7bd9e33528fba98d3417c4003af9a84db3dc1880de", size = 5002912, upload-time = "2026-04-03T23:51:01.115Z" }, - { url = "https://files.pythonhosted.org/packages/90/cc/76f22649048620b678ff167c952ce8701e8f3567f4dd8aa175be98d99412/pagefind_bin-1.5.0b2-py3-none-win_amd64.whl", hash = "sha256:568b84a1791d7552da814839044211a242530731a1ea6c09632f35edf6b4f39f", size = 5187054, upload-time = "2026-04-03T23:51:02.888Z" }, + { url = "https://files.pythonhosted.org/packages/e4/a0/ee073ae9eb4fe538eae293ed993a8997cccdd55716d3a80e9c2f9ae174d3/pagefind_bin-1.5.0-py3-none-macosx_12_0_arm64.whl", hash = "sha256:eff63e30133bbff252ca9f74d9b9302ef0aaa6919aee82a016c219333a967e9f", size = 4976505, upload-time = "2026-04-06T08:44:00.43Z" }, + { url = "https://files.pythonhosted.org/packages/91/d2/3ed8ed5c41dda820f73d3500741a76446dffcc0f245d3517c60bc4b3712b/pagefind_bin-1.5.0-py3-none-macosx_12_0_x86_64.whl", hash = "sha256:03530001a79c2ae123f166d046ea6b5434df6260edcceeacea04d39fbbef347c", size = 5053027, upload-time = "2026-04-06T08:44:02.293Z" }, + { url = "https://files.pythonhosted.org/packages/eb/aa/5053abcee777ac01638c621cd3aa1f62d55a3636a43d063bbd5400ab4f70/pagefind_bin-1.5.0-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:e9aa3c06fadf7b3d14a393752a2c07a5ba4c10a1514bdd12495c9ce46b6bcfd6", size = 5270428, upload-time = "2026-04-06T08:44:04.552Z" }, + { url = "https://files.pythonhosted.org/packages/83/e0/8a2430bbb2506559b74aadb8e39dfa6791fb45cb21fc53f9dc13209534d6/pagefind_bin-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:8b1da987c150c34985f9fc0797c767fc9c331b0b87de5a443127e6441028a9eb", size = 5004889, upload-time = "2026-04-06T08:44:06.281Z" }, + { url = "https://files.pythonhosted.org/packages/c8/de/bff59b417033cd68a1cef6323b3c182740b4b3d0253332f4097bdde6c038/pagefind_bin-1.5.0-py3-none-win_amd64.whl", hash = "sha256:aa536c5b836a0ee6eea7464fc158037b607753b6a56c005784af5cd16ac6b5b8", size = 5189286, upload-time = "2026-04-06T08:44:07.858Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ec/571aaf0105038b3d8286059ec8193901175b8cdf85a0e8b6bfb7d4da7f41/pagefind_bin-1.5.0-py3-none-win_arm64.whl", hash = "sha256:1c0cc9809063a571427afab4535b5685bc08c4b6bbb66b8e476d7d111e60e220", size = 5066830, upload-time = "2026-04-06T08:44:10Z" }, ] [[package]] @@ -16257,7 +16267,7 @@ sql-other = [ [[package]] name = "pandas-gbq" -version = "0.34.1" +version = "0.35.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "db-dtypes" }, @@ -16274,9 +16284,9 @@ dependencies = [ { name = "pydata-google-auth" }, { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f6/c7/2d2877fe71c13c6713aa1872bf8c8613044361ca00a488d6ddd5b1a74cbc/pandas_gbq-0.34.1.tar.gz", hash = "sha256:6bea5b85937251b976cf9db38151ea59abbff98771179183488d4614694bff67", size = 79211, upload-time = "2026-03-26T22:17:46.5Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/b9/f2dfa655e840cda5bc6ac5404695bf132e2fcafb2d7dfa5d1c8ea26b524a/pandas_gbq-0.35.0.tar.gz", hash = "sha256:596c908487ef0649a161e86ef272c00c267e581b95dc5ee0dc3518545b33bcfc", size = 79219, upload-time = "2026-04-10T00:41:19.354Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/51/72b7c3b25ecfc6810b29ae9bffe76e26a407adb20de5b90ed984b3d483ca/pandas_gbq-0.34.1-py3-none-any.whl", hash = "sha256:b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf", size = 50778, upload-time = "2026-03-26T22:15:20.992Z" }, + { url = "https://files.pythonhosted.org/packages/06/3d/2f0e9c5cbc456d34f48215645d876f7885a15e09a72a07d1de3ddb181c38/pandas_gbq-0.35.0-py3-none-any.whl", hash = "sha256:258de481019566611031919997bf9c1ece4ca30a4dd02d3fc3664b251d446182", size = 50773, upload-time = "2026-04-10T00:40:59.337Z" }, ] [[package]] @@ -16528,7 +16538,7 @@ wheels = [ [[package]] name = "pinecone" -version = "8.1.1" +version = "8.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -16539,9 +16549,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a8/4a/a8d26580a3522c0deeeb81504e53ba1a6c2f4eb9623629e24ab99020cd01/pinecone-8.1.1.tar.gz", hash = "sha256:077d42d0996969b1dbc9ad433a30be439f12c5dcad1bde647d5e39db97b16e78", size = 1041875, upload-time = "2026-04-02T13:54:11.948Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/09/cb00dd61e61e7a840e0ea7c3bf017335a49bed596ac3df9bf1d1237dd833/pinecone-8.1.2.tar.gz", hash = "sha256:a86d433cd2fec85b118ec19a44ee740a687c6b8172f1aecace83137f00c0741f", size = 1043253, upload-time = "2026-04-08T18:06:33.442Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/a5/0d45978aa0be9ec67259f38fdd089f3523a5db5eb283a09db090430f2b3d/pinecone-8.1.1-py3-none-any.whl", hash = "sha256:1ff2032310603814ee71675ba33a2998b4751edc9402c27af1550f9e5f74f21c", size = 742787, upload-time = "2026-04-02T13:54:10.309Z" }, + { url = "https://files.pythonhosted.org/packages/09/19/09b66463203393e9de5e84f8f581aa1e84cb1bfe664ff10ecd22cb7b923d/pinecone-8.1.2-py3-none-any.whl", hash = "sha256:9f91477e9f765c8392805d582b4fad9fe9732ce816276e10d89921e7894c6653", size = 742810, upload-time = "2026-04-08T18:06:31.261Z" }, ] [[package]] @@ -16591,23 +16601,23 @@ wheels = [ [[package]] name = "pipdeptree" -version = "2.34.0" +version = "2.35.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/fc/e05f4629ea01e0218c0858d4f1676349787558ce830b39c741ae169ea4a5/pipdeptree-2.34.0.tar.gz", hash = "sha256:9a43a0b4a16a5cbc4e6ab02966dfd5411b949ff8c7cb1de7ade960bef2db3537", size = 66683, upload-time = "2026-03-23T18:25:11.429Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/18/95aa034bf0ce37197f39b79c2b89cb1516bca99d5d1c905d1415716ac5e2/pipdeptree-2.35.0.tar.gz", hash = "sha256:e6cb5213d5b4d2c50258ba86f4ae06ced653111c664fe088c379f3c9a4d41562", size = 74148, upload-time = "2026-04-10T05:40:04.831Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/e7/6d83535bc50609473af9fcc687bb2b31b3d2dcf416ac9e11b8a113989d51/pipdeptree-2.34.0-py3-none-any.whl", hash = "sha256:4f5b77c07871103f6cf3c402093263609cbfd4e2ce3402bc8b9a7e984b2c6265", size = 44858, upload-time = "2026-03-23T18:25:09.947Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7f/9556d4900b667b899934ce63883a029c12cd7dbc1a81a066155d1e84fd03/pipdeptree-2.35.0-py3-none-any.whl", hash = "sha256:a233057842b1fa93825993f14d7b155e3a771b6d182cace689c817c1d54b4783", size = 48895, upload-time = "2026-04-10T05:40:03.259Z" }, ] [[package]] name = "platformdirs" -version = "4.9.4" +version = "4.9.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/19/56/8d4c30c8a1d07013911a8fdbd8f89440ef9f08d07a1b50ab8ca8be5a20f9/platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", size = 28737, upload-time = "2026-03-05T18:34:13.271Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868", size = 21216, upload-time = "2026-03-05T18:34:12.172Z" }, + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, ] [[package]] @@ -16747,11 +16757,11 @@ wheels = [ [[package]] name = "prometheus-client" -version = "0.24.1" +version = "0.25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/fb/d9aa83ffe43ce1f19e557c0971d04b90561b0cfd50762aafb01968285553/prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28", size = 86035, upload-time = "2026-04-09T19:53:42.359Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9b/d4b1e644385499c8346fa9b622a3f030dce14cd6ef8a1871c221a17a67e7/prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1", size = 64154, upload-time = "2026-04-09T19:53:41.324Z" }, ] [[package]] @@ -17308,7 +17318,7 @@ wheels = [ [[package]] name = "pydantic-ai-slim" -version = "1.77.0" +version = "1.79.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -17320,9 +17330,9 @@ dependencies = [ { name = "pydantic-graph" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/79/a7/ad011e626bed1f275fbaf933181573a50b05c2b9a0be927583d46fb8ff13/pydantic_ai_slim-1.77.0.tar.gz", hash = "sha256:a6e7006a4b048193d45b6ba816d301271e3f5ef1cdc4f9fb340617f382c6ce0d", size = 518781, upload-time = "2026-04-03T02:16:54.524Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/c3/8f20558616b2b9aa26792e08727ac53baca2e80f87de0587da803a4784ac/pydantic_ai_slim-1.79.0.tar.gz", hash = "sha256:463c552e926e953f78fe8ff5f82545e98816f92c6620bfd8dc8675b35190b827", size = 540871, upload-time = "2026-04-10T01:22:29.242Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/c5/5913cc4ae99047901c602f0d8208e3a75a7952b7e57d76169547307d7cea/pydantic_ai_slim-1.77.0-py3-none-any.whl", hash = "sha256:110c516935de384f1beddc36fda04e8df36cdf5bee3a5bfd0da562726182e52b", size = 664494, upload-time = "2026-04-03T02:16:46.668Z" }, + { url = "https://files.pythonhosted.org/packages/4c/8f/999efe177af0d6b244a478401790c7f8ea0b9e86ac9ad39e0e19c838a4fb/pydantic_ai_slim-1.79.0-py3-none-any.whl", hash = "sha256:2a79d47a3b74d82da83ae3a05db2d7c78c6a49d7ad8afedce1e2746a93d766b2", size = 693734, upload-time = "2026-04-10T01:22:21.33Z" }, ] [package.optional-dependencies] @@ -17476,7 +17486,7 @@ wheels = [ [[package]] name = "pydantic-graph" -version = "1.77.0" +version = "1.79.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -17484,9 +17494,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/40/a8b8e256bb90e4e284b35cc1c5e1a8e2724fa88ad89b7eac958fbf85852b/pydantic_graph-1.77.0.tar.gz", hash = "sha256:ba75dbdf221cd7e366e5c5d250f4d9f3138e05400ea52d3f36330772d989deee", size = 58689, upload-time = "2026-04-03T02:16:56.625Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/0c/13f0cd7f2dde132b7d8ea3f343f48f23913581139eafab1194744d9b7682/pydantic_graph-1.79.0.tar.gz", hash = "sha256:9b71916961b3ef5bcd1834560eda2928370d487785a15a3764298ffd26618e2e", size = 59239, upload-time = "2026-04-10T01:22:32.074Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/09/3c9c3aba8031adbd21d1833e8e4edd749697e50a88fa9bdab641874abe4f/pydantic_graph-1.77.0-py3-none-any.whl", hash = "sha256:063803e87aec901919c2073ccf3fdd6e4fff84e8b05dbfbe8a6c1af63dd12c05", size = 72503, upload-time = "2026-04-03T02:16:49.97Z" }, + { url = "https://files.pythonhosted.org/packages/c3/17/7fa99ecd68c53082499226b69b59aab86fb3b30f489a08af6d1fe4c648bf/pydantic_graph-1.79.0-py3-none-any.whl", hash = "sha256:7818c4995b08ee72a998a9513b9601bab7fee7684f3368ebe56db418881f5efd", size = 73064, upload-time = "2026-04-10T01:22:24.228Z" }, ] [[package]] @@ -18133,7 +18143,7 @@ kerberos = [ [[package]] name = "pytest" -version = "9.0.2" +version = "9.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -18144,9 +18154,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, + { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, ] [[package]] @@ -18316,15 +18326,15 @@ wheels = [ [[package]] name = "python-discovery" -version = "1.2.1" +version = "1.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/88/815e53084c5079a59df912825a279f41dd2e0df82281770eadc732f5352c/python_discovery-1.2.1.tar.gz", hash = "sha256:180c4d114bff1c32462537eac5d6a332b768242b76b69c0259c7d14b1b680c9e", size = 58457, upload-time = "2026-03-26T22:30:44.496Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872, upload-time = "2026-04-07T17:28:49.249Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl", hash = "sha256:b6a957b24c1cd79252484d3566d1b49527581d46e789aaf43181005e56201502", size = 31674, upload-time = "2026-03-26T22:30:43.396Z" }, + { url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894, upload-time = "2026-04-07T17:28:48.09Z" }, ] [[package]] @@ -18388,11 +18398,11 @@ sdist = { url = "https://files.pythonhosted.org/packages/0c/88/8d2797decc42e1c1c [[package]] name = "python-multipart" -version = "0.0.22" +version = "0.0.24" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/45/e23b5dc14ddb9918ae4a625379506b17b6f8fc56ca1d82db62462f59aea6/python_multipart-0.0.24.tar.gz", hash = "sha256:9574c97e1c026e00bc30340ef7c7d76739512ab4dfd428fec8c330fa6a5cc3c8", size = 37695, upload-time = "2026-04-05T20:49:13.829Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" }, + { url = "https://files.pythonhosted.org/packages/a3/73/89930efabd4da63cea44a3f438aeb753d600123570e6d6264e763617a9ce/python_multipart-0.0.24-py3-none-any.whl", hash = "sha256:9b110a98db707df01a53c194f0af075e736a770dc5058089650d70b4a182f950", size = 24420, upload-time = "2026-04-05T20:49:12.555Z" }, ] [[package]] @@ -19325,27 +19335,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e6/97/e9f1ca355108ef7194e38c812ef40ba98c7208f47b13ad78d023caa583da/ruff-0.15.9.tar.gz", hash = "sha256:29cbb1255a9797903f6dde5ba0188c707907ff44a9006eb273b5a17bfa0739a2", size = 4617361, upload-time = "2026-04-02T18:17:20.829Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/1f/9cdfd0ac4b9d1e5a6cf09bedabdf0b56306ab5e333c85c87281273e7b041/ruff-0.15.9-py3-none-linux_armv6l.whl", hash = "sha256:6efbe303983441c51975c243e26dff328aca11f94b70992f35b093c2e71801e1", size = 10511206, upload-time = "2026-04-02T18:16:41.574Z" }, - { url = "https://files.pythonhosted.org/packages/3d/f6/32bfe3e9c136b35f02e489778d94384118bb80fd92c6d92e7ccd97db12ce/ruff-0.15.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4965bac6ac9ea86772f4e23587746f0b7a395eccabb823eb8bfacc3fa06069f7", size = 10923307, upload-time = "2026-04-02T18:17:08.645Z" }, - { url = "https://files.pythonhosted.org/packages/ca/25/de55f52ab5535d12e7aaba1de37a84be6179fb20bddcbe71ec091b4a3243/ruff-0.15.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf05aad70ca5b5a0a4b0e080df3a6b699803916d88f006efd1f5b46302daab8", size = 10316722, upload-time = "2026-04-02T18:16:44.206Z" }, - { url = "https://files.pythonhosted.org/packages/48/11/690d75f3fd6278fe55fff7c9eb429c92d207e14b25d1cae4064a32677029/ruff-0.15.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9439a342adb8725f32f92732e2bafb6d5246bd7a5021101166b223d312e8fc59", size = 10623674, upload-time = "2026-04-02T18:16:50.951Z" }, - { url = "https://files.pythonhosted.org/packages/bd/ec/176f6987be248fc5404199255522f57af1b4a5a1b57727e942479fec98ad/ruff-0.15.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c5e6faf9d97c8edc43877c3f406f47446fc48c40e1442d58cfcdaba2acea745", size = 10351516, upload-time = "2026-04-02T18:16:57.206Z" }, - { url = "https://files.pythonhosted.org/packages/b2/fc/51cffbd2b3f240accc380171d51446a32aa2ea43a40d4a45ada67368fbd2/ruff-0.15.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b34a9766aeec27a222373d0b055722900fbc0582b24f39661aa96f3fe6ad901", size = 11150202, upload-time = "2026-04-02T18:17:06.452Z" }, - { url = "https://files.pythonhosted.org/packages/d6/d4/25292a6dfc125f6b6528fe6af31f5e996e19bf73ca8e3ce6eb7fa5b95885/ruff-0.15.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89dd695bc72ae76ff484ae54b7e8b0f6b50f49046e198355e44ea656e521fef9", size = 11988891, upload-time = "2026-04-02T18:17:18.575Z" }, - { url = "https://files.pythonhosted.org/packages/13/e1/1eebcb885c10e19f969dcb93d8413dfee8172578709d7ee933640f5e7147/ruff-0.15.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce187224ef1de1bd225bc9a152ac7102a6171107f026e81f317e4257052916d5", size = 11480576, upload-time = "2026-04-02T18:16:52.986Z" }, - { url = "https://files.pythonhosted.org/packages/ff/6b/a1548ac378a78332a4c3dcf4a134c2475a36d2a22ddfa272acd574140b50/ruff-0.15.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b0c7c341f68adb01c488c3b7d4b49aa8ea97409eae6462d860a79cf55f431b6", size = 11254525, upload-time = "2026-04-02T18:17:02.041Z" }, - { url = "https://files.pythonhosted.org/packages/42/aa/4bb3af8e61acd9b1281db2ab77e8b2c3c5e5599bf2a29d4a942f1c62b8d6/ruff-0.15.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:55cc15eee27dc0eebdfcb0d185a6153420efbedc15eb1d38fe5e685657b0f840", size = 11204072, upload-time = "2026-04-02T18:17:13.581Z" }, - { url = "https://files.pythonhosted.org/packages/69/48/d550dc2aa6e423ea0bcc1d0ff0699325ffe8a811e2dba156bd80750b86dc/ruff-0.15.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6537f6eed5cda688c81073d46ffdfb962a5f29ecb6f7e770b2dc920598997ed", size = 10594998, upload-time = "2026-04-02T18:16:46.369Z" }, - { url = "https://files.pythonhosted.org/packages/63/47/321167e17f5344ed5ec6b0aa2cff64efef5f9e985af8f5622cfa6536043f/ruff-0.15.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6d3fcbca7388b066139c523bda744c822258ebdcfbba7d24410c3f454cc9af71", size = 10359769, upload-time = "2026-04-02T18:17:10.994Z" }, - { url = "https://files.pythonhosted.org/packages/67/5e/074f00b9785d1d2c6f8c22a21e023d0c2c1817838cfca4c8243200a1fa87/ruff-0.15.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:058d8e99e1bfe79d8a0def0b481c56059ee6716214f7e425d8e737e412d69677", size = 10850236, upload-time = "2026-04-02T18:16:48.749Z" }, - { url = "https://files.pythonhosted.org/packages/76/37/804c4135a2a2caf042925d30d5f68181bdbd4461fd0d7739da28305df593/ruff-0.15.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8e1ddb11dbd61d5983fa2d7d6370ef3eb210951e443cace19594c01c72abab4c", size = 11358343, upload-time = "2026-04-02T18:16:55.068Z" }, - { url = "https://files.pythonhosted.org/packages/88/3d/1364fcde8656962782aa9ea93c92d98682b1ecec2f184e625a965ad3b4a6/ruff-0.15.9-py3-none-win32.whl", hash = "sha256:bde6ff36eaf72b700f32b7196088970bf8fdb2b917b7accd8c371bfc0fd573ec", size = 10583382, upload-time = "2026-04-02T18:17:04.261Z" }, - { url = "https://files.pythonhosted.org/packages/4c/56/5c7084299bd2cacaa07ae63a91c6f4ba66edc08bf28f356b24f6b717c799/ruff-0.15.9-py3-none-win_amd64.whl", hash = "sha256:45a70921b80e1c10cf0b734ef09421f71b5aa11d27404edc89d7e8a69505e43d", size = 11744969, upload-time = "2026-04-02T18:16:59.611Z" }, - { url = "https://files.pythonhosted.org/packages/03/36/76704c4f312257d6dbaae3c959add2a622f63fcca9d864659ce6d8d97d3d/ruff-0.15.9-py3-none-win_arm64.whl", hash = "sha256:0694e601c028fd97dc5c6ee244675bc241aeefced7ef80cd9c6935a871078f53", size = 11005870, upload-time = "2026-04-02T18:17:15.773Z" }, +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" }, ] [[package]] @@ -19676,7 +19686,7 @@ wheels = [ [[package]] name = "segment-analytics-python" -version = "2.3.3" +version = "2.3.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "backoff" }, @@ -19684,9 +19694,9 @@ dependencies = [ { name = "python-dateutil" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/01/7a231c76ec80a9b9769317638e59a902726ee60be88675c26f504a43c3c9/segment-analytics-python-2.3.3.tar.gz", hash = "sha256:ce6b3b4387ec9ebc5b55842c44d7dd63b4d4b0b8188e268c4492f909e5eeeed8", size = 34911, upload-time = "2024-10-07T16:21:43.676Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/7f/74dd70484cc33eb6b49499ac4afbc1ca9bbac40d0dee5712f75fb77b0c62/segment_analytics_python-2.3.6.tar.gz", hash = "sha256:b07779d90432399fdd08f8cbeb483139cab862b5dca1bb3f0711f415def776a8", size = 35997, upload-time = "2026-04-07T17:16:44.03Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/94/6d1512e0e54003eda9e1480cadf0e967bf1fffbd8454f4537bddc47f2a48/segment_analytics_python-2.3.3-py2.py3-none-any.whl", hash = "sha256:769251706d71f4c96d2039391d119222dbd9faf00308400f7b314ec9fb86cfc7", size = 32726, upload-time = "2024-10-07T16:21:42.014Z" }, + { url = "https://files.pythonhosted.org/packages/a5/5f/487b415925aac0f232a8aaae1f372f39ae13ca46207d923c4762efdddae5/segment_analytics_python-2.3.6-py2.py3-none-any.whl", hash = "sha256:a8c5c0f542be3be39aa57cd77e7e6b85b2a3c348174bc1192a296aeb81626594", size = 33477, upload-time = "2026-04-07T17:16:42.853Z" }, ] [[package]] @@ -20558,11 +20568,11 @@ wheels = [ [[package]] name = "sqlglot" -version = "30.2.1" +version = "30.4.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ff/5a/b8149963cd479a7e5b71f43d11d678f5e4b8633ab4de5b25e7a5d6eefa20/sqlglot-30.2.1.tar.gz", hash = "sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199", size = 5820630, upload-time = "2026-04-02T11:47:22.061Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/e9/0014221c8caddeeb24801fee95f8c6306db0b2d8baa36e5f843ac9427f2d/sqlglot-30.4.2.tar.gz", hash = "sha256:02775ae2a0c5c16fe307279c9f2cf107c1b7d6724a6f30306acd2a557472a3cd", size = 5827240, upload-time = "2026-04-08T19:50:23.021Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/69/13/f8c5dd59b119feee28cce53f23361d955cd46d0612697d49db0070f41ea9/sqlglot-30.2.1-py3-none-any.whl", hash = "sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1", size = 668564, upload-time = "2026-04-02T11:47:19.34Z" }, + { url = "https://files.pythonhosted.org/packages/de/fe/1e5289e2e5111d276ff060ae48a2c5795f669b99aeeda0bb005b1815e2c8/sqlglot-30.4.2-py3-none-any.whl", hash = "sha256:f9424479412cabc8f1e7ff9e90a442cd88c6586e8b36cceeb0fc5ca0b8bd3364", size = 670857, upload-time = "2026-04-08T19:50:20.816Z" }, ] [[package]] @@ -20758,13 +20768,13 @@ wheels = [ [[package]] name = "teradatasql" -version = "20.0.0.54" +version = "20.0.0.55" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycryptodome" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/7f/ffaaeeb58558f453c652943b7ba609aa38387473561b205f3752919f2a23/teradatasql-20.0.0.54-py3-none-any.whl", hash = "sha256:aea78894aba6a62769a7b030f52f42c7022a6208319b29b88f26da6826de33e7", size = 65839825, upload-time = "2026-03-19T20:50:43.036Z" }, + { url = "https://files.pythonhosted.org/packages/08/65/3d4e35be22adb9c6626728ead8b94614531a429708ae2f5987c8ed11e138/teradatasql-20.0.0.55-py3-none-any.whl", hash = "sha256:0bd7f465ff323a93727a67cab8575f0c44965aaa62154ce8851049d97e8721f5", size = 208557589, upload-time = "2026-04-08T18:38:53.745Z" }, ] [[package]] @@ -21266,20 +21276,20 @@ wheels = [ [[package]] name = "types-aiofiles" -version = "25.1.0.20251011" +version = "25.1.0.20260409" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/84/6c/6d23908a8217e36704aa9c79d99a620f2fdd388b66a4b7f72fbc6b6ff6c6/types_aiofiles-25.1.0.20251011.tar.gz", hash = "sha256:1c2b8ab260cb3cd40c15f9d10efdc05a6e1e6b02899304d80dfa0410e028d3ff", size = 14535, upload-time = "2025-10-11T02:44:51.237Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/66/9e62a2692792bc96c0f423f478149f4a7b84720704c546c8960b0a047c89/types_aiofiles-25.1.0.20260409.tar.gz", hash = "sha256:49e67d72bdcf9fe406f5815758a78dc34a1249bb5aa2adba78a80aec0a775435", size = 14812, upload-time = "2026-04-09T04:22:35.308Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/71/0f/76917bab27e270bb6c32addd5968d69e558e5b6f7fb4ac4cbfa282996a96/types_aiofiles-25.1.0.20251011-py3-none-any.whl", hash = "sha256:8ff8de7f9d42739d8f0dadcceeb781ce27cd8d8c4152d4a7c52f6b20edb8149c", size = 14338, upload-time = "2025-10-11T02:44:50.054Z" }, + { url = "https://files.pythonhosted.org/packages/27/d0/28236f869ba4dfb223ecdbc267eb2bdb634b81a561dd992230a4f9ec48fa/types_aiofiles-25.1.0.20260409-py3-none-any.whl", hash = "sha256:923fedb532c772cc0f62e0ce4282725afa82ca5b41cabd9857f06b55e5eee8de", size = 14372, upload-time = "2026-04-09T04:22:34.328Z" }, ] [[package]] name = "types-cachetools" -version = "6.2.0.20260317" +version = "6.2.0.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8b/7f/16a4d8344c28193a5a74358028c2d2f753f0d9658dd98b9e1967c50045a2/types_cachetools-6.2.0.20260317.tar.gz", hash = "sha256:6d91855bcc944665897c125e720aa3c80aace929b77a64e796343701df4f61c6", size = 9812, upload-time = "2026-03-17T04:06:32.007Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/61/475b0e8f4a92e5e33affcc6f4e6344c6dee540824021d22f695ea170da63/types_cachetools-6.2.0.20260408.tar.gz", hash = "sha256:0d8ae2dd5ba0b4cfe6a55c34396dd0415f1be07d0033d84781cdc4ed9c2ebc6b", size = 9854, upload-time = "2026-04-08T04:31:49.665Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/9a/b00b23054934c4d569c19f7278c4fb32746cd36a64a175a216d3073a4713/types_cachetools-6.2.0.20260317-py3-none-any.whl", hash = "sha256:92fa9bc50e4629e31fca67ceb3fb1de71791e314fa16c0a0d2728724dc222c8b", size = 9346, upload-time = "2026-03-17T04:06:31.184Z" }, + { url = "https://files.pythonhosted.org/packages/bb/7d/579f50f4f004ee93c7d1baa95339591cac1fe02f4e3fb8fc0f900ee4a80f/types_cachetools-6.2.0.20260408-py3-none-any.whl", hash = "sha256:470e0b274737feae74beed3d764885bf4664002ecc393fba3778846b13ce92cb", size = 9350, upload-time = "2026-04-08T04:31:48.826Z" }, ] [[package]] @@ -21293,50 +21303,50 @@ wheels = [ [[package]] name = "types-cffi" -version = "2.0.0.20260402" +version = "2.0.0.20260408" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "types-setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cb/85/3896bfcb4e7c32904f762c36ff0afa96d3e39bfce5a95a41635af79c8761/types_cffi-2.0.0.20260402.tar.gz", hash = "sha256:47e1320c009f630c59c55c8e3d2b8c501e280babf52e92f6109cbfb0864ba367", size = 17476, upload-time = "2026-04-02T04:21:09.332Z" } +sdist = { url = "https://files.pythonhosted.org/packages/64/67/eb4ef3408fdc0b4e5af38b30c0e6ad4663b41bdae9fb85a9f09a8db61a99/types_cffi-2.0.0.20260408.tar.gz", hash = "sha256:aa8b9c456ab715c079fc655929811f21f331bfb940f4a821987c581bf4e36230", size = 17541, upload-time = "2026-04-08T04:36:03.918Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/26/aacfef05841e31c65f889ae4225c6bce6b84cd5d3882c42a3661030f29ee/types_cffi-2.0.0.20260402-py3-none-any.whl", hash = "sha256:f647a400fba0a31d603479169d82ee5359db79bd1136e41dc7e6489296e3a2b2", size = 20103, upload-time = "2026-04-02T04:21:08.199Z" }, + { url = "https://files.pythonhosted.org/packages/c3/a3/7fbd93ededcc7c77e9e5948b9794161733ebdbf618a27965b1bea0e728a4/types_cffi-2.0.0.20260408-py3-none-any.whl", hash = "sha256:68bd296742b4ff7c0afe3547f50bd0acc55416ecf322ffefd2b7344ef6388a42", size = 20101, upload-time = "2026-04-08T04:36:02.995Z" }, ] [[package]] name = "types-croniter" -version = "6.2.2.20260402" +version = "6.2.2.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d2/3c/86cf37530b586c471a66b9246505f1f5094cf9aa22f7864daba731a281b9/types_croniter-6.2.2.20260402.tar.gz", hash = "sha256:1da2a6a76c81394876a576840829a94f0f43774e696cdeace26bbd2be46a6f00", size = 12005, upload-time = "2026-04-02T04:18:32.116Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/e4/89a0101471d6fe4e912dad24c54ae7afd90a9eaa5c74adef2c81f383f8da/types_croniter-6.2.2.20260408.tar.gz", hash = "sha256:a28a18908db371654990d30a3fd99856adc5137e475a23dbda4b10dce85525da", size = 12040, upload-time = "2026-04-08T04:27:20.068Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/6d/9bc5dce2f587742fd32399428a4f98f48bc09b8a74f87174a8d4e6837c5b/types_croniter-6.2.2.20260402-py3-none-any.whl", hash = "sha256:bf48ba148259a546eb9cd595bc48f9c3066dcc7af955aca2f1752eaa3e0f789d", size = 9730, upload-time = "2026-04-02T04:18:31.082Z" }, + { url = "https://files.pythonhosted.org/packages/c3/05/b32e67944ff33e83c181cadf5835858d63f4292a2f2ff5bf6a1edb7f6fed/types_croniter-6.2.2.20260408-py3-none-any.whl", hash = "sha256:242087a5b6e201b7004e55f71ed34f466951b74551c64ef1c6a8a08c47d3cc0d", size = 9732, upload-time = "2026-04-08T04:27:19.229Z" }, ] [[package]] name = "types-deprecated" -version = "1.3.1.20260402" +version = "1.3.1.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e2/ff/7e237c5118c1bd15e5205789901f7e01db232b0c61ca7c7c05de0394f5da/types_deprecated-1.3.1.20260402.tar.gz", hash = "sha256:00828ef7dce735d778583d00611f97da05b86b783ee14b0f22af2f945363cd12", size = 8481, upload-time = "2026-04-02T04:18:28.704Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1a/db/076de3e81b106d3cec17aec9640ab1b2d02f29bad441de280459c161ce65/types_deprecated-1.3.1.20260408.tar.gz", hash = "sha256:62d6a86d0cc754c14bb2de31162d069b1c6a07ce11ee65e5258f8f75308eb3a3", size = 8524, upload-time = "2026-04-08T04:26:39.894Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/3c/59aa775db5f69eba978390c33e1fd617817381cd87424ac1cff4bf2fb6c5/types_deprecated-1.3.1.20260402-py3-none-any.whl", hash = "sha256:ddf1813bd99cd1c00358cb0cb079878fdaa74509e7e482b79627f74f768f31a9", size = 9077, upload-time = "2026-04-02T04:18:27.867Z" }, + { url = "https://files.pythonhosted.org/packages/53/d0/d3258379deb749d949c3c72313981c9d2cceec518b87dcf506f022f5d49f/types_deprecated-1.3.1.20260408-py3-none-any.whl", hash = "sha256:b64e1eab560d4fa9394a27a3099211344b0e0f2f3ac8026d825c86e70d65cdd5", size = 9079, upload-time = "2026-04-08T04:26:38.752Z" }, ] [[package]] name = "types-docutils" -version = "0.22.3.20260322" +version = "0.22.3.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/44/bb/243a87fc1605a4a94c2c343d6dbddbf0d7ef7c0b9550f360b8cda8e82c39/types_docutils-0.22.3.20260322.tar.gz", hash = "sha256:e2450bb997283c3141ec5db3e436b91f0aa26efe35eb9165178ca976ccb4930b", size = 57311, upload-time = "2026-03-22T04:08:44.064Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3c/49/48a386fe15539556de085b87a69568b028cca2fa4b92596a3d4f79ac6784/types_docutils-0.22.3.20260408.tar.gz", hash = "sha256:22d5d45e4e0d65a1bc8280987a73e28669bb1cc9d16b18d0afc91713d1be26da", size = 57383, upload-time = "2026-04-08T04:27:26.924Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/4a/22c090cd4615a16917dff817cbe7c5956da376c961e024c241cd962d2c3d/types_docutils-0.22.3.20260322-py3-none-any.whl", hash = "sha256:681d4510ce9b80a0c6a593f0f9843d81f8caa786db7b39ba04d9fd5480ac4442", size = 91978, upload-time = "2026-03-22T04:08:43.117Z" }, + { url = "https://files.pythonhosted.org/packages/08/47/1667fda6e9fcb044f8fb797f6dc4367b88dc2ab40f1a035e387f5405e870/types_docutils-0.22.3.20260408-py3-none-any.whl", hash = "sha256:2545a86966022cdf1468d430b0007eba0837be77974a7f3fafa1b04a6815d531", size = 91981, upload-time = "2026-04-08T04:27:25.934Z" }, ] [[package]] name = "types-markdown" -version = "3.10.2.20260211" +version = "3.10.2.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/2e/35b30a09f6ee8a69142408d3ceb248c4454aa638c0a414d8704a3ef79563/types_markdown-3.10.2.20260211.tar.gz", hash = "sha256:66164310f88c11a58c6c706094c6f8c537c418e3525d33b76276a5fbd66b01ce", size = 19768, upload-time = "2026-02-11T04:19:29.497Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/0e/a690840934c459aa50e0470e7550d7f151632eafa4a8e3c21d18009ad15c/types_markdown-3.10.2.20260408.tar.gz", hash = "sha256:d5cba15ed65a1420e80e31c17e3d4a2ad7208a3f3a4da97fd2c5f093caf523cd", size = 19784, upload-time = "2026-04-08T04:33:07.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/c9/659fa2df04b232b0bfcd05d2418e683080e91ec68f636f3c0a5a267350e7/types_markdown-3.10.2.20260211-py3-none-any.whl", hash = "sha256:2d94d08587e3738203b3c4479c449845112b171abe8b5cadc9b0c12fcf3e99da", size = 25854, upload-time = "2026-02-11T04:19:28.647Z" }, + { url = "https://files.pythonhosted.org/packages/75/7e/265a8df257c8dced6ea89295f793a19f0a49ccbfeae1ed562368b2caf7a3/types_markdown-3.10.2.20260408-py3-none-any.whl", hash = "sha256:b0bbe8b7a8174db732067b86e391262898f5f536589ea81efec6d35ceb829331", size = 25857, upload-time = "2026-04-08T04:33:06.769Z" }, ] [[package]] @@ -21353,20 +21363,20 @@ wheels = [ [[package]] name = "types-protobuf" -version = "7.34.1.20260403" +version = "7.34.1.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/b3/c2e407ea36e0e4355c135127cee1b88a2cc9a2c92eafca50a360ab9f2708/types_protobuf-7.34.1.20260403.tar.gz", hash = "sha256:8d7881867888e667eb9563c08a916fccdc12bdb5f9f34c31d217cce876e36765", size = 68782, upload-time = "2026-04-03T04:18:09.428Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/b1/4521e68c2cc17703d80eb42796751345376dd4c706f84007ef5e7c707774/types_protobuf-7.34.1.20260408.tar.gz", hash = "sha256:e2c0a0430e08c75b52671a6f0035abfdcc791aad12af16274282de1b721758ab", size = 68835, upload-time = "2026-04-08T04:26:43.613Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/95/24fb0f6fe37b41cf94f9b9912712645e17d8048d4becaf37c1607ddd8e32/types_protobuf-7.34.1.20260403-py3-none-any.whl", hash = "sha256:16d9bbca52ab0f306279958878567df2520f3f5579059419b0ce149a0ad1e332", size = 86011, upload-time = "2026-04-03T04:18:08.245Z" }, + { url = "https://files.pythonhosted.org/packages/ef/b5/0bc9874d89c58fb0ce851e150055ce732d254dbb10b06becbc7635d0d635/types_protobuf-7.34.1.20260408-py3-none-any.whl", hash = "sha256:ebbcd4e27b145aef6a59bc0cb6c013b3528151c1ba5e7f7337aeee355d276a5e", size = 86012, upload-time = "2026-04-08T04:26:42.566Z" }, ] [[package]] name = "types-pymysql" -version = "1.1.0.20251220" +version = "1.1.0.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d3/59/e959dd6d2f8e3b3c3f058d79ac9ece328922a5a8770c707fe9c3a757481c/types_pymysql-1.1.0.20251220.tar.gz", hash = "sha256:ae1c3df32a777489431e2e9963880a0df48f6591e0aa2fd3a6fabd9dee6eca54", size = 22184, upload-time = "2025-12-20T03:07:38.689Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/04/c3570f05ebab083f28698c829dddf754ffefc30aae4e29915610848e44db/types_pymysql-1.1.0.20260408.tar.gz", hash = "sha256:b784dc37908479e3767e2d794ab507b3674adb1c686ca3d13fc9e2960dbcb9ec", size = 22344, upload-time = "2026-04-08T04:27:47.651Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/fa/4f4d3bfca9ef6dd17d69ed18b96564c53b32d3ce774132308d0bee849f10/types_pymysql-1.1.0.20251220-py3-none-any.whl", hash = "sha256:fa1082af7dea6c53b6caa5784241924b1296ea3a8d3bd060417352c5e10c0618", size = 23067, upload-time = "2025-12-20T03:07:37.766Z" }, + { url = "https://files.pythonhosted.org/packages/70/b3/15dee33878709705a4cc83bcc1bb30e00e95bbe038b472cb1207a15b50a1/types_pymysql-1.1.0.20260408-py3-none-any.whl", hash = "sha256:da630647eaaa7a926a3907794f4067f269cd245b2c202c74aa3c6a3bd660a9db", size = 23071, upload-time = "2026-04-08T04:27:46.735Z" }, ] [[package]] @@ -21384,11 +21394,11 @@ wheels = [ [[package]] name = "types-python-dateutil" -version = "2.9.0.20260402" +version = "2.9.0.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/30/c5d9efbff5422b20c9551dc5af237d1ab0c3d33729a9b3239a876ca47dd4/types_python_dateutil-2.9.0.20260402.tar.gz", hash = "sha256:a980142b9966713acb382c467e35c5cc4208a2f91b10b8d785a0ae6765df6c0b", size = 16941, upload-time = "2026-04-02T04:18:35.834Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/f3/2427775f80cd5e19a0a71ba8e5ab7645a01a852f43a5fd0ffc24f66338e0/types_python_dateutil-2.9.0.20260408.tar.gz", hash = "sha256:8b056ec01568674235f64ecbcef928972a5fac412f5aab09c516dfa2acfbb582", size = 16981, upload-time = "2026-04-08T04:28:10.995Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/d7/fe753bf8329c8c3c1addcba1d2bf716c33898216757abb24f8b80f82d040/types_python_dateutil-2.9.0.20260402-py3-none-any.whl", hash = "sha256:7827e6a9c93587cc18e766944254d1351a2396262e4abe1510cbbd7601c5e01f", size = 18436, upload-time = "2026-04-02T04:18:34.806Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c6/eeba37bfee282a6a97f889faef9352d6172c6a5088eb9a4daf570d9d748d/types_python_dateutil-2.9.0.20260408-py3-none-any.whl", hash = "sha256:473139d514a71c9d1fbd8bb328974bedcb1cc3dba57aad04ffa4157f483c216f", size = 18437, upload-time = "2026-04-08T04:28:10.095Z" }, ] [[package]] @@ -21402,20 +21412,20 @@ wheels = [ [[package]] name = "types-pytz" -version = "2026.1.1.20260402" +version = "2026.1.1.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/ff/52b895d4cb5f51f4ae50de8ca6a0b4098a71fa174b63f14d80ba86fa0692/types_pytz-2026.1.1.20260402.tar.gz", hash = "sha256:79209aa51dc003a4a6a764234d92b14e5c09a1b7f24e0f00c493929fd33618e8", size = 10726, upload-time = "2026-04-02T04:17:52.603Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/b7/33f5a4f29b1f285b99ff79a607751a7996194cbb98705e331dab7a2daa28/types_pytz-2026.1.1.20260408.tar.gz", hash = "sha256:89b6a34b9198ea2a4b98a9d15cbca987053f52a105fd44f7ce3789cae4349408", size = 10788, upload-time = "2026-04-08T04:28:14.54Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/79/ce/93d4fc3ba66be6cd50f3f22bbdb6fd953a02689398ea2c4a733e023c9227/types_pytz-2026.1.1.20260402-py3-none-any.whl", hash = "sha256:0d9a60ed1c6ad4fce7c6395b5bd2d9827db41d4b83de7c0322cf85869c2bfda3", size = 10122, upload-time = "2026-04-02T04:17:51.729Z" }, + { url = "https://files.pythonhosted.org/packages/ae/90/12c059e6bb330a22d9cc97daf027ac7fb7f50fbf518e4d88185b4d39120e/types_pytz-2026.1.1.20260408-py3-none-any.whl", hash = "sha256:c7e4dec76221fb7d0c97b91ad8561d689bebe39b6bcb7b728387e7ffd8cde788", size = 10124, upload-time = "2026-04-08T04:28:13.353Z" }, ] [[package]] name = "types-pyyaml" -version = "6.0.12.20250915" +version = "6.0.12.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7e/69/3c51b36d04da19b92f9e815be12753125bd8bc247ba0470a982e6979e71c/types_pyyaml-6.0.12.20250915.tar.gz", hash = "sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3", size = 17522, upload-time = "2025-09-15T03:01:00.728Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/73/b759b1e413c31034cc01ecdfb96b38115d0ab4db55a752a3929f0cd449fd/types_pyyaml-6.0.12.20260408.tar.gz", hash = "sha256:92a73f2b8d7f39ef392a38131f76b970f8c66e4c42b3125ae872b7c93b556307", size = 17735, upload-time = "2026-04-08T04:30:50.974Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/e0/1eed384f02555dde685fff1a1ac805c1c7dcb6dd019c916fe659b1c1f9ec/types_pyyaml-6.0.12.20250915-py3-none-any.whl", hash = "sha256:e7d4d9e064e89a3b3cae120b4990cd370874d2bf12fa5f46c97018dd5d3c9ab6", size = 20338, upload-time = "2025-09-15T03:00:59.218Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f0/c391068b86abb708882c6d75a08cd7d25b2c7227dab527b3a3685a3c635b/types_pyyaml-6.0.12.20260408-py3-none-any.whl", hash = "sha256:fbc42037d12159d9c801ebfcc79ebd28335a7c13b08a4cfbc6916df78fee9384", size = 20339, upload-time = "2026-04-08T04:30:50.113Z" }, ] [[package]] @@ -21433,41 +21443,41 @@ wheels = [ [[package]] name = "types-requests" -version = "2.33.0.20260402" +version = "2.33.0.20260408" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/7b/a06527d20af1441d813360b8e0ce152a75b7d8e4aab7c7d0a156f405d7ec/types_requests-2.33.0.20260402.tar.gz", hash = "sha256:1bdd3ada9b869741c5c4b887d2c8b4e38284a1449751823b5ebbccba3eefd9da", size = 23851, upload-time = "2026-04-02T04:19:55.942Z" } +sdist = { url = "https://files.pythonhosted.org/packages/69/6a/749dc53a54a3f35842c1f8197b3ca6b54af6d7458a1bfc75f6629b6da666/types_requests-2.33.0.20260408.tar.gz", hash = "sha256:95b9a86376807a216b2fb412b47617b202091c3ea7c078f47cc358d5528ccb7b", size = 23882, upload-time = "2026-04-08T04:34:49.33Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/65/3853bb6bac5ae789dc7e28781154705c27859eccc8e46282c3f36780f5f5/types_requests-2.33.0.20260402-py3-none-any.whl", hash = "sha256:c98372d7124dd5d10af815ee25c013897592ff92af27b27e22c98984102c3254", size = 20739, upload-time = "2026-04-02T04:19:54.955Z" }, + { url = "https://files.pythonhosted.org/packages/90/b8/78fd6c037de4788c040fdd323b3369804400351b7827473920f6c1d03c10/types_requests-2.33.0.20260408-py3-none-any.whl", hash = "sha256:81f31d5ea4acb39f03be7bc8bed569ba6d5a9c5d97e89f45ac43d819b68ca50f", size = 20739, upload-time = "2026-04-08T04:34:48.325Z" }, ] [[package]] name = "types-setuptools" -version = "82.0.0.20260402" +version = "82.0.0.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e9/f8/74f8a76b4311e70772c0df8f2d432040a3b0facd7bcce6b72b0b26e1746b/types_setuptools-82.0.0.20260402.tar.gz", hash = "sha256:63d2b10ba7958396ad79bbc24d2f6311484e452daad4637ffd40407983a27069", size = 44805, upload-time = "2026-04-02T04:17:49.229Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/12/3464b410c50420dd4674fa5fe9d3880711c1dbe1a06f5fe4960ee9067b9e/types_setuptools-82.0.0.20260408.tar.gz", hash = "sha256:036c68caf7e672a699f5ebbf914708d40644c14e05298bc49f7272be91cf43d3", size = 44861, upload-time = "2026-04-08T04:29:33.292Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/e9/22451997f70ac2c5f18dc5f988750c986011fb049d9021767277119e63fa/types_setuptools-82.0.0.20260402-py3-none-any.whl", hash = "sha256:4b9a9f6c3c4c65107a3956ad6a6acbccec38e398ff6d5f78d5df7f103dadb8d6", size = 68429, upload-time = "2026-04-02T04:17:48.11Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e1/46a4fc3ef03aabf5d18bac9df5cf37c6b02c3bddf3e05c3533f4b4588331/types_setuptools-82.0.0.20260408-py3-none-any.whl", hash = "sha256:ece0a215cdfa6463a65fd6f68bd940f39e455729300ddfe61cab1147ed1d2462", size = 68428, upload-time = "2026-04-08T04:29:32.175Z" }, ] [[package]] name = "types-tabulate" -version = "0.10.0.20260308" +version = "0.10.0.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5f/44/d9e94f06010dde47b89892b2b133e3e54da729d8280ead4165dfdfa484ea/types_tabulate-0.10.0.20260308.tar.gz", hash = "sha256:724dcb1330ffba5f46d3cf6e29f45089fccb8e85801e6e7ac9efb1195bf7bea1", size = 8364, upload-time = "2026-03-08T03:59:59.472Z" } +sdist = { url = "https://files.pythonhosted.org/packages/78/59/b563bfb6e216b8573052c09cb4abcbdca836487db4cfad9b7d492c327c0b/types_tabulate-0.10.0.20260408.tar.gz", hash = "sha256:903d62fdf7e5a0ff659fd5d629df716232f7658c6d30e98f0374488d06ffacf4", size = 8367, upload-time = "2026-04-08T04:30:00.482Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/74/3097387a6efcaef5ae92c7707a1a3e34a3881457d9ef1443a33681a77e08/types_tabulate-0.10.0.20260308-py3-none-any.whl", hash = "sha256:94a9795965bc6290f844d61e8680a1270040664b88fd12014624090fd847e13c", size = 8139, upload-time = "2026-03-08T03:59:58.678Z" }, + { url = "https://files.pythonhosted.org/packages/38/d1/34e27f543dd944f51fc6b0013a1a41113079cede9cc3be0a5f426f2f8d9d/types_tabulate-0.10.0.20260408-py3-none-any.whl", hash = "sha256:2b19d193603d38c34645de53c0c1087e2364487d518d4a2f44268db2366723cc", size = 8139, upload-time = "2026-04-08T04:29:59.699Z" }, ] [[package]] name = "types-toml" -version = "0.10.8.20240310" +version = "0.10.8.20260408" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/47/3e4c75042792bff8e90d7991aa5c51812cc668828cc6cce711e97f63a607/types-toml-0.10.8.20240310.tar.gz", hash = "sha256:3d41501302972436a6b8b239c850b26689657e25281b48ff0ec06345b8830331", size = 4392, upload-time = "2024-03-10T02:18:37.518Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/9b/887564a51a84c96ba08b715570e546f0ea793df6372b736bfbc596ca5536/types_toml-0.10.8.20260408.tar.gz", hash = "sha256:6b30b031235565a12febb1388900b129f1adeabfcfa594da46d0372b2ac107ad", size = 9341, upload-time = "2026-04-08T04:27:54.394Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/a2/d32ab58c0b216912638b140ab2170ee4b8644067c293b170e19fba340ccc/types_toml-0.10.8.20240310-py3-none-any.whl", hash = "sha256:627b47775d25fa29977d9c70dc0cbab3f314f32c8d8d0c012f2ef5de7aaec05d", size = 4777, upload-time = "2024-03-10T02:18:36.568Z" }, + { url = "https://files.pythonhosted.org/packages/56/f1/942d95ba026779bc6e3064f8b094216588dc3276cc328cf8e03a0541918d/types_toml-0.10.8.20260408-py3-none-any.whl", hash = "sha256:e958d4c660385e548705a298f17dc162baf44c8b6d6aff79aeefe75f4f77ac87", size = 9677, upload-time = "2026-04-08T04:27:53.526Z" }, ] [[package]] @@ -21588,42 +21598,42 @@ wheels = [ [[package]] name = "uv" -version = "0.11.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/ed/f11c558e8d2e02fba6057dacd9e92a71557359a80bd5355452310b89f40f/uv-0.11.3.tar.gz", hash = "sha256:6a6fcaf1fec28bbbdf0dfc5a0a6e34be4cea08c6287334b08c24cf187300f20d", size = 4027684, upload-time = "2026-04-01T21:47:22.096Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/93/4f04c49fd6046a18293de341d795ded3b9cbd95db261d687e26db0f11d1e/uv-0.11.3-py3-none-linux_armv6l.whl", hash = "sha256:deb533e780e8181e0859c68c84f546620072cd1bd827b38058cb86ebfba9bb7d", size = 23337334, upload-time = "2026-04-01T21:46:47.545Z" }, - { url = "https://files.pythonhosted.org/packages/7a/4b/c44fd3fbc80ac2f81e2ad025d235c820aac95b228076da85be3f5d509781/uv-0.11.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d2b3b0fa1693880ca354755c216ae1c65dd938a4f1a24374d0c3f4b9538e0ee6", size = 22940169, upload-time = "2026-04-01T21:47:32.72Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c7/7d01be259a47d42fa9e80adcb7a829d81e7c376aa8fa1b714f31d7dfc226/uv-0.11.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:71f5d0b9e73daa5d8a7e2db3fa2e22a4537d24bb4fe78130db797280280d4edc", size = 21473579, upload-time = "2026-04-01T21:47:25.063Z" }, - { url = "https://files.pythonhosted.org/packages/9a/71/fffcd890290a4639a3799cf3f3e87947c10d1b0de19eba3cf837cb418dd8/uv-0.11.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:55ba578752f29a3f2b22879b22a162edad1454e3216f3ca4694fdbd4093a6822", size = 23132691, upload-time = "2026-04-01T21:47:44.587Z" }, - { url = "https://files.pythonhosted.org/packages/d1/7b/1ac9e1f753a19b6252434f0bbe96efdcc335cd74677f4c6f431a7c916114/uv-0.11.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:3b1fe09d5e1d8e19459cd28d7825a3b66ef147b98328345bad6e17b87c4fea48", size = 22955764, upload-time = "2026-04-01T21:46:51.721Z" }, - { url = "https://files.pythonhosted.org/packages/ff/51/1a6010a681a3c3e0a8ec99737ba2d0452194dc372a5349a9267873261c02/uv-0.11.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:088165b9eed981d2c2a58566cc75dd052d613e47c65e2416842d07308f793a6f", size = 22966245, upload-time = "2026-04-01T21:47:07.403Z" }, - { url = "https://files.pythonhosted.org/packages/38/74/1a1b0712daead7e85f56d620afe96fe166a04b615524c14027b4edd39b82/uv-0.11.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef0ae8ee2988928092616401ec7f473612b8e9589fe1567452c45dbc56840f85", size = 24623370, upload-time = "2026-04-01T21:47:03.59Z" }, - { url = "https://files.pythonhosted.org/packages/b6/62/5c3aa5e7bd2744810e50ad72a5951386ec84a513e109b1b5cb7ec442f3b6/uv-0.11.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6708827ecb846d00c5512a7e4dc751c2e27b92e9bd55a0be390561ac68930c32", size = 25142735, upload-time = "2026-04-01T21:46:55.756Z" }, - { url = "https://files.pythonhosted.org/packages/88/ab/6266a04980e0877af5518762adfe23a0c1ab0b801ae3099a2e7b74e34411/uv-0.11.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8df030ea7563e99c09854e1bc82ab743dfa2d0ba18976e6861979cb40d04dba7", size = 24512083, upload-time = "2026-04-01T21:46:43.531Z" }, - { url = "https://files.pythonhosted.org/packages/4e/be/7c66d350f833eb437f9aa0875655cc05e07b441e3f4a770f8bced56133f7/uv-0.11.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fde893b5ab9f6997fe357138e794bac09d144328052519fbbe2e6f72145e457", size = 24589293, upload-time = "2026-04-01T21:47:11.379Z" }, - { url = "https://files.pythonhosted.org/packages/18/4f/22ada41564a8c8c36653fc86f89faae4c54a4cdd5817bda53764a3eb352d/uv-0.11.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:45006bcd9e8718248a23ab81448a5beb46a72a9dd508e3212d6f3b8c63aeb88a", size = 23214854, upload-time = "2026-04-01T21:46:59.491Z" }, - { url = "https://files.pythonhosted.org/packages/aa/18/8669840657fea9fd668739dec89643afe1061c023c1488228b02f79a2399/uv-0.11.3-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:089b9d338a64463956b6fee456f03f73c9a916479bdb29009600781dc1e1d2a7", size = 23914434, upload-time = "2026-04-01T21:47:29.164Z" }, - { url = "https://files.pythonhosted.org/packages/08/0d/c59f24b3a1ae5f377aa6fd9653562a0968ea6be946fe35761871a0072919/uv-0.11.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3ff461335888336467402cc5cb792c911df95dd0b52e369182cfa4c902bb21f4", size = 23971481, upload-time = "2026-04-01T21:47:48.551Z" }, - { url = "https://files.pythonhosted.org/packages/66/7d/f83ed79921310ef216ed6d73fcd3822dff4b66749054fb97e09b7bd5901e/uv-0.11.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:a62e29277efd39c35caf4a0fe739c4ebeb14d4ce4f02271f3f74271d608061ff", size = 23784797, upload-time = "2026-04-01T21:47:40.588Z" }, - { url = "https://files.pythonhosted.org/packages/35/19/3ff3539c44ca7dc2aa87b021d4a153ba6a72866daa19bf91c289e4318f95/uv-0.11.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:ebccdcdebd2b288925f0f7c18c39705dc783175952eacaf94912b01d3b381b86", size = 24794606, upload-time = "2026-04-01T21:47:36.814Z" }, - { url = "https://files.pythonhosted.org/packages/79/e5/e676454bb7cc5dcf5c4637ed3ef0ff97309d84a149b832a4dea53f04c0ab/uv-0.11.3-py3-none-win32.whl", hash = "sha256:794aae3bab141eafbe37c51dc5dd0139658a755a6fa9cc74d2dbd7c71dcc4826", size = 22573432, upload-time = "2026-04-01T21:47:15.143Z" }, - { url = "https://files.pythonhosted.org/packages/ff/a0/95d22d524bd3b4708043d65035f02fc9656e5fb6e0aaef73510313b1641b/uv-0.11.3-py3-none-win_amd64.whl", hash = "sha256:68fda574f2e5e7536a2b747dcea88329a71aad7222317e8f4717d0af8f99fbd4", size = 24969508, upload-time = "2026-04-01T21:47:19.515Z" }, - { url = "https://files.pythonhosted.org/packages/f8/6d/3f0b90a06e8c4594e11f813651756d6896de6dd4461f554fd7e4984a1c4f/uv-0.11.3-py3-none-win_arm64.whl", hash = "sha256:92ffc4d521ab2c4738ef05d8ef26f2750e26d31f3ad5611cdfefc52445be9ace", size = 23488911, upload-time = "2026-04-01T21:47:52.427Z" }, +version = "0.11.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/f3/8aceeab67ea69805293ab290e7ca8cc1b61a064d28b8a35c76d8eba063dd/uv-0.11.6.tar.gz", hash = "sha256:e3b21b7e80024c95ff339fcd147ac6fc3dd98d3613c9d45d3a1f4fd1057f127b", size = 4073298, upload-time = "2026-04-09T12:09:01.738Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/fe/4b61a3d5ad9d02e8a4405026ccd43593d7044598e0fa47d892d4dafe44c9/uv-0.11.6-py3-none-linux_armv6l.whl", hash = "sha256:ada04dcf89ddea5b69d27ac9cdc5ef575a82f90a209a1392e930de504b2321d6", size = 23780079, upload-time = "2026-04-09T12:08:56.609Z" }, + { url = "https://files.pythonhosted.org/packages/52/db/d27519a9e1a5ffee9d71af1a811ad0e19ce7ab9ae815453bef39dd479389/uv-0.11.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5be013888420f96879c6e0d3081e7bcf51b539b034a01777041934457dfbedf3", size = 23214721, upload-time = "2026-04-09T12:09:32.228Z" }, + { url = "https://files.pythonhosted.org/packages/a6/8f/4399fa8b882bd7e0efffc829f73ab24d117d490a93e6bc7104a50282b854/uv-0.11.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ffa5dc1cbb52bdce3b8447e83d1601a57ad4da6b523d77d4b47366db8b1ceb18", size = 21750109, upload-time = "2026-04-09T12:09:24.357Z" }, + { url = "https://files.pythonhosted.org/packages/32/07/5a12944c31c3dda253632da7a363edddb869ed47839d4d92a2dc5f546c93/uv-0.11.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:bfb107b4dade1d2c9e572992b06992d51dd5f2136eb8ceee9e62dd124289e825", size = 23551146, upload-time = "2026-04-09T12:09:10.439Z" }, + { url = "https://files.pythonhosted.org/packages/79/5b/2ec8b0af80acd1016ed596baf205ddc77b19ece288473b01926c4a9cf6db/uv-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:9e2fe7ce12161d8016b7deb1eaad7905a76ff7afec13383333ca75e0c4b5425d", size = 23331192, upload-time = "2026-04-09T12:09:34.792Z" }, + { url = "https://files.pythonhosted.org/packages/62/7d/eea35935f2112b21c296a3e42645f3e4b1aa8bcd34dcf13345fbd55134b7/uv-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ed9c6f70c25e8dfeedddf4eddaf14d353f5e6b0eb43da9a14d3a1033d51d915", size = 23337686, upload-time = "2026-04-09T12:09:18.522Z" }, + { url = "https://files.pythonhosted.org/packages/21/47/2584f5ab618f6ebe9bdefb2f765f2ca8540e9d739667606a916b35449eec/uv-0.11.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d68a013e609cebf82077cbeeb0809ed5e205257814273bfd31e02fc0353bbfc2", size = 25008139, upload-time = "2026-04-09T12:09:03.983Z" }, + { url = "https://files.pythonhosted.org/packages/95/81/497ae5c1d36355b56b97dc59f550c7e89d0291c163a3f203c6f341dff195/uv-0.11.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93f736dddca03dae732c6fdea177328d3bc4bf137c75248f3d433c57416a4311", size = 25712458, upload-time = "2026-04-09T12:09:07.598Z" }, + { url = "https://files.pythonhosted.org/packages/3c/1c/74083238e4fab2672b63575b9008f1ea418b02a714bcfcf017f4f6a309b6/uv-0.11.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e96a66abe53fced0e3389008b8d2eff8278cfa8bb545d75631ae8ceb9c929aba", size = 24915507, upload-time = "2026-04-09T12:08:50.892Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ee/e14fe10ba455a823ed18233f12de6699a601890905420b5c504abf115116/uv-0.11.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b096311b2743b228df911a19532b3f18fa420bf9530547aecd6a8e04bbfaccd", size = 24971011, upload-time = "2026-04-09T12:08:54.016Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/7b9c83eaadf98e343317ff6384a7227a4855afd02cdaf9696bcc71ee6155/uv-0.11.6-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:904d537b4a6e798015b4a64ff5622023bd4601b43b6cd1e5f423d63471f5e948", size = 23640234, upload-time = "2026-04-09T12:09:15.735Z" }, + { url = "https://files.pythonhosted.org/packages/d6/51/75ccdd23e76ff1703b70eb82881cd5b4d2a954c9679f8ef7e0136ef2cfab/uv-0.11.6-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:4ed8150c26b5e319381d75ae2ce6aba1e9c65888f4850f4e3b3fa839953c90a5", size = 24452664, upload-time = "2026-04-09T12:09:26.875Z" }, + { url = "https://files.pythonhosted.org/packages/4d/86/ace80fe47d8d48b5e3b5aee0b6eb1a49deaacc2313782870250b3faa36f5/uv-0.11.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1c9218c8d4ac35ca6e617fb0951cc0ab2d907c91a6aea2617de0a5494cf162c0", size = 24494599, upload-time = "2026-04-09T12:09:37.368Z" }, + { url = "https://files.pythonhosted.org/packages/05/2d/4b642669b56648194f026de79bc992cbfc3ac2318b0a8d435f3c284934e8/uv-0.11.6-py3-none-musllinux_1_1_i686.whl", hash = "sha256:9e211c83cc890c569b86a4183fcf5f8b6f0c7adc33a839b699a98d30f1310d3a", size = 24159150, upload-time = "2026-04-09T12:09:13.17Z" }, + { url = "https://files.pythonhosted.org/packages/ae/24/7eecd76fe983a74fed1fc700a14882e70c4e857f1d562a9f2303d4286c12/uv-0.11.6-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d2a1d2089afdf117ad19a4c1dd36b8189c00ae1ad4135d3bfbfced82342595cf", size = 25164324, upload-time = "2026-04-09T12:08:59.56Z" }, + { url = "https://files.pythonhosted.org/packages/27/e0/bbd4ba7c2e5067bbba617d87d306ec146889edaeeaa2081d3e122178ca08/uv-0.11.6-py3-none-win32.whl", hash = "sha256:6e8344f38fa29f85dcfd3e62dc35a700d2448f8e90381077ef393438dcd5012e", size = 22865693, upload-time = "2026-04-09T12:09:21.415Z" }, + { url = "https://files.pythonhosted.org/packages/a5/33/1983ce113c538a856f2d620d16e39691962ecceef091a84086c5785e32e5/uv-0.11.6-py3-none-win_amd64.whl", hash = "sha256:a28bea69c1186303d1200f155c7a28c449f8a4431e458fcf89360cc7ef546e40", size = 25371258, upload-time = "2026-04-09T12:09:40.52Z" }, + { url = "https://files.pythonhosted.org/packages/35/01/be0873f44b9c9bc250fcbf263367fcfc1f59feab996355bcb6b52fff080d/uv-0.11.6-py3-none-win_arm64.whl", hash = "sha256:a78f6d64b9950e24061bc7ec7f15ff8089ad7f5a976e7b65fcadce58fe02f613", size = 23869585, upload-time = "2026-04-09T12:09:29.425Z" }, ] [[package]] name = "uvicorn" -version = "0.43.0" +version = "0.44.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/62/f2/368268300fb8af33743508d738ef7bb4d56afdb46c6d9c0fa3dd515df171/uvicorn-0.43.0.tar.gz", hash = "sha256:ab1652d2fb23abf124f36ccc399828558880def222c3cb3d98d24021520dc6e8", size = 85686, upload-time = "2026-04-03T18:37:48.984Z" } +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" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/df/0cf5b0c451602748fdc7a702d4667f6e209bf96aa6e3160d754234445f2a/uvicorn-0.43.0-py3-none-any.whl", hash = "sha256:46fac64f487fd968cd999e5e49efbbe64bd231b5bd8b4a0b482a23ebce499620", size = 68591, upload-time = "2026-04-03T18:37:47.64Z" }, + { 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" }, ] [package.optional-dependencies] @@ -21714,7 +21724,7 @@ wheels = [ [[package]] name = "virtualenv" -version = "21.2.0" +version = "21.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, @@ -21723,9 +21733,9 @@ dependencies = [ { name = "python-discovery" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/92/58199fe10049f9703c2666e809c4f686c54ef0a68b0f6afccf518c0b1eb9/virtualenv-21.2.0.tar.gz", hash = "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098", size = 5840618, upload-time = "2026-03-09T17:24:38.013Z" } +sdist = { url = "https://files.pythonhosted.org/packages/97/c5/aff062c66b42e2183201a7ace10c6b2e959a9a16525c8e8ca8e59410d27a/virtualenv-21.2.1.tar.gz", hash = "sha256:b66ffe81301766c0d5e2208fc3576652c59d44e7b731fc5f5ed701c9b537fa78", size = 5844770, upload-time = "2026-04-09T18:47:11.482Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/59/7d02447a55b2e55755011a647479041bc92a82e143f96a8195cb33bd0a1c/virtualenv-21.2.0-py3-none-any.whl", hash = "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f", size = 5825084, upload-time = "2026-03-09T17:24:35.378Z" }, + { url = "https://files.pythonhosted.org/packages/20/0e/f083a76cb590e60dff3868779558eefefb8dfb7c9ed020babc7aa014ccbf/virtualenv-21.2.1-py3-none-any.whl", hash = "sha256:bd16b49c53562b28cf1a3ad2f36edb805ad71301dee70ddc449e5c88a9f919a2", size = 5828326, upload-time = "2026-04-09T18:47:09.331Z" }, ] [[package]] @@ -22205,7 +22215,7 @@ wheels = [ [[package]] name = "yandexcloud" -version = "0.384.0" +version = "0.385.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, @@ -22218,9 +22228,9 @@ dependencies = [ { name = "requests" }, { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2b/85/0d9880e830c758232078cb1c660ad30a5b43e3d1375da597e80b41869b3d/yandexcloud-0.384.0.tar.gz", hash = "sha256:d7ec0ae02e803d755f5b591263962ecd8883e46fffc386e684b6de532d0d0d43", size = 3850947, upload-time = "2026-03-30T15:33:52.504Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/0e/bdffb69294a6f6a550078f993b316c3ba10d98dc49d82395ad1308706841/yandexcloud-0.385.0.tar.gz", hash = "sha256:942e2b083e0d9e149c2aa0704a03dc6ff14b95c1bbf11b39caa16ba3d4d6db6a", size = 3857717, upload-time = "2026-04-06T15:21:29.288Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/d0/2d0d8a18210c950b828a74324e36c72c9dfa2314aa7ab56b7054d482fc4e/yandexcloud-0.384.0-py3-none-any.whl", hash = "sha256:1e220e7e58a097fa87aa19302bfe2aeeb3b227178abb2003649cae382163754b", size = 5892386, upload-time = "2026-03-30T15:33:50.5Z" }, + { url = "https://files.pythonhosted.org/packages/b9/48/2ea2f330230f617c8d0d18344c0c0305ec7dbe08fbdf8b073d48bf01cc75/yandexcloud-0.385.0-py3-none-any.whl", hash = "sha256:fa709ab75685c349c00df02f4fa0553362022bab906c03559fa374f7087e2bdd", size = 5898630, upload-time = "2026-04-06T15:21:26.607Z" }, ] [[package]] @@ -22365,7 +22375,7 @@ wheels = [ [[package]] name = "ydb" -version = "3.26.10" +version = "3.28.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -22373,9 +22383,9 @@ dependencies = [ { name = "packaging" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/93/95/a0f2382ad38c14f092a1b5828f436a579ac6b2ed6db0bfcb53ef555b9392/ydb-3.26.10.tar.gz", hash = "sha256:315a5719b7c5aa5d2791f27bf1cd43f29d585d38cab20c7f8b0611b661487e54", size = 996073, upload-time = "2026-04-01T18:51:32.341Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/95/2ac725c329cddb15c013dc37f3cb012cf6c7fd002bd8ea691a707c3b2669/ydb-3.28.0.tar.gz", hash = "sha256:cd7ad6db3d13f188bef0088ccf025fce0318d85c319002dbf382d18e8ca31234", size = 1000722, upload-time = "2026-04-09T08:00:55.015Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/81/cc64dea928b474648f56cece02dbaf9355b48d99790fd6ed34547f20431a/ydb-3.26.10-py2.py3-none-any.whl", hash = "sha256:86fbbda96afd658acf43ed7e5c098e827016575b83de1d3628b214f51a475fc8", size = 1328780, upload-time = "2026-04-01T18:51:30.595Z" }, + { url = "https://files.pythonhosted.org/packages/25/ed/169e9ccd65eec0357a367f90eaf59f268e9a468be8601331685bbad8211d/ydb-3.28.0-py2.py3-none-any.whl", hash = "sha256:c7f93b803c404ddebe3186a8b0977910a96f17e2c9da7817e5b08068d4192ec8", size = 1333529, upload-time = "2026-04-09T08:00:53.079Z" }, ] [[package]] @@ -22445,40 +22455,40 @@ wheels = [ [[package]] name = "zope-interface" -version = "8.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/a4/77daa5ba398996d16bb43fc721599d27d03eae68fe3c799de1963c72e228/zope_interface-8.2.tar.gz", hash = "sha256:afb20c371a601d261b4f6edb53c3c418c249db1a9717b0baafc9a9bb39ba1224", size = 254019, upload-time = "2026-01-09T07:51:07.253Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/fa/6d9eb3a33998a3019d7eb4fa1802d01d6602fad90e0aea443e6e0fe8e49a/zope_interface-8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:788c293f3165964ec6527b2d861072c68eef53425213f36d3893ebee89a89623", size = 207541, upload-time = "2026-01-09T08:04:55.378Z" }, - { url = "https://files.pythonhosted.org/packages/19/8c/ad23c96fdee84cb1f768f6695dac187cc26e9038e01c69713ba0f7dc46ab/zope_interface-8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9a4e785097e741a1c953b3970ce28f2823bd63c00adc5d276f2981dd66c96c15", size = 208075, upload-time = "2026-01-09T08:04:57.118Z" }, - { url = "https://files.pythonhosted.org/packages/dd/35/1bfd5fec31a307f0cf4065ee74ade63858ded3e2a71e248f1508118fcc95/zope_interface-8.2-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:16c69da19a06566664ddd4785f37cad5693a51d48df1515d264c20d005d322e2", size = 249528, upload-time = "2026-01-09T08:04:59.074Z" }, - { url = "https://files.pythonhosted.org/packages/c6/3a/5d50b5fdb0f8226a2edff6adb7efdd3762ec95dff827dbab1761cb9a9e85/zope_interface-8.2-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c31acfa3d7cde48bec45701b0e1f4698daffc378f559bfb296837d8c834732f6", size = 254646, upload-time = "2026-01-09T08:05:00.964Z" }, - { url = "https://files.pythonhosted.org/packages/2f/2a/ee7d675e151578eaf77828b8faac2b7ed9a69fead350bf5cf0e4afe7c73d/zope_interface-8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0723507127f8269b8f3f22663168f717e9c9742107d1b6c9f419df561b71aa6d", size = 255083, upload-time = "2026-01-09T08:05:02.857Z" }, - { url = "https://files.pythonhosted.org/packages/5d/07/99e2342f976c3700e142eddc01524e375a9e9078869a6885d9c72f3a3659/zope_interface-8.2-cp310-cp310-win_amd64.whl", hash = "sha256:3bf73a910bb27344def2d301a03329c559a79b308e1e584686b74171d736be4e", size = 211924, upload-time = "2026-01-09T08:05:04.702Z" }, - { url = "https://files.pythonhosted.org/packages/98/97/9c2aa8caae79915ed64eb114e18816f178984c917aa9adf2a18345e4f2e5/zope_interface-8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c65ade7ea85516e428651048489f5e689e695c79188761de8c622594d1e13322", size = 208081, upload-time = "2026-01-09T08:05:06.623Z" }, - { url = "https://files.pythonhosted.org/packages/34/86/4e2fcb01a8f6780ac84923748e450af0805531f47c0956b83065c99ab543/zope_interface-8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1ef4b43659e1348f35f38e7d1a6bbc1682efde239761f335ffc7e31e798b65b", size = 208522, upload-time = "2026-01-09T08:05:07.986Z" }, - { url = "https://files.pythonhosted.org/packages/f6/eb/08e277da32ddcd4014922854096cf6dcb7081fad415892c2da1bedefbf02/zope_interface-8.2-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:dfc4f44e8de2ff4eba20af4f0a3ca42d3c43ab24a08e49ccd8558b7a4185b466", size = 255198, upload-time = "2026-01-09T08:05:09.532Z" }, - { url = "https://files.pythonhosted.org/packages/ea/a1/b32484f3281a5dc83bc713ad61eca52c543735cdf204543172087a074a74/zope_interface-8.2-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8f094bfb49179ec5dc9981cb769af1275702bd64720ef94874d9e34da1390d4c", size = 259970, upload-time = "2026-01-09T08:05:11.477Z" }, - { url = "https://files.pythonhosted.org/packages/f6/81/bca0e8ae1e487d4093a8a7cfed2118aa2d4758c8cfd66e59d2af09d71f1c/zope_interface-8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d2bb8e7364e18f083bf6744ccf30433b2a5f236c39c95df8514e3c13007098ce", size = 261153, upload-time = "2026-01-09T08:05:13.402Z" }, - { url = "https://files.pythonhosted.org/packages/40/1e/e3ff2a708011e56b10b271b038d4cb650a8ad5b7d24352fe2edf6d6b187a/zope_interface-8.2-cp311-cp311-win_amd64.whl", hash = "sha256:6f4b4dfcfdfaa9177a600bb31cebf711fdb8c8e9ed84f14c61c420c6aa398489", size = 212330, upload-time = "2026-01-09T08:05:15.267Z" }, - { url = "https://files.pythonhosted.org/packages/e0/a0/1e1fabbd2e9c53ef92b69df6d14f4adc94ec25583b1380336905dc37e9a0/zope_interface-8.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:624b6787fc7c3e45fa401984f6add2c736b70a7506518c3b537ffaacc4b29d4c", size = 208785, upload-time = "2026-01-09T08:05:17.348Z" }, - { url = "https://files.pythonhosted.org/packages/c3/2a/88d098a06975c722a192ef1fb7d623d1b57c6a6997cf01a7aabb45ab1970/zope_interface-8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc9ded9e97a0ed17731d479596ed1071e53b18e6fdb2fc33af1e43f5fd2d3aaa", size = 208976, upload-time = "2026-01-09T08:05:18.792Z" }, - { url = "https://files.pythonhosted.org/packages/e9/e8/757398549fdfd2f8c89f32c82ae4d2f0537ae2a5d2f21f4a2f711f5a059f/zope_interface-8.2-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:532367553e4420c80c0fc0cabcc2c74080d495573706f66723edee6eae53361d", size = 259411, upload-time = "2026-01-09T08:05:20.567Z" }, - { url = "https://files.pythonhosted.org/packages/91/af/502601f0395ce84dff622f63cab47488657a04d0065547df42bee3a680ff/zope_interface-8.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2bf9cf275468bafa3c72688aad8cfcbe3d28ee792baf0b228a1b2d93bd1d541a", size = 264859, upload-time = "2026-01-09T08:05:22.234Z" }, - { url = "https://files.pythonhosted.org/packages/89/0c/d2f765b9b4814a368a7c1b0ac23b68823c6789a732112668072fe596945d/zope_interface-8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0009d2d3c02ea783045d7804da4fd016245e5c5de31a86cebba66dd6914d59a2", size = 264398, upload-time = "2026-01-09T08:05:23.853Z" }, - { url = "https://files.pythonhosted.org/packages/4a/81/2f171fbc4222066957e6b9220c4fb9146792540102c37e6d94e5d14aad97/zope_interface-8.2-cp312-cp312-win_amd64.whl", hash = "sha256:845d14e580220ae4544bd4d7eb800f0b6034fe5585fc2536806e0a26c2ee6640", size = 212444, upload-time = "2026-01-09T08:05:25.148Z" }, - { url = "https://files.pythonhosted.org/packages/66/47/45188fb101fa060b20e6090e500682398ab415e516a0c228fbb22bc7def2/zope_interface-8.2-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:6068322004a0158c80dfd4708dfb103a899635408c67c3b10e9acec4dbacefec", size = 209170, upload-time = "2026-01-09T08:05:26.616Z" }, - { url = "https://files.pythonhosted.org/packages/09/03/f6b9336c03c2b48403c4eb73a1ec961d94dc2fb5354c583dfb5fa05fd41f/zope_interface-8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2499de92e8275d0dd68f84425b3e19e9268cd1fa8507997900fa4175f157733c", size = 209229, upload-time = "2026-01-09T08:05:28.521Z" }, - { url = "https://files.pythonhosted.org/packages/07/b1/65fe1dca708569f302ade02e6cdca309eab6752bc9f80105514f5b708651/zope_interface-8.2-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f777e68c76208503609c83ca021a6864902b646530a1a39abb9ed310d1100664", size = 259393, upload-time = "2026-01-09T08:05:29.897Z" }, - { url = "https://files.pythonhosted.org/packages/eb/a5/97b49cfceb6ed53d3dcfb3f3ebf24d83b5553194f0337fbbb3a9fec6cf78/zope_interface-8.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b05a919fdb0ed6ea942e5a7800e09a8b6cdae6f98fee1bef1c9d1a3fc43aaa0", size = 264863, upload-time = "2026-01-09T08:05:31.501Z" }, - { url = "https://files.pythonhosted.org/packages/cb/02/0b7a77292810efe3a0586a505b077ebafd5114e10c6e6e659f0c8e387e1f/zope_interface-8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ccc62b5712dd7bd64cfba3ee63089fb11e840f5914b990033beeae3b2180b6cb", size = 264369, upload-time = "2026-01-09T08:05:32.941Z" }, - { url = "https://files.pythonhosted.org/packages/fb/1d/0d1ff3846302ed1b5bbf659316d8084b30106770a5f346b7ff4e9f540f80/zope_interface-8.2-cp313-cp313-win_amd64.whl", hash = "sha256:34f877d1d3bb7565c494ed93828fa6417641ca26faf6e8f044e0d0d500807028", size = 212447, upload-time = "2026-01-09T08:05:35.064Z" }, - { url = "https://files.pythonhosted.org/packages/1a/da/3c89de3917751446728b8898b4d53318bc2f8f6bf8196e150a063c59905e/zope_interface-8.2-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:46c7e4e8cbc698398a67e56ca985d19cb92365b4aafbeb6a712e8c101090f4cb", size = 209223, upload-time = "2026-01-09T08:05:36.449Z" }, - { url = "https://files.pythonhosted.org/packages/00/7f/62d00ec53f0a6e5df0c984781e6f3999ed265129c4c3413df8128d1e0207/zope_interface-8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a87fc7517f825a97ff4a4ca4c8a950593c59e0f8e7bfe1b6f898a38d5ba9f9cf", size = 209366, upload-time = "2026-01-09T08:05:38.197Z" }, - { url = "https://files.pythonhosted.org/packages/ef/a2/f241986315174be8e00aabecfc2153cf8029c1327cab8ed53a9d979d7e08/zope_interface-8.2-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:ccf52f7d44d669203c2096c1a0c2c15d52e36b2e7a9413df50f48392c7d4d080", size = 261037, upload-time = "2026-01-09T08:05:39.568Z" }, - { url = "https://files.pythonhosted.org/packages/02/cc/b321c51d6936ede296a1b8860cf173bee2928357fe1fff7f97234899173f/zope_interface-8.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:aae807efc7bd26302eb2fea05cd6de7d59269ed6ae23a6de1ee47add6de99b8c", size = 264219, upload-time = "2026-01-09T08:05:41.624Z" }, - { url = "https://files.pythonhosted.org/packages/ab/fb/5f5e7b40a2f4efd873fe173624795ca47eaa22e29051270c981361b45209/zope_interface-8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:05a0e42d6d830f547e114de2e7cd15750dc6c0c78f8138e6c5035e51ddfff37c", size = 264390, upload-time = "2026-01-09T08:05:42.936Z" }, - { url = "https://files.pythonhosted.org/packages/f9/82/3f2bc594370bc3abd58e5f9085d263bf682a222f059ed46275cde0570810/zope_interface-8.2-cp314-cp314-win_amd64.whl", hash = "sha256:561ce42390bee90bae51cf1c012902a8033b2aaefbd0deed81e877562a116d48", size = 212585, upload-time = "2026-01-09T08:05:44.419Z" }, +version = "8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/04/0b1d92e7d31507c5fbe203d9cc1ae80fb0645688c7af751ea0ec18c2223e/zope_interface-8.3.tar.gz", hash = "sha256:e1a9de7d0b5b5c249a73b91aebf4598ce05e334303af6aa94865893283e9ff10", size = 256822, upload-time = "2026-04-10T06:12:35.036Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/47/791e8da00c00332d4db7f9add22cb102c523e452ea0449bb63eb7dcc3c17/zope_interface-8.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a2f9c4ee0f2ad4817e9481684993d33b66d9b815f9157a716a189af483bc34", size = 210367, upload-time = "2026-04-10T06:21:50.304Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d5/92bad86cb429af22f59f6e08227c58c74a3d8395a64a5ca61b9301fc6171/zope_interface-8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99c84e12efe0e17f03c6bb5a8ea18fb2841e6666ee0b8331d5967fec84337884", size = 210726, upload-time = "2026-04-10T06:21:52.375Z" }, + { url = "https://files.pythonhosted.org/packages/cb/55/ddf1aeb3e4d5f7a343599a76dafc0766ec42b32112bfedc37f7ddeff753f/zope_interface-8.3-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:a918f8e73c35a1352a4b49db67b90b37d33fb7651c834def3f0e3784437bb3a8", size = 254046, upload-time = "2026-04-10T06:21:54.332Z" }, + { url = "https://files.pythonhosted.org/packages/b6/4f/a52a78b389c79d85d3d4afbf71b2984bd4a8a682beec248cdc21576b13a6/zope_interface-8.3-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5a5b50d0dcdb4200f1936f75b6688bd86de5c14c5d20bed2e004300a04521826", size = 258910, upload-time = "2026-04-10T06:21:56.588Z" }, + { url = "https://files.pythonhosted.org/packages/08/34/2841cb5c1dea43a1e3893deb0ed412d4eeb16f4a3eb4daf2465d24b71069/zope_interface-8.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:731eaf0a0f2a683315a2dfc2953ef831ae51e062b87cff6220e0e5102a83b612", size = 259521, upload-time = "2026-04-10T06:21:58.505Z" }, + { url = "https://files.pythonhosted.org/packages/23/ff/66ba0f3aba2d3724e425fdb99122d6f7927a37d623492a606477094a6891/zope_interface-8.3-cp310-cp310-win_amd64.whl", hash = "sha256:5e9861493457268f923d8aae4052383922162c3d56094c4e3a9ff83173d64be3", size = 214205, upload-time = "2026-04-10T06:22:00.611Z" }, + { url = "https://files.pythonhosted.org/packages/0d/99/cee01c7e8be6c5889f2c74914196decd91170011f420c9912792336f284c/zope_interface-8.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e8964f1a13b07c8770eab88b7a6cd0870c3e36442e4ef4937f36fd0b6d1cea2c", size = 210875, upload-time = "2026-04-10T06:22:02.746Z" }, + { url = "https://files.pythonhosted.org/packages/e2/f1/cf7a49b36385ed1ee0cc7f6b8861904f1533a3286e01cd1e3c2eb72976b9/zope_interface-8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ec2728e3cf685126ccd2e0f7635fb60edf116f76f402dd66f4df13d9d9348b4b", size = 211199, upload-time = "2026-04-10T06:22:04.596Z" }, + { url = "https://files.pythonhosted.org/packages/cc/86/1ccb73ce9189b1345b7824830a18796ae0b33317d3725d8a034a6ce06501/zope_interface-8.3-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:568b97cb701fd2830b52198a2885e851317a019e1912eaad107860e3cca71964", size = 259885, upload-time = "2026-04-10T06:22:06.403Z" }, + { url = "https://files.pythonhosted.org/packages/a1/de/d0185211ad4902641c0233b7c3b42e21582ffac24f5afe5cc4736b196346/zope_interface-8.3-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62839e4201869a29f99742df7f7139cac4ce301850d3787da37f84e271ad9b95", size = 264308, upload-time = "2026-04-10T06:22:08.425Z" }, + { url = "https://files.pythonhosted.org/packages/0e/e5/ac6f24cdaa04711246d425a2ca301e2f3c97e8d6d672b44258eb2ceb92ff/zope_interface-8.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d287183767926bc9841e51471a28b77c7b49fddf65016aa7faf5a1447e2b6558", size = 265594, upload-time = "2026-04-10T06:22:10.111Z" }, + { url = "https://files.pythonhosted.org/packages/b3/ca/e888c67123b6a7019936c67b5ebcc9396fdb3067cf278d7541d24f4c1a86/zope_interface-8.3-cp311-cp311-win_amd64.whl", hash = "sha256:12a33bb596ca20520e44f97918950cfc66a632ac0278a7f40608217cc4269948", size = 214562, upload-time = "2026-04-10T06:22:12.681Z" }, + { url = "https://files.pythonhosted.org/packages/16/1e/7ed593f9c3664e560febe1f132fdf73b8bb9a3de6e3448093b0167239c8c/zope_interface-8.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b361b7ce566bc024e55f74eb1e88afc14039d7bd8ea13eeff3b7a8400dc59683", size = 211571, upload-time = "2026-04-10T06:22:14.775Z" }, + { url = "https://files.pythonhosted.org/packages/cf/31/844979b472f30efd2a68480738c9a3be518786b0885137075616607e88c7/zope_interface-8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5be73ca1304daa3046ee5835f7fa6b3badadf02102b570532dd57cd25dd72d6", size = 211748, upload-time = "2026-04-10T06:22:16.695Z" }, + { url = "https://files.pythonhosted.org/packages/6e/b6/71f5c9d8dde7334e1b67306fea5814c67eac92d871bb0dfc664c9f3355f1/zope_interface-8.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:961af756797e36c1e77f7d0dc8ac1322de0c071eaa1a641dbe3b790061968dd9", size = 264718, upload-time = "2026-04-10T06:22:19.473Z" }, + { url = "https://files.pythonhosted.org/packages/94/e3/5eab77fd6795ca37b9ed1aeea5290170018938549322003745bdcd939238/zope_interface-8.3-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6329f296b70f62043bf2df06eb91b4be040baee32ec4a3e0314f3893fa5c51c", size = 269795, upload-time = "2026-04-10T06:22:21.728Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2f/4bc8807d65833f06335a49beb1786bafcf748cde7472ba14cdb4db463ba8/zope_interface-8.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f420f6c96307ff265981c510782f0ed97475107b78ca9fca0bb04fe36f363eb4", size = 269418, upload-time = "2026-04-10T06:22:23.802Z" }, + { url = "https://files.pythonhosted.org/packages/50/3d/1cfaf770bc6bc64edec3d4c5f17b5dbe600bf93cd2caac5ee0880eb9f9e0/zope_interface-8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ffeae9102aa6ba5bd2f9a547016347bd87c9cf01aea564936c0d165fff0b1242", size = 214390, upload-time = "2026-04-10T06:22:25.735Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/ff205c5463e52ad64cc40be667fdff2b01b9754a385c6b95bac01645fa4f/zope_interface-8.3-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:1aa0e1d72212cedc38b2156bbca08cf24625c057135a7947ef6b19bc732b2772", size = 211889, upload-time = "2026-04-10T06:22:27.612Z" }, + { url = "https://files.pythonhosted.org/packages/c7/21/0cc848e22769b1cf4c0cd636ec2e60ea05cfb958423435ea526d5a291fe8/zope_interface-8.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54ab83218a8f6947ba4b6cb1a121f1e1abe2e418b838ccdac71639d0f97e734e", size = 211961, upload-time = "2026-04-10T06:22:29.575Z" }, + { url = "https://files.pythonhosted.org/packages/e3/54/815c9dbb90336c50694b4c7ef7ced06bc389e5597200c77457b557a0221c/zope_interface-8.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:34d6c10fa790005487c471e0e4ab537b0fa9a70e55a96994e51ffeef92205fa4", size = 264409, upload-time = "2026-04-10T06:22:31.426Z" }, + { url = "https://files.pythonhosted.org/packages/3a/69/2e5c30adde0e94552d934971fa6eba107449d3d11fa086cfcfeb8ea6354d/zope_interface-8.3-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:93108d5f8dee20177a637438bf4df4c6faf8a317c9d4a8b1d5e78123854e3317", size = 269592, upload-time = "2026-04-10T06:22:33.393Z" }, + { url = "https://files.pythonhosted.org/packages/23/8a/fbb1dceb5c5400b2b27934aa102d29fe4cb06732122e7f409efebeb6e097/zope_interface-8.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f81d90f80b9fbf36602549e2f187861c9d7139837f8c9dd685ce3b933c6360f", size = 269548, upload-time = "2026-04-10T06:22:35.339Z" }, + { url = "https://files.pythonhosted.org/packages/a2/70/abd0bb9cc9b1a9a718f30c81f46a184a2e751dd80cf57db142ffa42730da/zope_interface-8.3-cp313-cp313-win_amd64.whl", hash = "sha256:96106a5f609bb355e1aec6ab0361213c8af0843ca1e1ba9c42eacfbd0910914e", size = 214391, upload-time = "2026-04-10T06:22:36.969Z" }, + { url = "https://files.pythonhosted.org/packages/8a/d9/95fe0d4d8da09042383c42f239e0106f1019ec86a27ed9f5000e754f6e7a/zope_interface-8.3-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:96f0001b49227d756770fc70ecde49f19332ae98ec98e1bbbf2fd7a87e9d4e45", size = 211979, upload-time = "2026-04-10T06:22:38.628Z" }, + { url = "https://files.pythonhosted.org/packages/f3/01/b6f694444ea1c911a4ea915f4ef066a95e9d1a58256a30c131ec88c3ae64/zope_interface-8.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3853bfb808084e1b4a3a769b00bd8b58a52b0c4a4fc5c23de26d283cd8beb627", size = 212038, upload-time = "2026-04-10T06:22:40.475Z" }, + { url = "https://files.pythonhosted.org/packages/f7/cf/237de1fba4f05686bc344eeb035236bd89890679c8211f129f05b5971ccf/zope_interface-8.3-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:33a13acba79ef693fb64ceb6193ece913d39586f184797f133c1bc549da86851", size = 266041, upload-time = "2026-04-10T06:22:42.093Z" }, + { url = "https://files.pythonhosted.org/packages/58/5f/df85b1ff5626d7f05231e69b7efd38bdc2c82ca363495e0bb112aaf655b3/zope_interface-8.3-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e9f7e4b46741a11a9e1fab8b68710f08dec700e9f1b877cdca02480fbebe4846", size = 269094, upload-time = "2026-04-10T06:22:43.832Z" }, + { url = "https://files.pythonhosted.org/packages/5f/10/7ad1ff9c514fe38b176fc1271967c453074eb386a4515bd3b957c485f3a8/zope_interface-8.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ce49d43366e12aeccd14fcaebb3ef110f50f5795e0d4a95383ea057365cedf2", size = 269413, upload-time = "2026-04-10T06:22:45.573Z" }, + { url = "https://files.pythonhosted.org/packages/38/42/3b0b5edee7801e0dd5c42c2c9bb4ec8bec430a6628462eb1315db76a7954/zope_interface-8.3-cp314-cp314-win_amd64.whl", hash = "sha256:301db4049c79a15a3b29d89795e150daf0e9ae701404b112ad6585ea863f6ef5", size = 215170, upload-time = "2026-04-10T06:22:47.115Z" }, ] [[package]] From 6d17303facfec004115426350e1b2f4516a6fd51 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:09:21 +0200 Subject: [PATCH 094/100] [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65165) * Move release calendar verification to its own scheduled workflow Run dev/verify_release_calendar.py from a dedicated daily scheduled workflow instead of as a canary job in the main CI pipeline, and notify the #release-management Slack channel when the check fails so the issue is surfaced to release managers directly. * Include wiki and calendar links in release calendar Slack alert (cherry picked from commit 048e9a191b4a6625bb4bbad23fad537b256f4062) Co-authored-by: Jarek Potiuk --- .github/workflows/ci-amd-arm.yml | 17 ----- .../scheduled-verify-release-calendar.yml | 72 +++++++++++++++++++ 2 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/scheduled-verify-release-calendar.yml diff --git a/.github/workflows/ci-amd-arm.yml b/.github/workflows/ci-amd-arm.yml index 0dc738ad3da48..160293a4784dc 100644 --- a/.github/workflows/ci-amd-arm.yml +++ b/.github/workflows/ci-amd-arm.yml @@ -213,23 +213,6 @@ jobs: platform: ${{ needs.build-info.outputs.platform }} shared-distributions-as-json: ${{needs.build-info.outputs.shared-distributions-as-json}} - verify-release-calendar: - name: "Verify release calendar" - runs-on: ${{ fromJSON(needs.build-info.outputs.runner-type) }} - needs: [build-info] - # Only run on canary builds (push to main, scheduled runs, or manual dispatch) - if: needs.build-info.outputs.canary-run == 'true' - timeout-minutes: 10 - steps: - - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - name: "Install uv" - run: pip install "uv==${UV_VERSION}" - - name: "Verify release calendar" - run: uv run dev/verify_release_calendar.py - build-ci-images: name: Build CI images needs: [build-info] diff --git a/.github/workflows/scheduled-verify-release-calendar.yml b/.github/workflows/scheduled-verify-release-calendar.yml new file mode 100644 index 0000000000000..75b5b8742dd47 --- /dev/null +++ b/.github/workflows/scheduled-verify-release-calendar.yml @@ -0,0 +1,72 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +--- +name: "Scheduled verify release calendar" +on: # yamllint disable-line rule:truthy + schedule: + # Daily at 06:00 UTC + - cron: '0 6 * * *' + workflow_dispatch: +permissions: + contents: read +env: + UV_VERSION: "0.11.3" # Keep this comment to allow automatic replacement of uv version +jobs: + verify-release-calendar: + name: "Verify release calendar" + runs-on: ["ubuntu-22.04"] + timeout-minutes: 10 + steps: + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: "Install uv" + run: pip install "uv==${UV_VERSION}" + - name: "Verify release calendar" + run: uv run dev/verify_release_calendar.py + # yamllint disable rule:line-length + - name: "Notify Slack on failure" + if: failure() + uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + channel: "release-management" + text: >- + :warning: Release calendar verification failed. + See: + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + blocks: + - type: section + text: + type: mrkdwn + text: >- + :warning: *Release calendar verification failed* + + The scheduled `verify_release_calendar.py` check + failed. Please review and fix the mismatch between + the Confluence release wiki and the Google + Calendar entries. + + • + + • + + • <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View failed run> From 234a3186f295520ff5835ccd1e320c1c1e390422 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:09:30 +0200 Subject: [PATCH 095/100] [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160) Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script). Updates `actions/github-script` from 8.0.0 to 9.0.0 - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/ed597411d8f924073f98dfc5c65a23a2325f34cd...3a2844b7e9c422d3c10d287c895573f7108da1b3) (cherry picked from commit e5a047ca8d23614cefeaad89e08eb1e3b0482e60) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: 9.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-updates ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 01a25b47dfc3eb21a91ed51fdf0a7679b642a869 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Tue, 14 Apr 2026 20:10:19 +0200 Subject: [PATCH 096/100] [v3-2-test] Add exclude-newer-package=false for all workspace components in uv config (#64859) (#65238) This ensures that workspace packages (local packages in the monorepo) are not subject to the exclude-newer time-based restriction, which could cause resolution issues when installing pre-release or locally-built packages. Also removes the redundant --exclude-newer flag from install_airflow_and_providers.py since the pyproject.toml now handles this globally, and mounts pyproject.toml in remove-sources docker-compose to make uv config available. (cherry picked from commit cacc2eb8dcac7e0343f26685e00f3d5700899a69) --- pyproject.toml | 272 +++++++++++++++++- scripts/ci/docker-compose/remove-sources.yml | 6 +- .../ci/prek/update_airflow_pyproject_toml.py | 40 +++ .../install_airflow_and_providers.py | 5 +- uv.lock | 136 ++++++++- 5 files changed, 447 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fa61502104363..15940303483bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1343,11 +1343,277 @@ leveldb = [ ] [tool.uv] -required-version = ">=0.6.3" +required-version = ">=0.9.17" +no-build-isolation-package = ["sphinx-redoc"] # Synchroonize with scripts/ci/prek/upgrade_important_versions.py exclude-newer = "4 days" -no-build-isolation-package = ["sphinx-redoc"] -constraint-dependencies = ["lxml==6.0.2"] # Remove after https://github.com/aws/amazon-redshift-python-driver/pull/272 + +[tool.uv.exclude-newer-package] +# Automatically generated exclude-newer-package entries (update_airflow_pyproject_toml.py) +apache-airflow = false +apache-airflow-breeze = false +apache-airflow-core = false +apache-airflow-ctl = false +apache-airflow-ctl-tests = false +apache-airflow-dev = false +apache-airflow-devel-common = false +apache-airflow-docker-tests = false +apache-airflow-e2e-tests = false +apache-airflow-helm-tests = false +apache-airflow-kubernetes-tests = false +apache-airflow-providers = false +apache-airflow-providers-airbyte = false +apache-airflow-providers-alibaba = false +apache-airflow-providers-amazon = false +apache-airflow-providers-apache-cassandra = false +apache-airflow-providers-apache-drill = false +apache-airflow-providers-apache-druid = false +apache-airflow-providers-apache-flink = false +apache-airflow-providers-apache-hdfs = false +apache-airflow-providers-apache-hive = false +apache-airflow-providers-apache-iceberg = false +apache-airflow-providers-apache-impala = false +apache-airflow-providers-apache-kafka = false +apache-airflow-providers-apache-kylin = false +apache-airflow-providers-apache-livy = false +apache-airflow-providers-apache-pig = false +apache-airflow-providers-apache-pinot = false +apache-airflow-providers-apache-spark = false +apache-airflow-providers-apache-tinkerpop = false +apache-airflow-providers-apprise = false +apache-airflow-providers-arangodb = false +apache-airflow-providers-asana = false +apache-airflow-providers-atlassian-jira = false +apache-airflow-providers-celery = false +apache-airflow-providers-cloudant = false +apache-airflow-providers-cncf-kubernetes = false +apache-airflow-providers-cohere = false +apache-airflow-providers-common-ai = false +apache-airflow-providers-common-compat = false +apache-airflow-providers-common-io = false +apache-airflow-providers-common-messaging = false +apache-airflow-providers-common-sql = false +apache-airflow-providers-databricks = false +apache-airflow-providers-datadog = false +apache-airflow-providers-dbt-cloud = false +apache-airflow-providers-dingding = false +apache-airflow-providers-discord = false +apache-airflow-providers-docker = false +apache-airflow-providers-edge3 = false +apache-airflow-providers-elasticsearch = false +apache-airflow-providers-exasol = false +apache-airflow-providers-fab = false +apache-airflow-providers-facebook = false +apache-airflow-providers-ftp = false +apache-airflow-providers-git = false +apache-airflow-providers-github = false +apache-airflow-providers-google = false +apache-airflow-providers-grpc = false +apache-airflow-providers-hashicorp = false +apache-airflow-providers-http = false +apache-airflow-providers-imap = false +apache-airflow-providers-influxdb = false +apache-airflow-providers-informatica = false +apache-airflow-providers-jdbc = false +apache-airflow-providers-jenkins = false +apache-airflow-providers-keycloak = false +apache-airflow-providers-microsoft-azure = false +apache-airflow-providers-microsoft-mssql = false +apache-airflow-providers-microsoft-psrp = false +apache-airflow-providers-microsoft-winrm = false +apache-airflow-providers-mongo = false +apache-airflow-providers-mysql = false +apache-airflow-providers-neo4j = false +apache-airflow-providers-odbc = false +apache-airflow-providers-openai = false +apache-airflow-providers-openfaas = false +apache-airflow-providers-openlineage = false +apache-airflow-providers-opensearch = false +apache-airflow-providers-opsgenie = false +apache-airflow-providers-oracle = false +apache-airflow-providers-pagerduty = false +apache-airflow-providers-papermill = false +apache-airflow-providers-pgvector = false +apache-airflow-providers-pinecone = false +apache-airflow-providers-postgres = false +apache-airflow-providers-presto = false +apache-airflow-providers-qdrant = false +apache-airflow-providers-redis = false +apache-airflow-providers-salesforce = false +apache-airflow-providers-samba = false +apache-airflow-providers-segment = false +apache-airflow-providers-sendgrid = false +apache-airflow-providers-sftp = false +apache-airflow-providers-singularity = false +apache-airflow-providers-slack = false +apache-airflow-providers-smtp = false +apache-airflow-providers-snowflake = false +apache-airflow-providers-sqlite = false +apache-airflow-providers-ssh = false +apache-airflow-providers-standard = false +apache-airflow-providers-tableau = false +apache-airflow-providers-telegram = false +apache-airflow-providers-teradata = false +apache-airflow-providers-trino = false +apache-airflow-providers-vertica = false +apache-airflow-providers-weaviate = false +apache-airflow-providers-yandex = false +apache-airflow-providers-ydb = false +apache-airflow-providers-zendesk = false +apache-airflow-scripts = false +apache-airflow-shared-configuration = false +apache-airflow-shared-dagnode = false +apache-airflow-shared-listeners = false +apache-airflow-shared-logging = false +apache-airflow-shared-module-loading = false +apache-airflow-shared-observability = false +apache-airflow-shared-plugins-manager = false +apache-airflow-shared-providers-discovery = false +apache-airflow-shared-secrets-backend = false +apache-airflow-shared-secrets-masker = false +apache-airflow-shared-serialization = false +apache-airflow-shared-template-rendering = false +apache-airflow-shared-timezones = false +apache-airflow-task-sdk = false +apache-airflow-task-sdk-integration-tests = false +apache-aurflow-docker-stack = false +# End of automatically generated exclude-newer-package entries + +[tool.uv.pip] +# Synchroonize with scripts/ci/prek/upgrade_important_versions.py +exclude-newer = "4 days" + +[tool.uv.pip.exclude-newer-package] +# Automatically generated exclude-newer-package-pip entries (update_airflow_pyproject_toml.py) +apache-airflow = false +apache-airflow-breeze = false +apache-airflow-core = false +apache-airflow-ctl = false +apache-airflow-ctl-tests = false +apache-airflow-dev = false +apache-airflow-devel-common = false +apache-airflow-docker-tests = false +apache-airflow-e2e-tests = false +apache-airflow-helm-tests = false +apache-airflow-kubernetes-tests = false +apache-airflow-providers = false +apache-airflow-providers-airbyte = false +apache-airflow-providers-alibaba = false +apache-airflow-providers-amazon = false +apache-airflow-providers-apache-cassandra = false +apache-airflow-providers-apache-drill = false +apache-airflow-providers-apache-druid = false +apache-airflow-providers-apache-flink = false +apache-airflow-providers-apache-hdfs = false +apache-airflow-providers-apache-hive = false +apache-airflow-providers-apache-iceberg = false +apache-airflow-providers-apache-impala = false +apache-airflow-providers-apache-kafka = false +apache-airflow-providers-apache-kylin = false +apache-airflow-providers-apache-livy = false +apache-airflow-providers-apache-pig = false +apache-airflow-providers-apache-pinot = false +apache-airflow-providers-apache-spark = false +apache-airflow-providers-apache-tinkerpop = false +apache-airflow-providers-apprise = false +apache-airflow-providers-arangodb = false +apache-airflow-providers-asana = false +apache-airflow-providers-atlassian-jira = false +apache-airflow-providers-celery = false +apache-airflow-providers-cloudant = false +apache-airflow-providers-cncf-kubernetes = false +apache-airflow-providers-cohere = false +apache-airflow-providers-common-ai = false +apache-airflow-providers-common-compat = false +apache-airflow-providers-common-io = false +apache-airflow-providers-common-messaging = false +apache-airflow-providers-common-sql = false +apache-airflow-providers-databricks = false +apache-airflow-providers-datadog = false +apache-airflow-providers-dbt-cloud = false +apache-airflow-providers-dingding = false +apache-airflow-providers-discord = false +apache-airflow-providers-docker = false +apache-airflow-providers-edge3 = false +apache-airflow-providers-elasticsearch = false +apache-airflow-providers-exasol = false +apache-airflow-providers-fab = false +apache-airflow-providers-facebook = false +apache-airflow-providers-ftp = false +apache-airflow-providers-git = false +apache-airflow-providers-github = false +apache-airflow-providers-google = false +apache-airflow-providers-grpc = false +apache-airflow-providers-hashicorp = false +apache-airflow-providers-http = false +apache-airflow-providers-imap = false +apache-airflow-providers-influxdb = false +apache-airflow-providers-informatica = false +apache-airflow-providers-jdbc = false +apache-airflow-providers-jenkins = false +apache-airflow-providers-keycloak = false +apache-airflow-providers-microsoft-azure = false +apache-airflow-providers-microsoft-mssql = false +apache-airflow-providers-microsoft-psrp = false +apache-airflow-providers-microsoft-winrm = false +apache-airflow-providers-mongo = false +apache-airflow-providers-mysql = false +apache-airflow-providers-neo4j = false +apache-airflow-providers-odbc = false +apache-airflow-providers-openai = false +apache-airflow-providers-openfaas = false +apache-airflow-providers-openlineage = false +apache-airflow-providers-opensearch = false +apache-airflow-providers-opsgenie = false +apache-airflow-providers-oracle = false +apache-airflow-providers-pagerduty = false +apache-airflow-providers-papermill = false +apache-airflow-providers-pgvector = false +apache-airflow-providers-pinecone = false +apache-airflow-providers-postgres = false +apache-airflow-providers-presto = false +apache-airflow-providers-qdrant = false +apache-airflow-providers-redis = false +apache-airflow-providers-salesforce = false +apache-airflow-providers-samba = false +apache-airflow-providers-segment = false +apache-airflow-providers-sendgrid = false +apache-airflow-providers-sftp = false +apache-airflow-providers-singularity = false +apache-airflow-providers-slack = false +apache-airflow-providers-smtp = false +apache-airflow-providers-snowflake = false +apache-airflow-providers-sqlite = false +apache-airflow-providers-ssh = false +apache-airflow-providers-standard = false +apache-airflow-providers-tableau = false +apache-airflow-providers-telegram = false +apache-airflow-providers-teradata = false +apache-airflow-providers-trino = false +apache-airflow-providers-vertica = false +apache-airflow-providers-weaviate = false +apache-airflow-providers-yandex = false +apache-airflow-providers-ydb = false +apache-airflow-providers-zendesk = false +apache-airflow-scripts = false +apache-airflow-shared-configuration = false +apache-airflow-shared-dagnode = false +apache-airflow-shared-listeners = false +apache-airflow-shared-logging = false +apache-airflow-shared-module-loading = false +apache-airflow-shared-observability = false +apache-airflow-shared-plugins-manager = false +apache-airflow-shared-providers-discovery = false +apache-airflow-shared-secrets-backend = false +apache-airflow-shared-secrets-masker = false +apache-airflow-shared-serialization = false +apache-airflow-shared-template-rendering = false +apache-airflow-shared-timezones = false +apache-airflow-task-sdk = false +apache-airflow-task-sdk-integration-tests = false +apache-aurflow-docker-stack = false +# End of automatically generated exclude-newer-package-pip entries + [tool.uv.sources] # These names must match the names as defined in the pyproject.toml of the workspace items, diff --git a/scripts/ci/docker-compose/remove-sources.yml b/scripts/ci/docker-compose/remove-sources.yml index bd08c89116b23..a4287f26e46d3 100644 --- a/scripts/ci/docker-compose/remove-sources.yml +++ b/scripts/ci/docker-compose/remove-sources.yml @@ -126,8 +126,10 @@ services: - ../../../empty:/opt/airflow/providers/ydb/src - ../../../empty:/opt/airflow/providers/zendesk/src # END automatically generated volumes by generate-volumes-for-sources prek hook - # However we keep in_container scripts to be able to debug easily the scripts that - # are run with --mount-sources removed flag - such as installing airflow and providers + # However we keep in_container scripts and pyproject.toml to be able to debug easily the scripts that + # are run with --mount-sources removed flag - such as installing airflow and providers or in order to + # get latest uv configuration for all uv sync commands + - ../../../pyproject.toml:/opt/airflow/pyproject.toml - type: bind source: ../../../scripts/in_container target: /opt/airflow/scripts/in_container diff --git a/scripts/ci/prek/update_airflow_pyproject_toml.py b/scripts/ci/prek/update_airflow_pyproject_toml.py index ae65e8cf84bb5..e912f3aee592c 100755 --- a/scripts/ci/prek/update_airflow_pyproject_toml.py +++ b/scripts/ci/prek/update_airflow_pyproject_toml.py @@ -67,8 +67,19 @@ ) END_PROVIDER_WORKSPACE_MEMBERS = " # End of automatically generated provider workspace members" +START_EXCLUDE_NEWER_PACKAGE = ( + "# Automatically generated exclude-newer-package entries (update_airflow_pyproject_toml.py)" +) +END_EXCLUDE_NEWER_PACKAGE = "# End of automatically generated exclude-newer-package entries" + +START_EXCLUDE_NEWER_PACKAGE_PIP = ( + "# Automatically generated exclude-newer-package-pip entries (update_airflow_pyproject_toml.py)" +) +END_EXCLUDE_NEWER_PACKAGE_PIP = "# End of automatically generated exclude-newer-package-pip entries" + CUT_OFF_TIMEDELTA = timedelta(days=6 * 30) + # Temporary override for providers that are not yet included in constraints or when they need # minimum versions for compatibility with Airflow 3 MIN_VERSION_OVERRIDE: dict[str, Version] = { @@ -117,6 +128,15 @@ def _read_toml(path: Path) -> dict[str, Any]: return tomllib.loads(path.read_text()) +def get_all_workspace_component_names() -> list[str]: + """Get all workspace component names from [tool.uv.sources] in pyproject.toml.""" + toml_dict = _read_toml(AIRFLOW_PYPROJECT_TOML_FILE) + sources = toml_dict.get("tool", {}).get("uv", {}).get("sources", {}) + return sorted( + name for name, value in sources.items() if isinstance(value, dict) and value.get("workspace") + ) + + def get_local_provider_version(provider_id: str) -> Version | None: provider_pyproject = PROVIDERS_DIR / provider_path(provider_id) / "pyproject.toml" if not provider_pyproject.exists(): @@ -301,3 +321,23 @@ def get_python_exclusion(provider_dependencies: dict[str, Any]) -> str: False, "provider workspace members", ) + all_workspace_components = get_all_workspace_component_names() + exclude_newer_entries = [] + for component in all_workspace_components: + exclude_newer_entries.append(f"{component} = false\n") + insert_documentation( + AIRFLOW_PYPROJECT_TOML_FILE, + exclude_newer_entries, + START_EXCLUDE_NEWER_PACKAGE, + END_EXCLUDE_NEWER_PACKAGE, + False, + "exclude-newer-package entries", + ) + insert_documentation( + AIRFLOW_PYPROJECT_TOML_FILE, + exclude_newer_entries, + START_EXCLUDE_NEWER_PACKAGE_PIP, + END_EXCLUDE_NEWER_PACKAGE_PIP, + False, + "exclude-newer-package-pip entries", + ) diff --git a/scripts/in_container/install_airflow_and_providers.py b/scripts/in_container/install_airflow_and_providers.py index 3118773721554..80d7fa601cb64 100755 --- a/scripts/in_container/install_airflow_and_providers.py +++ b/scripts/in_container/install_airflow_and_providers.py @@ -23,7 +23,6 @@ import re import shutil import sys -from datetime import datetime from functools import cache from pathlib import Path from typing import NamedTuple @@ -1129,7 +1128,7 @@ def _install_airflow_and_optionally_providers_together( ] if installation_spec.pre_release: console.print("[bright_blue]Allowing pre-release versions of airflow and providers") - base_install_cmd.extend(["--pre", "--exclude-newer", datetime.now().isoformat()]) + base_install_cmd.extend(["--pre"]) if installation_spec.airflow_distribution: console.print( f"\n[bright_blue]Adding airflow distribution to installation: {installation_spec.airflow_distribution} " @@ -1226,7 +1225,7 @@ def _install_only_airflow_airflow_core_task_sdk_with_constraints( ] if installation_spec.pre_release: console.print("[bright_blue]Allowing pre-release versions of airflow and providers") - base_install_airflow_cmd.extend(["--pre", "--exclude-newer", datetime.now().isoformat()]) + base_install_airflow_cmd.extend(["--pre"]) if installation_spec.airflow_distribution: console.print( f"\n[bright_blue]Installing airflow distribution: {installation_spec.airflow_distribution} with constraints" diff --git a/uv.lock b/uv.lock index 092ffc33ec78e..423d269179048 100644 --- a/uv.lock +++ b/uv.lock @@ -12,9 +12,138 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-10T12:24:23.8467168Z" +exclude-newer = "2026-04-02T19:44:45.502210462Z" exclude-newer-span = "P4D" +[options.exclude-newer-package] +apache-airflow-providers-informatica = false +apache-airflow-providers-amazon = false +apache-airflow-providers-elasticsearch = false +apache-airflow-providers-microsoft-winrm = false +apache-airflow-docker-tests = false +apache-airflow-providers = false +apache-airflow-providers-fab = false +apache-airflow-providers-openlineage = false +apache-airflow-providers-sftp = false +apache-airflow-e2e-tests = false +apache-airflow-shared-logging = false +apache-airflow-providers-apache-drill = false +apache-airflow-providers-pgvector = false +apache-airflow-providers-imap = false +apache-airflow-providers-qdrant = false +apache-airflow-providers-edge3 = false +apache-airflow-providers-neo4j = false +apache-airflow-providers-discord = false +apache-airflow-providers-opensearch = false +apache-airflow-providers-samba = false +apache-airflow-providers-arangodb = false +apache-airflow-providers-apache-spark = false +apache-airflow-providers-ftp = false +apache-airflow-helm-tests = false +apache-airflow-providers-jenkins = false +apache-airflow-shared-listeners = false +apache-airflow-providers-telegram = false +apache-airflow-shared-providers-discovery = false +apache-airflow-providers-celery = false +apache-airflow-providers-docker = false +apache-airflow-providers-sendgrid = false +apache-airflow-providers-common-ai = false +apache-airflow = false +apache-airflow-shared-observability = false +apache-airflow-dev = false +apache-airflow-providers-dbt-cloud = false +apache-airflow-providers-openfaas = false +apache-airflow-devel-common = false +apache-airflow-providers-apache-cassandra = false +apache-airflow-providers-asana = false +apache-airflow-providers-oracle = false +apache-airflow-providers-mysql = false +apache-airflow-providers-alibaba = false +apache-airflow-providers-microsoft-mssql = false +apache-airflow-providers-teradata = false +apache-airflow-providers-jdbc = false +apache-airflow-providers-common-io = false +apache-airflow-providers-cohere = false +apache-airflow-providers-pinecone = false +apache-airflow-providers-segment = false +apache-airflow-providers-redis = false +apache-airflow-shared-dagnode = false +apache-airflow-providers-apache-pinot = false +apache-airflow-providers-weaviate = false +apache-airflow-providers-salesforce = false +apache-airflow-providers-ssh = false +apache-airflow-providers-papermill = false +apache-airflow-providers-google = false +apache-airflow-providers-microsoft-psrp = false +apache-airflow-providers-vertica = false +apache-airflow-providers-apache-hdfs = false +apache-airflow-shared-template-rendering = false +apache-airflow-providers-http = false +apache-airflow-providers-slack = false +apache-airflow-providers-databricks = false +apache-airflow-providers-sqlite = false +apache-airflow-shared-module-loading = false +apache-airflow-providers-yandex = false +apache-airflow-shared-serialization = false +apache-airflow-scripts = false +apache-airflow-providers-exasol = false +apache-airflow-providers-mongo = false +apache-airflow-providers-apprise = false +apache-airflow-providers-apache-impala = false +apache-airflow-ctl = false +apache-airflow-providers-zendesk = false +apache-airflow-providers-github = false +apache-airflow-providers-snowflake = false +apache-airflow-providers-presto = false +apache-airflow-providers-airbyte = false +apache-airflow-providers-apache-hive = false +apache-airflow-kubernetes-tests = false +apache-airflow-providers-grpc = false +apache-airflow-providers-apache-druid = false +apache-airflow-providers-cncf-kubernetes = false +apache-airflow-providers-apache-flink = false +apache-airflow-providers-apache-pig = false +apache-airflow-providers-apache-tinkerpop = false +apache-airflow-shared-timezones = false +apache-airflow-providers-apache-iceberg = false +apache-airflow-breeze = false +apache-airflow-providers-opsgenie = false +apache-airflow-providers-apache-livy = false +apache-airflow-core = false +apache-airflow-providers-hashicorp = false +apache-airflow-providers-pagerduty = false +apache-airflow-providers-datadog = false +apache-airflow-providers-apache-kafka = false +apache-airflow-providers-influxdb = false +apache-airflow-providers-keycloak = false +apache-airflow-providers-trino = false +apache-airflow-providers-common-messaging = false +apache-airflow-providers-standard = false +apache-airflow-providers-singularity = false +apache-airflow-providers-common-compat = false +apache-airflow-ctl-tests = false +apache-airflow-providers-tableau = false +apache-airflow-providers-common-sql = false +apache-airflow-shared-configuration = false +apache-airflow-providers-facebook = false +apache-airflow-providers-ydb = false +apache-airflow-providers-microsoft-azure = false +apache-airflow-shared-plugins-manager = false +apache-airflow-shared-secrets-backend = false +apache-airflow-shared-secrets-masker = false +apache-airflow-providers-git = false +apache-airflow-task-sdk = false +apache-airflow-providers-atlassian-jira = false +apache-airflow-providers-odbc = false +apache-airflow-providers-postgres = false +apache-airflow-providers-openai = false +apache-airflow-task-sdk-integration-tests = false +apache-airflow-providers-smtp = false +apache-airflow-providers-dingding = false +apache-airflow-providers-apache-kylin = false +apache-airflow-providers-cloudant = false +apache-aurflow-docker-stack = false + [manifest] members = [ "apache-airflow", @@ -146,7 +275,6 @@ members = [ "apache-airflow-task-sdk-integration-tests", "docker-stack", ] -constraints = [{ name = "lxml", specifier = "==6.0.2" }] [[package]] name = "a2wsgi" @@ -19676,8 +19804,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography" }, - { name = "jeepney" }, + { name = "cryptography", marker = "(python_full_version < '3.14' and sys_platform == 'emscripten') or (python_full_version < '3.14' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, + { name = "jeepney", marker = "(python_full_version < '3.14' and sys_platform == 'emscripten') or (python_full_version < '3.14' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ From 4b2fd04c7f614818d9609a71868796019342c8ee Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Tue, 14 Apr 2026 20:20:55 +0200 Subject: [PATCH 097/100] [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241) * Add breeze generate issue content for airflow-ctl * add new command to doc (cherry picked from commit b24538b0bc3a53d8c666b62e52e023a17d102467) Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com> From b43d7bdac0b14a8c963198f6dc7b779898c6d9de Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Tue, 14 Apr 2026 20:28:34 +0200 Subject: [PATCH 098/100] [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242) * Move release calendar verification to its own scheduled workflow Run dev/verify_release_calendar.py from a dedicated daily scheduled workflow instead of as a canary job in the main CI pipeline, and notify the #release-management Slack channel when the check fails so the issue is surfaced to release managers directly. * Include wiki and calendar links in release calendar Slack alert (cherry picked from commit 048e9a191b4a6625bb4bbad23fad537b256f4062) From f143647e4aa469cb3b1fa4015b16cb8a0db02ae0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 14:07:51 +0000 Subject: [PATCH 099/100] Bump the 3-2-auth-ui-package-updates group across 1 directory with 19 updates Bumps the 3-2-auth-ui-package-updates group with 19 updates in the /airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui directory: | Package | From | To | | --- | --- | --- | | [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) | `0.94.0` | `0.95.0` | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.90.21` | `5.97.0` | | [axios](https://github.com/axios/axios) | `1.13.6` | `1.15.0` | | [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `19.2.4` | `19.2.5` | | [react-cookie](https://github.com/ItsBenCodes/cookies) | `8.0.1` | `8.1.0` | | [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `19.2.4` | `19.2.5` | | [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.71.2` | `7.72.1` | | [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) | `7.13.1` | `7.14.0` | | [@7nohe/openapi-react-query-codegen](https://github.com/7nohe/openapi-react-query-codegen) | `2.0.0` | `2.1.0` | | [@eslint/compat](https://github.com/eslint/rewrite/tree/HEAD/packages/compat) | `2.0.3` | `2.0.5` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.57.0` | `8.58.1` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.57.0` | `8.58.1` | | [@typescript-eslint/utils](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/utils) | `8.57.0` | `8.58.1` | | [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.0` | `4.1.4` | | [eslint](https://github.com/eslint/eslint) | `10.0.3` | `10.2.0` | | [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) | `5.6.0` | `5.8.0` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.57.0` | `8.58.1` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.0.5` | `8.0.8` | | [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.1.0` | `4.1.4` | Updates `@hey-api/openapi-ts` from 0.94.0 to 0.95.0 - [Release notes](https://github.com/hey-api/openapi-ts/releases) - [Changelog](https://github.com/hey-api/openapi-ts/blob/main/CHANGELOG.md) - [Commits](https://github.com/hey-api/openapi-ts/compare/@hey-api/openapi-ts@0.94.0...@hey-api/openapi-ts@0.95.0) Updates `@tanstack/react-query` from 5.90.21 to 5.97.0 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.97.0/packages/react-query) Updates `axios` from 1.13.6 to 1.15.0 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.13.6...v1.15.0) Updates `react` from 19.2.4 to 19.2.5 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.5/packages/react) Updates `react-cookie` from 8.0.1 to 8.1.0 - [Release notes](https://github.com/ItsBenCodes/cookies/releases) - [Commits](https://github.com/ItsBenCodes/cookies/compare/v8.0.1...v8.1.0) Updates `react-dom` from 19.2.4 to 19.2.5 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.5/packages/react-dom) Updates `react-hook-form` from 7.71.2 to 7.72.1 - [Release notes](https://github.com/react-hook-form/react-hook-form/releases) - [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md) - [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.71.2...v7.72.1) Updates `react-router-dom` from 7.13.1 to 7.14.0 - [Release notes](https://github.com/remix-run/react-router/releases) - [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md) - [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.14.0/packages/react-router-dom) Updates `@7nohe/openapi-react-query-codegen` from 2.0.0 to 2.1.0 - [Release notes](https://github.com/7nohe/openapi-react-query-codegen/releases) - [Commits](https://github.com/7nohe/openapi-react-query-codegen/compare/v2.0.0...v2.1.0) Updates `@eslint/compat` from 2.0.3 to 2.0.5 - [Release notes](https://github.com/eslint/rewrite/releases) - [Changelog](https://github.com/eslint/rewrite/blob/main/packages/compat/CHANGELOG.md) - [Commits](https://github.com/eslint/rewrite/commits/compat-v2.0.5/packages/compat) Updates `@typescript-eslint/eslint-plugin` from 8.57.0 to 8.58.1 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.1/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.57.0 to 8.58.1 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.1/packages/parser) Updates `@typescript-eslint/utils` from 8.57.0 to 8.58.1 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/utils/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.1/packages/utils) Updates `@vitest/coverage-v8` from 4.1.0 to 4.1.4 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/coverage-v8) Updates `eslint` from 10.0.3 to 10.2.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v10.0.3...v10.2.0) Updates `eslint-plugin-perfectionist` from 5.6.0 to 5.8.0 - [Release notes](https://github.com/azat-io/eslint-plugin-perfectionist/releases) - [Changelog](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/changelog.md) - [Commits](https://github.com/azat-io/eslint-plugin-perfectionist/compare/v5.6.0...v5.8.0) Updates `typescript-eslint` from 8.57.0 to 8.58.1 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.1/packages/typescript-eslint) Updates `vite` from 8.0.5 to 8.0.8 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.0.8/packages/vite) Updates `vitest` from 4.1.0 to 4.1.4 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/vitest) --- updated-dependencies: - dependency-name: "@hey-api/openapi-ts" dependency-version: 0.95.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: "@tanstack/react-query" dependency-version: 5.97.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: axios dependency-version: 1.15.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: react dependency-version: 19.2.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: 3-2-auth-ui-package-updates - dependency-name: react-cookie dependency-version: 8.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: react-dom dependency-version: 19.2.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: 3-2-auth-ui-package-updates - dependency-name: react-hook-form dependency-version: 7.72.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: react-router-dom dependency-version: 7.14.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: "@7nohe/openapi-react-query-codegen" dependency-version: 2.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: "@eslint/compat" dependency-version: 2.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-2-auth-ui-package-updates - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.58.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: "@typescript-eslint/parser" dependency-version: 8.58.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: "@typescript-eslint/utils" dependency-version: 8.58.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-2-auth-ui-package-updates - dependency-name: eslint dependency-version: 10.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: eslint-plugin-perfectionist dependency-version: 5.8.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: typescript-eslint dependency-version: 8.58.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-2-auth-ui-package-updates - dependency-name: vite dependency-version: 8.0.8 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-2-auth-ui-package-updates - dependency-name: vitest dependency-version: 4.1.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-2-auth-ui-package-updates ... Signed-off-by: dependabot[bot] --- .../auth/managers/simple/ui/package.json | 38 +- .../auth/managers/simple/ui/pnpm-lock.yaml | 1351 ++++++++--------- 2 files changed, 613 insertions(+), 776 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json index 85217c6ad39d1..8baeba595c47e 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json @@ -20,19 +20,19 @@ "dependencies": { "@chakra-ui/react": "^3.34.0", "@hey-api/client-axios": "^0.9.1", - "@hey-api/openapi-ts": "^0.94.0", - "@tanstack/react-query": "^5.90.21", - "axios": "^1.13.6", + "@hey-api/openapi-ts": "^0.95.0", + "@tanstack/react-query": "^5.97.0", + "axios": "^1.15.0", "next-themes": "^0.4.6", - "react": "^19.2.4", - "react-cookie": "^8.0.1", - "react-dom": "^19.2.4", - "react-hook-form": "^7.71.2", - "react-router-dom": "^7.13.1" + "react": "^19.2.5", + "react-cookie": "^8.1.0", + "react-dom": "^19.2.5", + "react-hook-form": "^7.72.1", + "react-router-dom": "^7.14.0" }, "devDependencies": { - "@7nohe/openapi-react-query-codegen": "^2.0.0", - "@eslint/compat": "^2.0.3", + "@7nohe/openapi-react-query-codegen": "^2.1.0", + "@eslint/compat": "^2.0.5", "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", "@testing-library/jest-dom": "^6.9.1", @@ -40,15 +40,15 @@ "@trivago/prettier-plugin-sort-imports": "^6.0.2", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "@typescript-eslint/eslint-plugin": "8.57.0", - "@typescript-eslint/parser": "8.57.0", - "@typescript-eslint/utils": "^8.57.0", + "@typescript-eslint/eslint-plugin": "8.58.1", + "@typescript-eslint/parser": "8.58.1", + "@typescript-eslint/utils": "^8.58.1", "@vitejs/plugin-react-swc": "^4.3.0", - "@vitest/coverage-v8": "^4.1.0", - "eslint": "^10.0.3", + "@vitest/coverage-v8": "^4.1.4", + "eslint": "^10.2.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^5.6.0", + "eslint-plugin-perfectionist": "^5.8.0", "eslint-plugin-prettier": "^5.5.5", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.0.1", @@ -58,10 +58,10 @@ "prettier": "^3.8.1", "ts-morph": "^27.0.2", "typescript": "~5.9.3", - "typescript-eslint": "^8.57.0", - "vite": "^7.3.1", + "typescript-eslint": "^8.58.1", + "vite": "^8.0.8", "vite-plugin-css-injected-by-js": "^4.0.1", - "vitest": "^4.1.0" + "vitest": "^4.1.4" }, "pnpm": { "minimumReleaseAge": 5760, diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml index c0b82ea335ae6..8abf185ca92ef 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml @@ -33,56 +33,56 @@ importers: dependencies: '@chakra-ui/react': specifier: ^3.34.0 - version: 3.34.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 3.34.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@hey-api/client-axios': specifier: ^0.9.1 - version: 0.9.1(@hey-api/openapi-ts@0.94.0(magicast@0.3.5)(typescript@5.9.3))(axios@1.13.6) + version: 0.9.1(@hey-api/openapi-ts@0.95.0(magicast@0.5.2)(typescript@5.9.3))(axios@1.15.0) '@hey-api/openapi-ts': - specifier: ^0.94.0 - version: 0.94.0(magicast@0.3.5)(typescript@5.9.3) + specifier: ^0.95.0 + version: 0.95.0(magicast@0.5.2)(typescript@5.9.3) '@tanstack/react-query': - specifier: ^5.90.21 - version: 5.90.21(react@19.2.4) + specifier: ^5.97.0 + version: 5.97.0(react@19.2.5) axios: - specifier: ^1.13.6 - version: 1.13.6 + specifier: ^1.15.0 + version: 1.15.0 next-themes: specifier: ^0.4.6 - version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 0.4.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: - specifier: ^19.2.4 - version: 19.2.4 + specifier: ^19.2.5 + version: 19.2.5 react-cookie: - specifier: ^8.0.1 - version: 8.0.1(react@19.2.4) + specifier: ^8.1.0 + version: 8.1.0(@types/react@19.2.14)(react@19.2.5) react-dom: - specifier: ^19.2.4 - version: 19.2.4(react@19.2.4) + specifier: ^19.2.5 + version: 19.2.5(react@19.2.5) react-hook-form: - specifier: ^7.71.2 - version: 7.71.2(react@19.2.4) + specifier: ^7.72.1 + version: 7.72.1(react@19.2.5) react-router-dom: - specifier: ^7.13.1 - version: 7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^7.14.0 + version: 7.14.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5) devDependencies: '@7nohe/openapi-react-query-codegen': - specifier: ^2.0.0 - version: 2.0.0(commander@14.0.3)(magicast@0.3.5)(ts-morph@27.0.2)(typescript@5.9.3) + specifier: ^2.1.0 + version: 2.1.0(commander@14.0.3)(magicast@0.5.2)(ts-morph@27.0.2)(typescript@5.9.3) '@eslint/compat': - specifier: ^2.0.3 - version: 2.0.3(eslint@10.0.3(jiti@2.6.1)) + specifier: ^2.0.5 + version: 2.0.5(eslint@10.2.0(jiti@2.6.1)) '@eslint/js': specifier: ^10.0.1 - version: 10.0.1(eslint@10.0.3(jiti@2.6.1)) + version: 10.0.1(eslint@10.2.0(jiti@2.6.1)) '@stylistic/eslint-plugin': specifier: ^5.10.0 - version: 5.10.0(eslint@10.0.3(jiti@2.6.1)) + version: 5.10.0(eslint@10.2.0(jiti@2.6.1)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 '@testing-library/react': specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 16.3.2(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.2 version: 6.0.2(prettier@3.8.1) @@ -93,47 +93,47 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.14) '@typescript-eslint/eslint-plugin': - specifier: 8.57.0 - version: 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + specifier: 8.58.1 + version: 8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': - specifier: 8.57.0 - version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + specifier: 8.58.1 + version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/utils': - specifier: ^8.57.0 - version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.58.1 + version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) '@vitejs/plugin-react-swc': specifier: ^4.3.0 - version: 4.3.0(@swc/helpers@0.5.19)(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) + version: 4.3.0(@swc/helpers@0.5.19)(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) '@vitest/coverage-v8': - specifier: ^4.1.0 - version: 4.1.0(vitest@4.1.0(@types/node@25.3.5)(happy-dom@20.8.9)(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3))) + specifier: ^4.1.4 + version: 4.1.4(vitest@4.1.4) eslint: - specifier: ^10.0.3 - version: 10.0.3(jiti@2.6.1) + specifier: ^10.2.0 + version: 10.2.0(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@10.0.3(jiti@2.6.1)) + version: 10.1.8(eslint@10.2.0(jiti@2.6.1)) eslint-plugin-jsx-a11y: specifier: ^6.10.2 - version: 6.10.2(eslint@10.0.3(jiti@2.6.1)) + version: 6.10.2(eslint@10.2.0(jiti@2.6.1)) eslint-plugin-perfectionist: - specifier: ^5.6.0 - version: 5.6.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + specifier: ^5.8.0 + version: 5.8.0(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) eslint-plugin-prettier: specifier: ^5.5.5 - version: 5.5.5(eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.6.1)))(eslint@10.0.3(jiti@2.6.1))(prettier@3.8.1) + version: 5.5.5(eslint-config-prettier@10.1.8(eslint@10.2.0(jiti@2.6.1)))(eslint@10.2.0(jiti@2.6.1))(prettier@3.8.1) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@10.0.3(jiti@2.6.1)) + version: 7.37.5(eslint@10.2.0(jiti@2.6.1)) eslint-plugin-react-hooks: specifier: ^7.0.1 - version: 7.0.1(eslint@10.0.3(jiti@2.6.1)) + version: 7.0.1(eslint@10.2.0(jiti@2.6.1)) eslint-plugin-react-refresh: specifier: ^0.5.2 - version: 0.5.2(eslint@10.0.3(jiti@2.6.1)) + version: 0.5.2(eslint@10.2.0(jiti@2.6.1)) eslint-plugin-unicorn: specifier: ^63.0.0 - version: 63.0.0(eslint@10.0.3(jiti@2.6.1)) + version: 63.0.0(eslint@10.2.0(jiti@2.6.1)) happy-dom: specifier: '>=20.8.9' version: 20.8.9 @@ -147,36 +147,32 @@ importers: specifier: ~5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.57.0 - version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.58.1 + version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) vite: - specifier: '>=7.3.2' - version: 8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) + specifier: ^8.0.8 + version: 8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) vite-plugin-css-injected-by-js: specifier: ^4.0.1 - version: 4.0.1(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) + version: 4.0.1(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) vitest: - specifier: ^4.1.0 - version: 4.1.0(@types/node@25.3.5)(happy-dom@20.8.9)(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) + specifier: ^4.1.4 + version: 4.1.4(@types/node@25.3.5)(@vitest/coverage-v8@4.1.4)(happy-dom@20.8.9)(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) packages: - '@7nohe/openapi-react-query-codegen@2.0.0': - resolution: {integrity: sha512-RZKQNK36xiziPzio9msj72gVuQq/d5WfiUI6cExCQuMOZUhdG2nEVdt1EunI3wc7msHX3oxVfxJGjMdn8ydz7w==} - engines: {node: '>=14', pnpm: '>=9'} + '@7nohe/openapi-react-query-codegen@2.1.0': + resolution: {integrity: sha512-aUIjrGRASWQC7CnKJilZlp5klrszZXudQNjNb91R1S1oUwhoP0HBLQYQp5GvkQXdn2+xrVJkY7ukptPR9z/0QA==} + engines: {node: '>=20.19.0', pnpm: '>=9'} hasBin: true peerDependencies: commander: 12.x - ts-morph: 23.x + ts-morph: 27.x typescript: 5.x '@adobe/css-tools@4.4.4': resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} - '@apidevtools/json-schema-ref-parser@11.7.0': - resolution: {integrity: sha512-pRrmXMCwnmrkS3MLgAIW5dXRzeTv6GLjkjb4HmxNnvAKXN1Nfzp4KmGADBQvlVUcqi+a5D+hfGDLLnd5NnYxog==} - engines: {node: '>= 16'} - '@ark-ui/react@5.34.1': resolution: {integrity: sha512-RJlXCvsHzbK9LVxUVtaSD5pyF1PL8IUR1rHHkf0H0Sa397l6kOFE4EH7MCSj3pDumj2NsmKDVeVgfkfG0KCuEw==} peerDependencies: @@ -259,8 +255,8 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} engines: {node: '>=6.0.0'} hasBin: true @@ -268,6 +264,10 @@ packages: resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -522,8 +522,8 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/compat@2.0.3': - resolution: {integrity: sha512-SjIJhGigp8hmd1YGIBwh7Ovri7Kisl42GYFjrOyHhtfYGGoLW6teYi/5p8W50KSsawUPpuLOSmsq1bD0NGQLBw==} + '@eslint/compat@2.0.5': + resolution: {integrity: sha512-IbHDbHJfkVNv6xjlET8AIVo/K1NQt7YT4Rp6ok/clyBGcpRx1l6gv0Rq3vBvYfPJIZt6ODf66Zq08FJNDpnzgg==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} peerDependencies: eslint: ^8.40 || 9 || 10 @@ -531,16 +531,16 @@ packages: eslint: optional: true - '@eslint/config-array@0.23.3': - resolution: {integrity: sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==} + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.5.3': - resolution: {integrity: sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==} + '@eslint/config-helpers@0.5.5': + resolution: {integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/core@1.1.1': - resolution: {integrity: sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==} + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/js@10.0.1': @@ -552,12 +552,12 @@ packages: eslint: optional: true - '@eslint/object-schema@3.0.3': - resolution: {integrity: sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==} + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.6.1': - resolution: {integrity: sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==} + '@eslint/plugin-kit@0.7.1': + resolution: {integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@floating-ui/core@1.7.5': @@ -576,45 +576,59 @@ packages: '@hey-api/openapi-ts': < 2 axios: '>= 1.0.0 < 2' - '@hey-api/client-fetch@0.4.0': - resolution: {integrity: sha512-T8T3yCl2+AiVVDP6tvfnU/rXOkEHddMTOYCZXUVbydj7URVErh5BelIa8UWBkFYZBP2/mi2nViScNhe9eBolPw==} - deprecated: Starting with v0.73.0, this package is bundled directly inside @hey-api/openapi-ts. - - '@hey-api/codegen-core@0.7.1': - resolution: {integrity: sha512-X5qG+rr/BJvr+pEGcoW6l2azoZGrVuxsviEIhuf+3VwL9bk0atfubT65Xwo+4jDxXvjbhZvlwS0Ty3I7mLE2fg==} + '@hey-api/codegen-core@0.7.0': + resolution: {integrity: sha512-HglL4B4QwpzocE+c8qDU6XK8zMf8W8Pcv0RpFDYxHuYALWLTnpDUuEsglC7NQ4vC1maoXsBpMbmwpco0N4QviA==} engines: {node: '>=20.19.0'} peerDependencies: typescript: '>=5.5.3' + '@hey-api/codegen-core@0.7.4': + resolution: {integrity: sha512-DGd9yeSQzflOWO3Y5mt1GRXkXH9O/yIMgbxPjwLI3jwu/3nAjoXXD26lEeFb6tclYlg0JAqTIs5d930G/qxHeA==} + engines: {node: '>=20.19.0'} + + '@hey-api/json-schema-ref-parser@1.2.4': + resolution: {integrity: sha512-uuOaZ6tStUgRJFUqnX3Xdbs792++ezxOLI5NMxuikVklpbFWk2wcvIZbeX+qTWDv6kiS1Ik2EVKQgeQFWHML4A==} + engines: {node: '>= 16'} + '@hey-api/json-schema-ref-parser@1.3.1': resolution: {integrity: sha512-7atnpUkT8TyUPHYPLk91j/GyaqMuwTEHanLOe50Dlx0EEvNuQqFD52Yjg8x4KU0UFL1mWlyhE+sUE/wAtQ1N2A==} engines: {node: '>=20.19.0'} - '@hey-api/openapi-ts@0.53.8': - resolution: {integrity: sha512-UbiaIq+JNgG00N/iWYk+LSivOBgWsfGxEHDleWEgQcQr3q7oZJTKL8oH87+KkFDDbUngm1g8lnKI/zLdu1aElQ==} - engines: {node: ^18.0.0 || >=20.0.0} + '@hey-api/openapi-ts@0.92.3': + resolution: {integrity: sha512-D+2ySL+PXvp1iZtS+1gTEeGChwjHT3d/a6o9IwAaNdGJVsI1lPqESZx7vxqjoUtE/DruovGZC2/jPc/kA5IQPg==} + engines: {node: '>=20.19.0'} hasBin: true peerDependencies: - typescript: ^5.x + typescript: '>=5.5.3' - '@hey-api/openapi-ts@0.94.0': - resolution: {integrity: sha512-dbg3GG+v7sg9/Ahb7yFzwzQIJwm151JAtsnh9KtFyqiN0rGkMGA3/VqogEUq1kJB9XWrlMQwigwzhiEQ33VCSg==} + '@hey-api/openapi-ts@0.95.0': + resolution: {integrity: sha512-lk5C+WKl5yqEmliQihEyhX/jNcWlAykTSEqkDeKa9xSq5YDAzOFvx7oos8YTqiIzdc4TemtlEaB8Rns7+8A0qg==} engines: {node: '>=20.19.0'} hasBin: true peerDependencies: - typescript: '>=5.5.3' + typescript: '>=5.5.3 || >=6.0.0 || 6.0.1-rc' - '@hey-api/shared@0.2.2': - resolution: {integrity: sha512-vMqCS+j7F9xpWoXC7TBbqZkaelwrdeuSB+s/3elu54V5iq++S59xhkSq5rOgDIpI1trpE59zZQa6dpyUxItOgw==} + '@hey-api/shared@0.1.2': + resolution: {integrity: sha512-dcldulfNI1xiXl/zhdXKDlNX2bvY0TOBWRRyFXNtcfPddMEFcrlXGmi/wk6LN4fPyDO8lM7FAM9aEpkEdUo92A==} engines: {node: '>=20.19.0'} peerDependencies: typescript: '>=5.5.3' + '@hey-api/shared@0.3.0': + resolution: {integrity: sha512-G+4GPojdLEh9bUwRG88teMPM1HdqMm/IsJ38cbnNxhyDu1FkFGwilkA1EqnULCzfTam/ZoZkaLdmAd8xEh4Xsw==} + engines: {node: '>=20.19.0'} + + '@hey-api/spec-types@0.1.0': + resolution: {integrity: sha512-StS4RrAO5pyJCBwe6uF9MAuPflkztriW+FPnVb7oEjzDYv1sxPwP+f7fL6u6D+UVrKpZ/9bPNx/xXVdkeWPU6A==} + '@hey-api/types@0.1.3': resolution: {integrity: sha512-mZaiPOWH761yD4GjDQvtjS2ZYLu5o5pI1TVSvV/u7cmbybv51/FVtinFBeaE1kFQCKZ8OQpn2ezjLBJrKsGATw==} peerDependencies: typescript: '>=5.5.3' + '@hey-api/types@0.1.4': + resolution: {integrity: sha512-thWfawrDIP7wSI9ioT13I5soaaqB5vAPIiZmgD8PbeEVKNrkonc0N/Sjj97ezl7oQgusZmaNphGdMKipPO6IBg==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -637,10 +651,6 @@ packages: '@internationalized/number@3.6.5': resolution: {integrity: sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==} - '@isaacs/fs-minipass@4.0.1': - resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} - engines: {node: '>=18.0.0'} - '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -660,14 +670,14 @@ packages: '@jsdevtools/ono@7.1.3': resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} - '@napi-rs/wasm-runtime@1.1.2': - resolution: {integrity: sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==} + '@napi-rs/wasm-runtime@1.1.3': + resolution: {integrity: sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@oxc-project/types@0.122.0': - resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} + '@oxc-project/types@0.124.0': + resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} '@pandacss/is-valid-prop@1.9.0': resolution: {integrity: sha512-AZvpXWGyjbHc8TC+YVloQ31Z2c4j2xMvYj6UfVxuZdB5w4c9+4N8wy5R7I/XswNh8e4cfUlkvsEGDXjhJRgypw==} @@ -676,103 +686,97 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@rolldown/binding-android-arm64@1.0.0-rc.12': - resolution: {integrity: sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==} + '@rolldown/binding-android-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-rc.12': - resolution: {integrity: sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==} + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.12': - resolution: {integrity: sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==} + '@rolldown/binding-darwin-x64@1.0.0-rc.15': + resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-rc.12': - resolution: {integrity: sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==} + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': + resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': - resolution: {integrity: sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': + resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': - resolution: {integrity: sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==} + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': + resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==} + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==} + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==} + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': - resolution: {integrity: sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==} + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': + resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': - resolution: {integrity: sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==} + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.12': - resolution: {integrity: sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==} + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': + resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': - resolution: {integrity: sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': + resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': - resolution: {integrity: sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==} + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': + resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-rc.12': - resolution: {integrity: sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==} + '@rolldown/pluginutils@1.0.0-rc.15': + resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==} '@rolldown/pluginutils@1.0.0-rc.7': resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==} @@ -809,28 +813,24 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [glibc] '@swc/core-linux-arm64-musl@1.15.18': resolution: {integrity: sha512-0a+Lix+FSSHBSBOA0XznCcHo5/1nA6oLLjcnocvzXeqtdjnPb+SvchItHI+lfeiuj1sClYPDvPMLSLyXFaiIKw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [musl] '@swc/core-linux-x64-gnu@1.15.18': resolution: {integrity: sha512-wG9J8vReUlpaHz4KOD/5UE1AUgirimU4UFT9oZmupUDEofxJKYb1mTA/DrMj0s78bkBiNI+7Fo2EgPuvOJfuAA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [glibc] '@swc/core-linux-x64-musl@1.15.18': resolution: {integrity: sha512-4nwbVvCphKzicwNWRmvD5iBaZj8JYsRGa4xOxJmOyHlMDpsvvJ2OR2cODlvWyGFH6BYL1MfIAK3qph3hp0Az6g==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [musl] '@swc/core-win32-arm64-msvc@1.15.18': resolution: {integrity: sha512-zk0RYO+LjiBCat2RTMHzAWaMky0cra9loH4oRrLKLLNuL+jarxKLFDA8xTZWEkCPLjUTwlRN7d28eDLLMgtUcQ==} @@ -868,11 +868,11 @@ packages: '@swc/types@0.1.25': resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} - '@tanstack/query-core@5.90.20': - resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} + '@tanstack/query-core@5.97.0': + resolution: {integrity: sha512-QdpLP5VzVMgo4VtaPppRA2W04UFjIqX+bxke/ZJhE5cfd5UPkRzqIAJQt9uXkQJjqE8LBOMbKv7f8HCsZltXlg==} - '@tanstack/react-query@5.90.21': - resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==} + '@tanstack/react-query@5.97.0': + resolution: {integrity: sha512-y4So4eGcQoK2WVMAcDNZE9ofB/p5v1OlKvtc1F3uqHwrtifobT7q+ZnXk2mRkc8E84HKYSlAE9z6HXl2V0+ySQ==} peerDependencies: react: ^18 || ^19 @@ -939,8 +939,10 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/hoist-non-react-statics@3.3.6': - resolution: {integrity: sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==} + '@types/hoist-non-react-statics@3.3.7': + resolution: {integrity: sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==} + peerDependencies: + '@types/react': '*' '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -965,63 +967,67 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@typescript-eslint/eslint-plugin@8.57.0': - resolution: {integrity: sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==} + '@typescript-eslint/eslint-plugin@8.58.1': + resolution: {integrity: sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.57.0 + '@typescript-eslint/parser': ^8.58.1 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.57.0': - resolution: {integrity: sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==} + '@typescript-eslint/parser@8.58.1': + resolution: {integrity: sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.57.0': - resolution: {integrity: sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==} + '@typescript-eslint/project-service@8.58.1': + resolution: {integrity: sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.57.0': - resolution: {integrity: sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==} + '@typescript-eslint/scope-manager@8.58.1': + resolution: {integrity: sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.57.0': - resolution: {integrity: sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==} + '@typescript-eslint/tsconfig-utils@8.58.1': + resolution: {integrity: sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.57.0': - resolution: {integrity: sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==} + '@typescript-eslint/type-utils@8.58.1': + resolution: {integrity: sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' '@typescript-eslint/types@8.57.0': resolution: {integrity: sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.57.0': - resolution: {integrity: sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==} + '@typescript-eslint/types@8.58.1': + resolution: {integrity: sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.58.1': + resolution: {integrity: sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.57.0': - resolution: {integrity: sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==} + '@typescript-eslint/utils@8.58.1': + resolution: {integrity: sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.57.0': - resolution: {integrity: sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==} + '@typescript-eslint/visitor-keys@8.58.1': + resolution: {integrity: sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react-swc@4.3.0': @@ -1030,20 +1036,20 @@ packages: peerDependencies: vite: '>=7.3.2' - '@vitest/coverage-v8@4.1.0': - resolution: {integrity: sha512-nDWulKeik2bL2Va/Wl4x7DLuTKAXa906iRFooIRPR+huHkcvp9QDkPQ2RJdmjOFrqOqvNfoSQLF68deE3xC3CQ==} + '@vitest/coverage-v8@4.1.4': + resolution: {integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==} peerDependencies: - '@vitest/browser': 4.1.0 - vitest: 4.1.0 + '@vitest/browser': 4.1.4 + vitest: 4.1.4 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.0': - resolution: {integrity: sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==} + '@vitest/expect@4.1.4': + resolution: {integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==} - '@vitest/mocker@4.1.0': - resolution: {integrity: sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==} + '@vitest/mocker@4.1.4': + resolution: {integrity: sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==} peerDependencies: msw: ^2.4.9 vite: '>=7.3.2' @@ -1053,20 +1059,20 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.0': - resolution: {integrity: sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==} + '@vitest/pretty-format@4.1.4': + resolution: {integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==} - '@vitest/runner@4.1.0': - resolution: {integrity: sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==} + '@vitest/runner@4.1.4': + resolution: {integrity: sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==} - '@vitest/snapshot@4.1.0': - resolution: {integrity: sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==} + '@vitest/snapshot@4.1.4': + resolution: {integrity: sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==} - '@vitest/spy@4.1.0': - resolution: {integrity: sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==} + '@vitest/spy@4.1.4': + resolution: {integrity: sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==} - '@vitest/utils@4.1.0': - resolution: {integrity: sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==} + '@vitest/utils@4.1.4': + resolution: {integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==} '@zag-js/accordion@1.35.3': resolution: {integrity: sha512-wmw6yo5Zr6ShiKGTc5ICEOJCurWAOSGubIpGISiHi3cZ4tlxKF/vpATIUT3eq8xzdB56YK57yKCujs/WmwqqoA==} @@ -1389,8 +1395,8 @@ packages: resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} engines: {node: '>=4'} - axios@1.13.6: - resolution: {integrity: sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==} + axios@1.15.0: + resolution: {integrity: sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==} axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -1425,14 +1431,6 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - c12@2.0.1: - resolution: {integrity: sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A==} - peerDependencies: - magicast: ^0.3.5 - peerDependenciesMeta: - magicast: - optional: true - c12@3.3.3: resolution: {integrity: sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q==} peerDependencies: @@ -1471,18 +1469,10 @@ packages: change-case@5.4.4: resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} - chokidar@4.0.3: - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} - engines: {node: '>= 14.16.0'} - chokidar@5.0.0: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} - chownr@3.0.0: - resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} - engines: {node: '>=18'} - ci-info@4.4.0: resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} @@ -1490,8 +1480,8 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - citty@0.2.1: - resolution: {integrity: sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg==} + citty@0.2.2: + resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==} clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} @@ -1515,17 +1505,10 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} - commander@14.0.3: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} - confbox@0.1.8: - resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - confbox@0.2.4: resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} @@ -1539,10 +1522,6 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie@1.0.2: - resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} - engines: {node: '>=18'} - cookie@1.1.1: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} @@ -1611,8 +1590,8 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - defu@6.1.6: - resolution: {integrity: sha512-f8mefEW4WIVg4LckePx3mALjQSPQgFlg9U8yaPdlsbdYcHQyj9n2zL2LJEA52smeYxOvmd/nB7TpMtHGMTHcug==} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} @@ -1639,12 +1618,8 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dotenv@16.6.1: - resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} - engines: {node: '>=12'} - - dotenv@17.3.1: - resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} + dotenv@17.4.2: + resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} dunder-proto@1.0.1: @@ -1728,8 +1703,8 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-perfectionist@5.6.0: - resolution: {integrity: sha512-pxrLrfRp5wl1Vol1fAEa/G5yTXxefTPJjz07qC7a8iWFXcOZNuWBItMQ2OtTzfQIvMq6bMyYcrzc3Wz++na55Q==} + eslint-plugin-perfectionist@5.8.0: + resolution: {integrity: sha512-k8uIptWIxkUclonCFGyDzgYs9NI+Qh0a7cUXS3L7IYZDEsjXuimFBVbxXPQQngWqMiaxJRwbtYB4smMGMqF+cw==} engines: {node: ^20.0.0 || >=22.0.0} peerDependencies: eslint: ^8.45.0 || ^9.0.0 || ^10.0.0 @@ -1787,8 +1762,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.0.3: - resolution: {integrity: sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==} + eslint@10.2.0: + resolution: {integrity: sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -1874,8 +1849,8 @@ packages: flatted@3.4.2: resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} - follow-redirects@1.15.11: - resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -1922,9 +1897,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - giget@1.2.5: - resolution: {integrity: sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug==} - hasBin: true + get-tsconfig@4.13.6: + resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} giget@2.0.0: resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} @@ -1946,11 +1920,6 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} - handlebars@4.7.9: - resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} - engines: {node: '>=0.4.7'} - hasBin: true - happy-dom@20.8.9: resolution: {integrity: sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA==} engines: {node: '>=20.0.0'} @@ -2253,28 +2222,24 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} @@ -2302,6 +2267,9 @@ packages: lodash-es@4.18.1: resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -2316,9 +2284,6 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.3.5: - resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} - magicast@0.5.2: resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} @@ -2346,19 +2311,9 @@ packages: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@3.1.0: - resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} - engines: {node: '>= 18'} - - mlly@1.8.0: - resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -2375,9 +2330,6 @@ packages: resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==} engines: {node: '>=18'} - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - next-themes@0.4.6: resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} peerDependencies: @@ -2390,11 +2342,6 @@ packages: node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} - nypm@0.5.4: - resolution: {integrity: sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA==} - engines: {node: ^14.16.0 || >=16.10.0} - hasBin: true - nypm@0.6.5: resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==} engines: {node: '>=18'} @@ -2431,9 +2378,6 @@ packages: obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - ohash@1.1.6: - resolution: {integrity: sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg==} - ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} @@ -2489,15 +2433,9 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - perfect-debounce@1.0.0: - resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} - perfect-debounce@2.1.0: resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} @@ -2511,9 +2449,6 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} - pkg-types@1.3.1: - resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} @@ -2525,8 +2460,8 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + postcss@8.5.9: + resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==} engines: {node: ^10 || ^12 || >=14} powershell-utils@0.1.0: @@ -2556,8 +2491,9 @@ packages: proxy-compare@3.0.1: resolution: {integrity: sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==} - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} proxy-memoize@3.0.1: resolution: {integrity: sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g==} @@ -2569,18 +2505,18 @@ packages: rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} - react-cookie@8.0.1: - resolution: {integrity: sha512-QNdAd0MLuAiDiLcDU/2s/eyKmmfMHtjPUKJ2dZ/5CcQ9QKUium4B3o61/haq6PQl/YWFqC5PO8GvxeHKhy3GFA==} + react-cookie@8.1.0: + resolution: {integrity: sha512-Qs+gD3gpQmUXnJUZafhJtNWhhNdi8OYbOAF5YQRAZa/D171ILOIEMfXDz/tmhkE+nOthllmqryHH6I/qmvIYWQ==} peerDependencies: react: '>= 16.3.0' - react-dom@19.2.4: - resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + react-dom@19.2.5: + resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==} peerDependencies: - react: ^19.2.4 + react: ^19.2.5 - react-hook-form@7.71.2: - resolution: {integrity: sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA==} + react-hook-form@7.72.1: + resolution: {integrity: sha512-RhwBoy2ygeVZje+C+bwJ8g0NjTdBmDlJvAUHTxRjTmSUKPYsKfMphkS2sgEMotsY03bP358yEYlnUeZy//D9Ig==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -2591,15 +2527,15 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - react-router-dom@7.13.1: - resolution: {integrity: sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==} + react-router-dom@7.14.0: + resolution: {integrity: sha512-2G3ajSVSZMEtmTjIklRWlNvo8wICEpLihfD/0YMDxbWK2UyP5EGfnoIn9AIQGnF3G/FX0MRbHXdFcD+rL1ZreQ==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' react-dom: '>=18' - react-router@7.13.1: - resolution: {integrity: sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==} + react-router@7.14.0: + resolution: {integrity: sha512-m/xR9N4LQLmAS0ZhkY2nkPA1N7gQ5TUVa5n8TgANuDTARbn1gt+zLPXEm7W0XDTbrQ2AJSJKhoa6yx1D8BcpxQ==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' @@ -2608,14 +2544,10 @@ packages: react-dom: optional: true - react@19.2.4: - resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + react@19.2.5: + resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} engines: {node: '>=0.10.0'} - readdirp@4.1.2: - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} - engines: {node: '>= 14.18.0'} - readdirp@5.0.0: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} @@ -2644,8 +2576,11 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} engines: {node: '>= 0.4'} hasBin: true @@ -2653,8 +2588,8 @@ packages: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true - rolldown@1.0.0-rc.12: - resolution: {integrity: sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==} + rolldown@1.0.0-rc.15: + resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2741,10 +2676,6 @@ packages: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2797,30 +2728,23 @@ packages: resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} engines: {node: ^14.18.0 || >=16.0.0} - tar@7.5.11: - resolution: {integrity: sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==} - engines: {node: '>=18'} - tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - - tinyexec@1.0.4: - resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + tinyexec@1.1.1: + resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} engines: {node: '>=18'} - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} tinyrainbow@3.1.0: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} - ts-api-utils@2.4.0: - resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -2851,26 +2775,18 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript-eslint@8.57.0: - resolution: {integrity: sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA==} + typescript-eslint@8.58.1: + resolution: {integrity: sha512-gf6/oHChByg9HJvhMO1iBexJh12AqqTfnuxscMDOVqfJW3htsdRJI/GfPpHTTcyeB8cSTUY2JcZmVgoyPqcrDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true - ufo@1.6.2: - resolution: {integrity: sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==} - - uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} - engines: {node: '>=0.8.0'} - hasBin: true - unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -2878,8 +2794,8 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - universal-cookie@8.0.1: - resolution: {integrity: sha512-B6ks9FLLnP1UbPPcveOidfvB9pHjP+wekP2uRYB9YDfKVpvcjKgy1W5Zj+cEXJ9KTPnqOKGfVDQBmn8/YCQfRg==} + universal-cookie@8.1.0: + resolution: {integrity: sha512-65+kikQAWq7gsJbirwB7dk6e8xeug1hx3++x2dQoymdXcV7fYv0yChOgHCg01ZwP3fE3sYeq6EWCSpFv3HLl9g==} update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} @@ -2898,8 +2814,8 @@ packages: peerDependencies: vite: '>=7.3.2' - vite@8.0.5: - resolution: {integrity: sha512-nmu43Qvq9UopTRfMx2jOYW5l16pb3iDC1JH6yMuPkpVbzK0k+L7dfsEDH4jRgYFmsg0sTAqkojoZgzLMlwHsCQ==} + vite@8.0.8: + resolution: {integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -2941,18 +2857,20 @@ packages: yaml: optional: true - vitest@4.1.0: - resolution: {integrity: sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==} + vitest@4.1.4: + resolution: {integrity: sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.0 - '@vitest/browser-preview': 4.1.0 - '@vitest/browser-webdriverio': 4.1.0 - '@vitest/ui': 4.1.0 + '@vitest/browser-playwright': 4.1.4 + '@vitest/browser-preview': 4.1.4 + '@vitest/browser-webdriverio': 4.1.4 + '@vitest/coverage-istanbul': 4.1.4 + '@vitest/coverage-v8': 4.1.4 + '@vitest/ui': 4.1.4 happy-dom: '>=20.8.9' jsdom: '*' vite: '>=7.3.2' @@ -2969,6 +2887,10 @@ packages: optional: true '@vitest/browser-webdriverio': optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true '@vitest/ui': optional: true happy-dom: @@ -3010,9 +2932,6 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - ws@8.19.0: resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} @@ -3032,10 +2951,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@5.0.0: - resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} - engines: {node: '>=18'} - yaml@2.8.3: resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} engines: {node: '>= 14.6'} @@ -3056,10 +2971,9 @@ packages: snapshots: - '@7nohe/openapi-react-query-codegen@2.0.0(commander@14.0.3)(magicast@0.3.5)(ts-morph@27.0.2)(typescript@5.9.3)': + '@7nohe/openapi-react-query-codegen@2.1.0(commander@14.0.3)(magicast@0.5.2)(ts-morph@27.0.2)(typescript@5.9.3)': dependencies: - '@hey-api/client-fetch': 0.4.0 - '@hey-api/openapi-ts': 0.53.8(magicast@0.3.5)(typescript@5.9.3) + '@hey-api/openapi-ts': 0.92.3(magicast@0.5.2)(typescript@5.9.3) commander: 14.0.3 cross-spawn: 7.0.6 ts-morph: 27.0.2 @@ -3069,13 +2983,7 @@ snapshots: '@adobe/css-tools@4.4.4': {} - '@apidevtools/json-schema-ref-parser@11.7.0': - dependencies: - '@jsdevtools/ono': 7.1.3 - '@types/json-schema': 7.0.15 - js-yaml: 4.1.1 - - '@ark-ui/react@5.34.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@ark-ui/react@5.34.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@internationalized/date': 3.11.0 '@zag-js/accordion': 1.35.3 @@ -3123,7 +3031,7 @@ snapshots: '@zag-js/qr-code': 1.35.3 '@zag-js/radio-group': 1.35.3 '@zag-js/rating-group': 1.35.3 - '@zag-js/react': 1.35.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@zag-js/react': 1.35.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@zag-js/scroll-area': 1.35.3 '@zag-js/select': 1.35.3 '@zag-js/signature-pad': 1.35.3 @@ -3142,8 +3050,8 @@ snapshots: '@zag-js/tree-view': 1.35.3 '@zag-js/types': 1.35.3 '@zag-js/utils': 1.35.3 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) '@babel/code-frame@7.27.1': dependencies: @@ -3195,7 +3103,7 @@ snapshots: '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 @@ -3253,12 +3161,14 @@ snapshots: dependencies: '@babel/types': 7.28.6 - '@babel/parser@7.29.0': + '@babel/parser@7.29.2': dependencies: '@babel/types': 7.29.0 '@babel/runtime@7.28.6': {} + '@babel/runtime@7.29.2': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -3288,7 +3198,7 @@ snapshots: '@babel/code-frame': 7.29.0 '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/template': 7.28.6 '@babel/types': 7.29.0 debug: 4.4.3 @@ -3307,18 +3217,18 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@chakra-ui/react@3.34.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@chakra-ui/react@3.34.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - '@ark-ui/react': 5.34.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@ark-ui/react': 5.34.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.4) + '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5) '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.4) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.5) '@emotion/utils': 1.4.2 '@pandacss/is-valid-prop': 1.9.0 csstype: 3.2.3 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) '@emnapi/core@1.9.2': dependencies: @@ -3339,7 +3249,7 @@ snapshots: '@emotion/babel-plugin@11.13.5': dependencies: '@babel/helper-module-imports': 7.28.6 - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 '@emotion/serialize': 1.3.3 @@ -3368,17 +3278,17 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4)': + '@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@emotion/babel-plugin': 11.13.5 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.4) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.5) '@emotion/utils': 1.4.2 '@emotion/weak-memoize': 0.4.0 hoist-non-react-statics: 3.3.2 - react: 19.2.4 + react: 19.2.5 optionalDependencies: '@types/react': 19.2.14 transitivePeerDependencies: @@ -3396,9 +3306,9 @@ snapshots: '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.4)': + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.5)': dependencies: - react: 19.2.4 + react: 19.2.5 '@emotion/utils@1.4.2': {} @@ -3482,44 +3392,44 @@ snapshots: '@esbuild/win32-x64@0.27.2': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.0.3(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0(jiti@2.6.1))': dependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/compat@2.0.3(eslint@10.0.3(jiti@2.6.1))': + '@eslint/compat@2.0.5(eslint@10.2.0(jiti@2.6.1))': dependencies: - '@eslint/core': 1.1.1 + '@eslint/core': 1.2.1 optionalDependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) - '@eslint/config-array@0.23.3': + '@eslint/config-array@0.23.5': dependencies: - '@eslint/object-schema': 3.0.3 + '@eslint/object-schema': 3.0.5 debug: 4.4.3 - minimatch: 10.2.4 + minimatch: 10.2.5 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.5.3': + '@eslint/config-helpers@0.5.5': dependencies: - '@eslint/core': 1.1.1 + '@eslint/core': 1.2.1 - '@eslint/core@1.1.1': + '@eslint/core@1.2.1': dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@10.0.1(eslint@10.0.3(jiti@2.6.1))': + '@eslint/js@10.0.1(eslint@10.2.0(jiti@2.6.1))': optionalDependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) - '@eslint/object-schema@3.0.3': {} + '@eslint/object-schema@3.0.5': {} - '@eslint/plugin-kit@0.6.1': + '@eslint/plugin-kit@0.7.1': dependencies: - '@eslint/core': 1.1.1 + '@eslint/core': 1.2.1 levn: 0.4.1 '@floating-ui/core@1.7.5': @@ -3533,56 +3443,75 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@hey-api/client-axios@0.9.1(@hey-api/openapi-ts@0.94.0(magicast@0.3.5)(typescript@5.9.3))(axios@1.13.6)': + '@hey-api/client-axios@0.9.1(@hey-api/openapi-ts@0.95.0(magicast@0.5.2)(typescript@5.9.3))(axios@1.15.0)': dependencies: - '@hey-api/openapi-ts': 0.94.0(magicast@0.3.5)(typescript@5.9.3) - axios: 1.13.6 + '@hey-api/openapi-ts': 0.95.0(magicast@0.5.2)(typescript@5.9.3) + axios: 1.15.0 - '@hey-api/client-fetch@0.4.0': {} - - '@hey-api/codegen-core@0.7.1(magicast@0.3.5)(typescript@5.9.3)': + '@hey-api/codegen-core@0.7.0(magicast@0.5.2)(typescript@5.9.3)': dependencies: '@hey-api/types': 0.1.3(typescript@5.9.3) ansi-colors: 4.1.3 - c12: 3.3.3(magicast@0.3.5) + c12: 3.3.3(magicast@0.5.2) color-support: 1.1.3 typescript: 5.9.3 transitivePeerDependencies: - magicast + '@hey-api/codegen-core@0.7.4(magicast@0.5.2)': + dependencies: + '@hey-api/types': 0.1.4 + ansi-colors: 4.1.3 + c12: 3.3.3(magicast@0.5.2) + color-support: 1.1.3 + transitivePeerDependencies: + - magicast + + '@hey-api/json-schema-ref-parser@1.2.4': + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + js-yaml: 4.1.1 + lodash: 4.18.1 + '@hey-api/json-schema-ref-parser@1.3.1': dependencies: '@jsdevtools/ono': 7.1.3 '@types/json-schema': 7.0.15 js-yaml: 4.1.1 - '@hey-api/openapi-ts@0.53.8(magicast@0.3.5)(typescript@5.9.3)': + '@hey-api/openapi-ts@0.92.3(magicast@0.5.2)(typescript@5.9.3)': dependencies: - '@apidevtools/json-schema-ref-parser': 11.7.0 - c12: 2.0.1(magicast@0.3.5) - commander: 12.1.0 - handlebars: 4.7.9 + '@hey-api/codegen-core': 0.7.0(magicast@0.5.2)(typescript@5.9.3) + '@hey-api/json-schema-ref-parser': 1.2.4 + '@hey-api/shared': 0.1.2(magicast@0.5.2)(typescript@5.9.3) + '@hey-api/types': 0.1.3(typescript@5.9.3) + ansi-colors: 4.1.3 + color-support: 1.1.3 + commander: 14.0.3 typescript: 5.9.3 transitivePeerDependencies: - magicast - '@hey-api/openapi-ts@0.94.0(magicast@0.3.5)(typescript@5.9.3)': + '@hey-api/openapi-ts@0.95.0(magicast@0.5.2)(typescript@5.9.3)': dependencies: - '@hey-api/codegen-core': 0.7.1(magicast@0.3.5)(typescript@5.9.3) + '@hey-api/codegen-core': 0.7.4(magicast@0.5.2) '@hey-api/json-schema-ref-parser': 1.3.1 - '@hey-api/shared': 0.2.2(magicast@0.3.5)(typescript@5.9.3) - '@hey-api/types': 0.1.3(typescript@5.9.3) + '@hey-api/shared': 0.3.0(magicast@0.5.2) + '@hey-api/spec-types': 0.1.0 + '@hey-api/types': 0.1.4 ansi-colors: 4.1.3 color-support: 1.1.3 commander: 14.0.3 + get-tsconfig: 4.13.6 typescript: 5.9.3 transitivePeerDependencies: - magicast - '@hey-api/shared@0.2.2(magicast@0.3.5)(typescript@5.9.3)': + '@hey-api/shared@0.1.2(magicast@0.5.2)(typescript@5.9.3)': dependencies: - '@hey-api/codegen-core': 0.7.1(magicast@0.3.5)(typescript@5.9.3) - '@hey-api/json-schema-ref-parser': 1.3.1 + '@hey-api/codegen-core': 0.7.0(magicast@0.5.2)(typescript@5.9.3) + '@hey-api/json-schema-ref-parser': 1.2.4 '@hey-api/types': 0.1.3(typescript@5.9.3) ansi-colors: 4.1.3 cross-spawn: 7.0.6 @@ -3592,10 +3521,29 @@ snapshots: transitivePeerDependencies: - magicast + '@hey-api/shared@0.3.0(magicast@0.5.2)': + dependencies: + '@hey-api/codegen-core': 0.7.4(magicast@0.5.2) + '@hey-api/json-schema-ref-parser': 1.3.1 + '@hey-api/spec-types': 0.1.0 + '@hey-api/types': 0.1.4 + ansi-colors: 4.1.3 + cross-spawn: 7.0.6 + open: 11.0.0 + semver: 7.7.3 + transitivePeerDependencies: + - magicast + + '@hey-api/spec-types@0.1.0': + dependencies: + '@hey-api/types': 0.1.4 + '@hey-api/types@0.1.3(typescript@5.9.3)': dependencies: typescript: 5.9.3 + '@hey-api/types@0.1.4': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -3615,10 +3563,6 @@ snapshots: dependencies: '@swc/helpers': 0.5.19 - '@isaacs/fs-minipass@4.0.1': - dependencies: - minipass: 7.1.2 - '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -3640,80 +3584,79 @@ snapshots: '@jsdevtools/ono@7.1.3': {} - '@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@napi-rs/wasm-runtime@1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: '@emnapi/core': 1.9.2 '@emnapi/runtime': 1.9.2 '@tybys/wasm-util': 0.10.1 optional: true - '@oxc-project/types@0.122.0': {} + '@oxc-project/types@0.124.0': {} '@pandacss/is-valid-prop@1.9.0': {} '@pkgr/core@0.2.9': {} - '@rolldown/binding-android-arm64@1.0.0-rc.12': + '@rolldown/binding-android-arm64@1.0.0-rc.15': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.12': + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.12': + '@rolldown/binding-darwin-x64@1.0.0-rc.15': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.12': + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': dependencies: - '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': optional: true - '@rolldown/pluginutils@1.0.0-rc.12': {} + '@rolldown/pluginutils@1.0.0-rc.15': {} '@rolldown/pluginutils@1.0.0-rc.7': {} '@standard-schema/spec@1.1.0': {} - '@stylistic/eslint-plugin@5.10.0(eslint@10.0.3(jiti@2.6.1))': + '@stylistic/eslint-plugin@5.10.0(eslint@10.2.0(jiti@2.6.1))': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) '@typescript-eslint/types': 8.57.0 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -3776,17 +3719,17 @@ snapshots: dependencies: '@swc/counter': 0.1.3 - '@tanstack/query-core@5.90.20': {} + '@tanstack/query-core@5.97.0': {} - '@tanstack/react-query@5.90.21(react@19.2.4)': + '@tanstack/react-query@5.97.0(react@19.2.5)': dependencies: - '@tanstack/query-core': 5.90.20 - react: 19.2.4 + '@tanstack/query-core': 5.97.0 + react: 19.2.5 '@testing-library/dom@10.4.0': dependencies: '@babel/code-frame': 7.29.0 - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -3803,12 +3746,12 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@babel/runtime': 7.28.6 '@testing-library/dom': 10.4.0 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) optionalDependencies: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) @@ -3829,9 +3772,9 @@ snapshots: '@ts-morph/common@0.28.1': dependencies: - minimatch: 10.2.4 + minimatch: 10.2.5 path-browserify: 1.0.1 - tinyglobby: 0.2.15 + tinyglobby: 0.2.16 '@tybys/wasm-util@0.10.1': dependencies: @@ -3851,7 +3794,7 @@ snapshots: '@types/estree@1.0.8': {} - '@types/hoist-non-react-statics@3.3.6': + '@types/hoist-non-react-statics@3.3.7(@types/react@19.2.14)': dependencies: '@types/react': 19.2.14 hoist-non-react-statics: 3.3.2 @@ -3878,109 +3821,111 @@ snapshots: dependencies: '@types/node': 25.3.5 - '@typescript-eslint/eslint-plugin@8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.57.0 - '@typescript-eslint/type-utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.0 - eslint: 10.0.3(jiti@2.6.1) + '@typescript-eslint/parser': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.58.1 + '@typescript-eslint/type-utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.58.1 + eslint: 10.2.0(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.57.0 - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.0 + '@typescript-eslint/scope-manager': 8.58.1 + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.58.1 debug: 4.4.3 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.57.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.58.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.57.0(typescript@5.9.3) - '@typescript-eslint/types': 8.57.0 + '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.9.3) + '@typescript-eslint/types': 8.58.1 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.57.0': + '@typescript-eslint/scope-manager@8.58.1': dependencies: - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/visitor-keys': 8.57.0 + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/visitor-keys': 8.58.1 - '@typescript-eslint/tsconfig-utils@8.57.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.58.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 10.0.3(jiti@2.6.1) - ts-api-utils: 2.4.0(typescript@5.9.3) + eslint: 10.2.0(jiti@2.6.1) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color '@typescript-eslint/types@8.57.0': {} - '@typescript-eslint/typescript-estree@8.57.0(typescript@5.9.3)': + '@typescript-eslint/types@8.58.1': {} + + '@typescript-eslint/typescript-estree@8.58.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.57.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.57.0(typescript@5.9.3) - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/visitor-keys': 8.57.0 + '@typescript-eslint/project-service': 8.58.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.9.3) + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/visitor-keys': 8.58.1 debug: 4.4.3 - minimatch: 10.2.4 + minimatch: 10.2.5 semver: 7.7.4 - tinyglobby: 0.2.15 - ts-api-utils: 2.4.0(typescript@5.9.3) + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.57.0 - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - eslint: 10.0.3(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.58.1 + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3) + eslint: 10.2.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.57.0': + '@typescript-eslint/visitor-keys@8.58.1': dependencies: - '@typescript-eslint/types': 8.57.0 + '@typescript-eslint/types': 8.58.1 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react-swc@4.3.0(@swc/helpers@0.5.19)(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3))': + '@vitejs/plugin-react-swc@4.3.0(@swc/helpers@0.5.19)(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 '@swc/core': 1.15.18(@swc/helpers@0.5.19) - vite: 8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) transitivePeerDependencies: - '@swc/helpers' - '@vitest/coverage-v8@4.1.0(vitest@4.1.0(@types/node@25.3.5)(happy-dom@20.8.9)(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)))': + '@vitest/coverage-v8@4.1.4(vitest@4.1.4)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.0 + '@vitest/utils': 4.1.4 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -3989,46 +3934,46 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.0(@types/node@25.3.5)(happy-dom@20.8.9)(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) + vitest: 4.1.4(@types/node@25.3.5)(@vitest/coverage-v8@4.1.4)(happy-dom@20.8.9)(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) - '@vitest/expect@4.1.0': + '@vitest/expect@4.1.4': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.0 - '@vitest/utils': 4.1.0 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.0(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3))': + '@vitest/mocker@4.1.4(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.1.0 + '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) - '@vitest/pretty-format@4.1.0': + '@vitest/pretty-format@4.1.4': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.0': + '@vitest/runner@4.1.4': dependencies: - '@vitest/utils': 4.1.0 + '@vitest/utils': 4.1.4 pathe: 2.0.3 - '@vitest/snapshot@4.1.0': + '@vitest/snapshot@4.1.4': dependencies: - '@vitest/pretty-format': 4.1.0 - '@vitest/utils': 4.1.0 + '@vitest/pretty-format': 4.1.4 + '@vitest/utils': 4.1.4 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.0': {} + '@vitest/spy@4.1.4': {} - '@vitest/utils@4.1.0': + '@vitest/utils@4.1.4': dependencies: - '@vitest/pretty-format': 4.1.0 + '@vitest/pretty-format': 4.1.4 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -4414,14 +4359,14 @@ snapshots: '@zag-js/types': 1.35.3 '@zag-js/utils': 1.35.3 - '@zag-js/react@1.35.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@zag-js/react@1.35.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@zag-js/core': 1.35.3 '@zag-js/store': 1.35.3 '@zag-js/types': 1.35.3 '@zag-js/utils': 1.35.3 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) '@zag-js/rect-utils@1.35.3': {} @@ -4694,11 +4639,11 @@ snapshots: axe-core@4.10.3: {} - axios@1.13.6: + axios@1.15.0: dependencies: - follow-redirects: 1.15.11 + follow-redirects: 1.16.0 form-data: 4.0.5 - proxy-from-env: 1.1.0 + proxy-from-env: 2.1.0 transitivePeerDependencies: - debug @@ -4706,9 +4651,9 @@ snapshots: babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 cosmiconfig: 7.1.0 - resolve: 1.22.11 + resolve: 1.22.12 balanced-match@4.0.4: {} @@ -4732,29 +4677,12 @@ snapshots: dependencies: run-applescript: 7.1.0 - c12@2.0.1(magicast@0.3.5): - dependencies: - chokidar: 4.0.3 - confbox: 0.1.8 - defu: 6.1.6 - dotenv: 16.6.1 - giget: 1.2.5 - jiti: 2.6.1 - mlly: 1.8.0 - ohash: 1.1.6 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.3.1 - rc9: 2.1.2 - optionalDependencies: - magicast: 0.3.5 - - c12@3.3.3(magicast@0.3.5): + c12@3.3.3(magicast@0.5.2): dependencies: chokidar: 5.0.0 confbox: 0.2.4 - defu: 6.1.6 - dotenv: 17.3.1 + defu: 6.1.7 + dotenv: 17.4.2 exsolve: 1.0.8 giget: 2.0.0 jiti: 2.6.1 @@ -4764,7 +4692,7 @@ snapshots: pkg-types: 2.3.0 rc9: 2.1.2 optionalDependencies: - magicast: 0.3.5 + magicast: 0.5.2 call-bind-apply-helpers@1.0.2: dependencies: @@ -4796,23 +4724,17 @@ snapshots: change-case@5.4.4: {} - chokidar@4.0.3: - dependencies: - readdirp: 4.1.2 - chokidar@5.0.0: dependencies: readdirp: 5.0.0 - chownr@3.0.0: {} - ci-info@4.4.0: {} citty@0.1.6: dependencies: consola: 3.4.2 - citty@0.2.1: {} + citty@0.2.2: {} clean-regexp@1.0.0: dependencies: @@ -4832,12 +4754,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 - commander@12.1.0: {} - commander@14.0.3: {} - confbox@0.1.8: {} - confbox@0.2.4: {} consola@3.4.2: {} @@ -4846,8 +4764,6 @@ snapshots: convert-source-map@2.0.0: {} - cookie@1.0.2: {} - cookie@1.1.1: {} core-js-compat@3.48.0: @@ -4919,7 +4835,7 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - defu@6.1.6: {} + defu@6.1.7: {} delayed-stream@1.0.0: {} @@ -4937,9 +4853,7 @@ snapshots: dom-accessibility-api@0.6.3: {} - dotenv@16.6.1: {} - - dotenv@17.3.1: {} + dotenv@17.4.2: {} dunder-proto@1.0.1: dependencies: @@ -5093,11 +5007,11 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@10.2.0(jiti@2.6.1)): dependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) - eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.3(jiti@2.6.1)): + eslint-plugin-jsx-a11y@6.10.2(eslint@10.2.0(jiti@2.6.1)): dependencies: aria-query: 5.3.2 array-includes: 3.1.8 @@ -5107,7 +5021,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -5116,40 +5030,40 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-perfectionist@5.6.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3): + eslint-plugin-perfectionist@5.8.0(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - eslint: 10.0.3(jiti@2.6.1) + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 10.2.0(jiti@2.6.1) natural-orderby: 5.0.0 transitivePeerDependencies: - supports-color - typescript - eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.6.1)))(eslint@10.0.3(jiti@2.6.1))(prettier@3.8.1): + eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@10.2.0(jiti@2.6.1)))(eslint@10.2.0(jiti@2.6.1))(prettier@3.8.1): dependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) prettier: 3.8.1 prettier-linter-helpers: 1.0.1 synckit: 0.11.12 optionalDependencies: - eslint-config-prettier: 10.1.8(eslint@10.0.3(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@10.2.0(jiti@2.6.1)) - eslint-plugin-react-hooks@7.0.1(eslint@10.0.3(jiti@2.6.1)): + eslint-plugin-react-hooks@7.0.1(eslint@10.2.0(jiti@2.6.1)): dependencies: '@babel/core': 7.28.5 '@babel/parser': 7.28.5 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) hermes-parser: 0.25.1 zod: 4.1.12 zod-validation-error: 4.0.2(zod@4.1.12) transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.5.2(eslint@10.0.3(jiti@2.6.1)): + eslint-plugin-react-refresh@0.5.2(eslint@10.2.0(jiti@2.6.1)): dependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) - eslint-plugin-react@7.37.5(eslint@10.0.3(jiti@2.6.1)): + eslint-plugin-react@7.37.5(eslint@10.2.0(jiti@2.6.1)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -5157,7 +5071,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -5171,15 +5085,15 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-unicorn@63.0.0(eslint@10.0.3(jiti@2.6.1)): + eslint-plugin-unicorn@63.0.0(eslint@10.2.0(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) change-case: 5.4.4 ci-info: 4.4.0 clean-regexp: 1.0.0 core-js-compat: 3.48.0 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.2.0(jiti@2.6.1) find-up-simple: 1.0.1 globals: 16.5.0 indent-string: 5.0.0 @@ -5204,14 +5118,14 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.0.3(jiti@2.6.1): + eslint@10.2.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.3 - '@eslint/config-helpers': 0.5.3 - '@eslint/core': 1.1.1 - '@eslint/plugin-kit': 0.6.1 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.5.5 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -5233,7 +5147,7 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.4 + minimatch: 10.2.5 natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -5305,7 +5219,7 @@ snapshots: flatted@3.4.2: {} - follow-redirects@1.15.11: {} + follow-redirects@1.16.0: {} for-each@0.3.5: dependencies: @@ -5361,21 +5275,15 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - giget@1.2.5: + get-tsconfig@4.13.6: dependencies: - citty: 0.1.6 - consola: 3.4.2 - defu: 6.1.6 - node-fetch-native: 1.6.7 - nypm: 0.5.4 - pathe: 2.0.3 - tar: 7.5.11 + resolve-pkg-maps: 1.0.0 giget@2.0.0: dependencies: citty: 0.1.6 consola: 3.4.2 - defu: 6.1.6 + defu: 6.1.7 node-fetch-native: 1.6.7 nypm: 0.6.5 pathe: 2.0.3 @@ -5393,15 +5301,6 @@ snapshots: gopd@1.2.0: {} - handlebars@4.7.9: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - happy-dom@20.8.9: dependencies: '@types/node': 25.3.5 @@ -5719,6 +5618,8 @@ snapshots: lodash-es@4.18.1: {} + lodash@4.18.1: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -5733,16 +5634,9 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.3.5: - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - source-map-js: 1.2.1 - optional: true - magicast@0.5.2: dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/types': 7.29.0 source-map-js: 1.2.1 @@ -5764,20 +5658,9 @@ snapshots: dependencies: brace-expansion: 5.0.5 - minimist@1.2.8: {} - - minipass@7.1.2: {} - - minizlib@3.1.0: - dependencies: - minipass: 7.1.2 - - mlly@1.8.0: + minimatch@10.2.5: dependencies: - acorn: 8.16.0 - pathe: 2.0.3 - pkg-types: 1.3.1 - ufo: 1.6.2 + brace-expansion: 5.0.5 ms@2.1.3: {} @@ -5787,31 +5670,20 @@ snapshots: natural-orderby@5.0.0: {} - neo-async@2.6.2: {} - - next-themes@0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next-themes@0.4.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) node-fetch-native@1.6.7: {} node-releases@2.0.27: {} - nypm@0.5.4: - dependencies: - citty: 0.1.6 - consola: 3.4.2 - pathe: 2.0.3 - pkg-types: 1.3.1 - tinyexec: 0.3.2 - ufo: 1.6.2 - nypm@0.6.5: dependencies: - citty: 0.2.1 + citty: 0.2.2 pathe: 2.0.3 - tinyexec: 1.0.4 + tinyexec: 1.1.1 object-assign@4.1.1: {} @@ -5851,8 +5723,6 @@ snapshots: obug@2.1.1: {} - ohash@1.1.6: {} - ohash@2.0.11: {} open@11.0.0: @@ -5914,12 +5784,8 @@ snapshots: path-type@4.0.0: {} - pathe@1.1.2: {} - pathe@2.0.3: {} - perfect-debounce@1.0.0: {} - perfect-debounce@2.1.0: {} perfect-freehand@1.2.3: {} @@ -5928,12 +5794,6 @@ snapshots: picomatch@4.0.4: {} - pkg-types@1.3.1: - dependencies: - confbox: 0.1.8 - mlly: 1.8.0 - pathe: 2.0.3 - pkg-types@2.3.0: dependencies: confbox: 0.2.4 @@ -5944,7 +5804,7 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss@8.5.8: + postcss@8.5.9: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -5974,7 +5834,7 @@ snapshots: proxy-compare@3.0.1: {} - proxy-from-env@1.1.0: {} + proxy-from-env@2.1.0: {} proxy-memoize@3.0.1: dependencies: @@ -5984,46 +5844,46 @@ snapshots: rc9@2.1.2: dependencies: - defu: 6.1.6 + defu: 6.1.7 destr: 2.0.5 - react-cookie@8.0.1(react@19.2.4): + react-cookie@8.1.0(@types/react@19.2.14)(react@19.2.5): dependencies: - '@types/hoist-non-react-statics': 3.3.6 + '@types/hoist-non-react-statics': 3.3.7(@types/react@19.2.14) hoist-non-react-statics: 3.3.2 - react: 19.2.4 - universal-cookie: 8.0.1 + react: 19.2.5 + universal-cookie: 8.1.0 + transitivePeerDependencies: + - '@types/react' - react-dom@19.2.4(react@19.2.4): + react-dom@19.2.5(react@19.2.5): dependencies: - react: 19.2.4 + react: 19.2.5 scheduler: 0.27.0 - react-hook-form@7.71.2(react@19.2.4): + react-hook-form@7.72.1(react@19.2.5): dependencies: - react: 19.2.4 + react: 19.2.5 react-is@16.13.1: {} react-is@17.0.2: {} - react-router-dom@7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + react-router-dom@7.14.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-router: 7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-router: 7.14.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - react-router@7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + react-router@7.14.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: cookie: 1.1.1 - react: 19.2.4 + react: 19.2.5 set-cookie-parser: 2.7.2 optionalDependencies: - react-dom: 19.2.4(react@19.2.4) - - react@19.2.4: {} + react-dom: 19.2.5(react@19.2.5) - readdirp@4.1.2: {} + react@19.2.5: {} readdirp@5.0.0: {} @@ -6060,8 +5920,11 @@ snapshots: resolve-from@4.0.0: {} - resolve@1.22.11: + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.12: dependencies: + es-errors: 1.3.0 is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -6072,29 +5935,26 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - rolldown@1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): + rolldown@1.0.0-rc.15: dependencies: - '@oxc-project/types': 0.122.0 - '@rolldown/pluginutils': 1.0.0-rc.12 + '@oxc-project/types': 0.124.0 + '@rolldown/pluginutils': 1.0.0-rc.15 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.12 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.12 - '@rolldown/binding-darwin-x64': 1.0.0-rc.12 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.12 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.12 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.12 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.12 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.12 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.12 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.12 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.12 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.12 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.12 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.12 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' + '@rolldown/binding-android-arm64': 1.0.0-rc.15 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.15 + '@rolldown/binding-darwin-x64': 1.0.0-rc.15 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.15 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.15 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.15 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.15 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.15 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.15 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15 run-applescript@7.1.0: {} @@ -6189,8 +6049,6 @@ snapshots: source-map@0.5.7: {} - source-map@0.6.1: {} - stackback@0.0.2: {} std-env@4.0.0: {} @@ -6263,28 +6121,18 @@ snapshots: dependencies: '@pkgr/core': 0.2.9 - tar@7.5.11: - dependencies: - '@isaacs/fs-minipass': 4.0.1 - chownr: 3.0.0 - minipass: 7.1.2 - minizlib: 3.1.0 - yallist: 5.0.0 - tinybench@2.9.0: {} - tinyexec@0.3.2: {} - - tinyexec@1.0.4: {} + tinyexec@1.1.1: {} - tinyglobby@0.2.15: + tinyglobby@0.2.16: dependencies: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 tinyrainbow@3.1.0: {} - ts-api-utils@2.4.0(typescript@5.9.3): + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -6332,24 +6180,19 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - eslint: 10.0.3(jiti@2.6.1) + '@typescript-eslint/eslint-plugin': 8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 10.2.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color typescript@5.9.3: {} - ufo@1.6.2: {} - - uglify-js@3.19.3: - optional: true - unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -6359,9 +6202,9 @@ snapshots: undici-types@7.18.2: {} - universal-cookie@8.0.1: + universal-cookie@8.1.0: dependencies: - cookie: 1.0.2 + cookie: 1.1.1 update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: @@ -6375,36 +6218,33 @@ snapshots: dependencies: punycode: 2.3.1 - vite-plugin-css-injected-by-js@4.0.1(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)): + vite-plugin-css-injected-by-js@4.0.1(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)): dependencies: - vite: 8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) - vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3): + vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.8 - rolldown: 1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - tinyglobby: 0.2.15 + postcss: 8.5.9 + rolldown: 1.0.0-rc.15 + tinyglobby: 0.2.16 optionalDependencies: '@types/node': 25.3.5 esbuild: 0.27.2 fsevents: 2.3.3 jiti: 2.6.1 yaml: 2.8.3 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - - vitest@4.1.0(@types/node@25.3.5)(happy-dom@20.8.9)(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)): - dependencies: - '@vitest/expect': 4.1.0 - '@vitest/mocker': 4.1.0(vite@8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.0 - '@vitest/runner': 4.1.0 - '@vitest/snapshot': 4.1.0 - '@vitest/spy': 4.1.0 - '@vitest/utils': 4.1.0 + + vitest@4.1.4(@types/node@25.3.5)(@vitest/coverage-v8@4.1.4)(happy-dom@20.8.9)(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)): + dependencies: + '@vitest/expect': 4.1.4 + '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.4 + '@vitest/runner': 4.1.4 + '@vitest/snapshot': 4.1.4 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -6413,13 +6253,14 @@ snapshots: picomatch: 4.0.4 std-env: 4.0.0 tinybench: 2.9.0 - tinyexec: 1.0.4 - tinyglobby: 0.2.15 + tinyexec: 1.1.1 + tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.5(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.3.5)(esbuild@0.27.2)(jiti@2.6.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.3.5 + '@vitest/coverage-v8': 4.1.4(vitest@4.1.4) happy-dom: 20.8.9 transitivePeerDependencies: - msw @@ -6478,8 +6319,6 @@ snapshots: word-wrap@1.2.5: {} - wordwrap@1.0.0: {} - ws@8.19.0: {} wsl-utils@0.3.1: @@ -6489,8 +6328,6 @@ snapshots: yallist@3.1.1: {} - yallist@5.0.0: {} - yaml@2.8.3: {} yocto-queue@0.1.0: {} From a1bc3d055f2190e62c60957c2b5f8b33a5318698 Mon Sep 17 00:00:00 2001 From: vincbeck Date: Tue, 14 Apr 2026 12:35:21 -0300 Subject: [PATCH 100/100] Update generated files --- .pre-commit-config.yaml | 1 + .../simple/ui/openapi-gen/queries/common.ts | 11 +- .../ui/openapi-gen/queries/ensureQueryData.ts | 21 +- .../simple/ui/openapi-gen/queries/index.ts | 2 +- .../ui/openapi-gen/queries/infiniteQueries.ts | 2 +- .../simple/ui/openapi-gen/queries/prefetch.ts | 21 +- .../simple/ui/openapi-gen/queries/queries.ts | 33 +- .../simple/ui/openapi-gen/queries/suspense.ts | 27 +- .../ui/openapi-gen/requests/client.gen.ts | 16 + .../openapi-gen/requests/client/client.gen.ts | 156 ++++++++ .../ui/openapi-gen/requests/client/index.ts | 23 ++ .../openapi-gen/requests/client/types.gen.ts | 160 ++++++++ .../openapi-gen/requests/client/utils.gen.ts | 208 ++++++++++ .../ui/openapi-gen/requests/core/ApiError.ts | 21 - .../requests/core/ApiRequestOptions.ts | 14 - .../ui/openapi-gen/requests/core/ApiResult.ts | 7 - .../requests/core/CancelablePromise.ts | 126 ------ .../ui/openapi-gen/requests/core/OpenAPI.ts | 58 --- .../ui/openapi-gen/requests/core/auth.gen.ts | 41 ++ .../requests/core/bodySerializer.gen.ts | 84 ++++ .../openapi-gen/requests/core/params.gen.ts | 169 ++++++++ .../requests/core/pathSerializer.gen.ts | 171 ++++++++ .../requests/core/queryKeySerializer.gen.ts | 117 ++++++ .../ui/openapi-gen/requests/core/request.ts | 374 ------------------ .../requests/core/serverSentEvents.gen.ts | 243 ++++++++++++ .../ui/openapi-gen/requests/core/types.gen.ts | 104 +++++ .../ui/openapi-gen/requests/core/utils.gen.ts | 140 +++++++ .../simple/ui/openapi-gen/requests/index.ts | 6 +- .../ui/openapi-gen/requests/schemas.gen.ts | 177 +++++---- .../simple/ui/openapi-gen/requests/sdk.gen.ts | 67 ++++ .../ui/openapi-gen/requests/services.gen.ts | 74 +--- .../ui/openapi-gen/requests/types.gen.ts | 195 +++++++-- .../managers/simple/ui/src/queryClient.ts | 11 +- 33 files changed, 2060 insertions(+), 820 deletions(-) create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/client.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/index.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/types.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/utils.gen.ts delete mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiError.ts delete mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiRequestOptions.ts delete mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiResult.ts delete mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/CancelablePromise.ts delete mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/OpenAPI.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/auth.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/bodySerializer.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/params.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/pathSerializer.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/queryKeySerializer.gen.ts delete mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/request.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/serverSentEvents.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/types.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/utils.gen.ts create mode 100644 airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/sdk.gen.ts diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 77033ceadc584..91e7a99444fb9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -469,6 +469,7 @@ repos: ^clients/gen/go\.sh$| ^\.gitmodules$| ^airflow-core/src/airflow/ui/openapi-gen/| + ^airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/| ^providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/| .*/dist/.*| \.go$| diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/common.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/common.ts index cefec2d009b8d..17f37daa8cc71 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/common.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/common.ts @@ -1,8 +1,9 @@ -// generated with @7nohe/openapi-react-query-codegen@2.0.0 -import { type Options } from "@hey-api/client-axios"; +// generated with @7nohe/openapi-react-query-codegen@2.1.0 import { UseQueryResult } from "@tanstack/react-query"; -import { createToken, createTokenAllAdmins, createTokenCli, loginAllAdmins } from "../requests/services.gen"; +import type { Options } from "../requests/sdk.gen"; +import { createToken, createTokenAllAdmins, createTokenCli, loginAllAdmins } from "../requests/sdk.gen"; +import { CreateTokenAllAdminsData, LoginAllAdminsData } from "../requests/types.gen"; export type CreateTokenAllAdminsDefaultResponse = Awaited>["data"]; export type CreateTokenAllAdminsQueryResult< @@ -11,7 +12,7 @@ export type CreateTokenAllAdminsQueryResult< > = UseQueryResult; export const useCreateTokenAllAdminsKey = "CreateTokenAllAdmins"; export const UseCreateTokenAllAdminsKeyFn = ( - clientOptions: Options = {}, + clientOptions: Options = {}, queryKey?: Array, ) => [useCreateTokenAllAdminsKey, ...(queryKey ?? [clientOptions])]; export type LoginAllAdminsDefaultResponse = Awaited>["data"]; @@ -21,7 +22,7 @@ export type LoginAllAdminsQueryResult< > = UseQueryResult; export const useLoginAllAdminsKey = "LoginAllAdmins"; export const UseLoginAllAdminsKeyFn = ( - clientOptions: Options = {}, + clientOptions: Options = {}, queryKey?: Array, ) => [useLoginAllAdminsKey, ...(queryKey ?? [clientOptions])]; export type CreateTokenMutationResult = Awaited>; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/ensureQueryData.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/ensureQueryData.ts index 2ef7bd14a6952..a0f3de25ddeb2 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/ensureQueryData.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/ensureQueryData.ts @@ -1,21 +1,32 @@ -// generated with @7nohe/openapi-react-query-codegen@2.0.0 -import { type Options } from "@hey-api/client-axios"; +// generated with @7nohe/openapi-react-query-codegen@2.1.0 import { type QueryClient } from "@tanstack/react-query"; -import { createTokenAllAdmins, loginAllAdmins } from "../requests/services.gen"; +import type { Options } from "../requests/sdk.gen"; +import { createTokenAllAdmins, loginAllAdmins } from "../requests/sdk.gen"; +import { CreateTokenAllAdminsData, LoginAllAdminsData } from "../requests/types.gen"; import * as Common from "./common"; +/** + * Create Token All Admins + * + * Create a token with no credentials only if ``simple_auth_manager_all_admins`` is True. + */ export const ensureUseCreateTokenAllAdminsData = ( queryClient: QueryClient, - clientOptions: Options = {}, + clientOptions: Options = {}, ) => queryClient.ensureQueryData({ queryKey: Common.UseCreateTokenAllAdminsKeyFn(clientOptions), queryFn: () => createTokenAllAdmins({ ...clientOptions }).then((response) => response.data), }); +/** + * Login All Admins + * + * Login the user with no credentials. + */ export const ensureUseLoginAllAdminsData = ( queryClient: QueryClient, - clientOptions: Options = {}, + clientOptions: Options = {}, ) => queryClient.ensureQueryData({ queryKey: Common.UseLoginAllAdminsKeyFn(clientOptions), diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/index.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/index.ts index 1fecbe2b0d243..fd344d39ed445 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/index.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/index.ts @@ -1,4 +1,4 @@ -// generated with @7nohe/openapi-react-query-codegen@2.0.0 +// generated with @7nohe/openapi-react-query-codegen@2.1.0 export * from "./common"; export * from "./queries"; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/infiniteQueries.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/infiniteQueries.ts index 9d70f5ba83f5c..eb9895b02c265 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/infiniteQueries.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/infiniteQueries.ts @@ -1 +1 @@ -// generated with @7nohe/openapi-react-query-codegen@2.0.0 +// generated with @7nohe/openapi-react-query-codegen@2.1.0 diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/prefetch.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/prefetch.ts index 26121c74967ef..9d3156f311a54 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/prefetch.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/prefetch.ts @@ -1,21 +1,32 @@ -// generated with @7nohe/openapi-react-query-codegen@2.0.0 -import { type Options } from "@hey-api/client-axios"; +// generated with @7nohe/openapi-react-query-codegen@2.1.0 import { type QueryClient } from "@tanstack/react-query"; -import { createTokenAllAdmins, loginAllAdmins } from "../requests/services.gen"; +import type { Options } from "../requests/sdk.gen"; +import { createTokenAllAdmins, loginAllAdmins } from "../requests/sdk.gen"; +import { CreateTokenAllAdminsData, LoginAllAdminsData } from "../requests/types.gen"; import * as Common from "./common"; +/** + * Create Token All Admins + * + * Create a token with no credentials only if ``simple_auth_manager_all_admins`` is True. + */ export const prefetchUseCreateTokenAllAdmins = ( queryClient: QueryClient, - clientOptions: Options = {}, + clientOptions: Options = {}, ) => queryClient.prefetchQuery({ queryKey: Common.UseCreateTokenAllAdminsKeyFn(clientOptions), queryFn: () => createTokenAllAdmins({ ...clientOptions }).then((response) => response.data), }); +/** + * Login All Admins + * + * Login the user with no credentials. + */ export const prefetchUseLoginAllAdmins = ( queryClient: QueryClient, - clientOptions: Options = {}, + clientOptions: Options = {}, ) => queryClient.prefetchQuery({ queryKey: Common.UseLoginAllAdminsKeyFn(clientOptions), diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/queries.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/queries.ts index 5e1ad9acc5208..461248cf6bc04 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/queries.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/queries.ts @@ -1,24 +1,32 @@ -// generated with @7nohe/openapi-react-query-codegen@2.0.0 -import { type Options } from "@hey-api/client-axios"; +// generated with @7nohe/openapi-react-query-codegen@2.1.0 import { useMutation, UseMutationOptions, useQuery, UseQueryOptions } from "@tanstack/react-query"; import { AxiosError } from "axios"; -import { createToken, createTokenAllAdmins, createTokenCli, loginAllAdmins } from "../requests/services.gen"; +import type { Options } from "../requests/sdk.gen"; +import { createToken, createTokenAllAdmins, createTokenCli, loginAllAdmins } from "../requests/sdk.gen"; import { + CreateTokenAllAdminsData, CreateTokenAllAdminsError, CreateTokenCliData, CreateTokenCliError, CreateTokenData, CreateTokenError, + LoginAllAdminsData, + LoginAllAdminsError, } from "../requests/types.gen"; import * as Common from "./common"; +/** + * Create Token All Admins + * + * Create a token with no credentials only if ``simple_auth_manager_all_admins`` is True. + */ export const useCreateTokenAllAdmins = < TData = Common.CreateTokenAllAdminsDefaultResponse, TError = AxiosError, TQueryKey extends Array = unknown[], >( - clientOptions: Options = {}, + clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => @@ -28,12 +36,17 @@ export const useCreateTokenAllAdmins = < createTokenAllAdmins({ ...clientOptions }).then((response) => response.data as TData) as TData, ...options, }); +/** + * Login All Admins + * + * Login the user with no credentials. + */ export const useLoginAllAdmins = < TData = Common.LoginAllAdminsDefaultResponse, TError = AxiosError, TQueryKey extends Array = unknown[], >( - clientOptions: Options = {}, + clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => @@ -42,6 +55,11 @@ export const useLoginAllAdmins = < queryFn: () => loginAllAdmins({ ...clientOptions }).then((response) => response.data as TData) as TData, ...options, }); +/** + * Create Token + * + * Authenticate the user. + */ export const useCreateToken = < TData = Common.CreateTokenMutationResult, TError = AxiosError, @@ -59,6 +77,11 @@ export const useCreateToken = < mutationFn: (clientOptions) => createToken(clientOptions) as unknown as Promise, ...options, }); +/** + * Create Token Cli + * + * Authenticate the user for the CLI. + */ export const useCreateTokenCli = < TData = Common.CreateTokenCliMutationResult, TError = AxiosError, diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/suspense.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/suspense.ts index 91f54777bf147..f34840b44965b 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/suspense.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/queries/suspense.ts @@ -1,18 +1,28 @@ -// generated with @7nohe/openapi-react-query-codegen@2.0.0 -import { type Options } from "@hey-api/client-axios"; +// generated with @7nohe/openapi-react-query-codegen@2.1.0 import { useSuspenseQuery, UseSuspenseQueryOptions } from "@tanstack/react-query"; import { AxiosError } from "axios"; -import { createTokenAllAdmins, loginAllAdmins } from "../requests/services.gen"; -import { CreateTokenAllAdminsError } from "../requests/types.gen"; +import type { Options } from "../requests/sdk.gen"; +import { createTokenAllAdmins, loginAllAdmins } from "../requests/sdk.gen"; +import { + CreateTokenAllAdminsData, + CreateTokenAllAdminsError, + LoginAllAdminsData, + LoginAllAdminsError, +} from "../requests/types.gen"; import * as Common from "./common"; +/** + * Create Token All Admins + * + * Create a token with no credentials only if ``simple_auth_manager_all_admins`` is True. + */ export const useCreateTokenAllAdminsSuspense = < TData = NonNullable, TError = AxiosError, TQueryKey extends Array = unknown[], >( - clientOptions: Options = {}, + clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => @@ -22,12 +32,17 @@ export const useCreateTokenAllAdminsSuspense = < createTokenAllAdmins({ ...clientOptions }).then((response) => response.data as TData) as TData, ...options, }); +/** + * Login All Admins + * + * Login the user with no credentials. + */ export const useLoginAllAdminsSuspense = < TData = NonNullable, TError = AxiosError, TQueryKey extends Array = unknown[], >( - clientOptions: Options = {}, + clientOptions: Options = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client.gen.ts new file mode 100644 index 0000000000000..cab3c70195b3c --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client.gen.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { type ClientOptions, type Config, createClient, createConfig } from './client'; +import type { ClientOptions as ClientOptions2 } from './types.gen'; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = (override?: Config) => Config & T>; + +export const client = createClient(createConfig()); diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/client.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/client.gen.ts new file mode 100644 index 0000000000000..9b3b2fa6a0e1a --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/client.gen.ts @@ -0,0 +1,156 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { AxiosError, AxiosInstance, RawAxiosRequestHeaders } from 'axios'; +import axios from 'axios'; + +import { createSseClient } from '../core/serverSentEvents.gen'; +import type { HttpMethod } from '../core/types.gen'; +import { getValidRequestBody } from '../core/utils.gen'; +import type { Client, Config, RequestOptions } from './types.gen'; +import { buildUrl, createConfig, mergeConfigs, mergeHeaders, setAuthParams } from './utils.gen'; + +export const createClient = (config: Config = {}): Client => { + let _config = mergeConfigs(createConfig(), config); + + let instance: AxiosInstance; + + if (_config.axios && !('Axios' in _config.axios)) { + instance = _config.axios; + } else { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { auth, ...configWithoutAuth } = _config; + instance = axios.create(configWithoutAuth); + } + + const getConfig = (): Config => ({ ..._config }); + + const setConfig = (config: Config): Config => { + _config = mergeConfigs(_config, config); + instance.defaults = { + ...instance.defaults, + ..._config, + // @ts-expect-error + headers: mergeHeaders(instance.defaults.headers, _config.headers), + }; + return getConfig(); + }; + + const beforeRequest = async (options: RequestOptions) => { + const opts = { + ..._config, + ...options, + axios: options.axios ?? _config.axios ?? instance, + headers: mergeHeaders(_config.headers, options.headers), + }; + + if (opts.security) { + await setAuthParams({ + ...opts, + security: opts.security, + }); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.body = opts.bodySerializer(opts.body); + } + + const url = buildUrl(opts); + + return { opts, url }; + }; + + // @ts-expect-error + const request: Client['request'] = async (options) => { + // @ts-expect-error + const { opts, url } = await beforeRequest(options); + try { + // assign Axios here for consistency with fetch + const _axios = opts.axios!; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { auth, ...optsWithoutAuth } = opts; + const response = await _axios({ + ...optsWithoutAuth, + baseURL: '', // the baseURL is already included in `url` + data: getValidRequestBody(opts), + headers: opts.headers as RawAxiosRequestHeaders, + // let `paramsSerializer()` handle query params if it exists + params: opts.paramsSerializer ? opts.query : undefined, + url, + }); + + let { data } = response; + + if (opts.responseType === 'json') { + if (opts.responseValidator) { + await opts.responseValidator(data); + } + + if (opts.responseTransformer) { + data = await opts.responseTransformer(data); + } + } + + return { + ...response, + data: data ?? {}, + }; + } catch (error) { + const e = error as AxiosError; + if (opts.throwOnError) { + throw e; + } + // @ts-expect-error + e.error = e.response?.data ?? {}; + return e; + } + }; + + const makeMethodFn = (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + headers: opts.headers as Record, + method, + serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined, + // @ts-expect-error + signal: opts.signal, + url, + }); + }; + + return { + buildUrl, + connect: makeMethodFn('CONNECT'), + delete: makeMethodFn('DELETE'), + get: makeMethodFn('GET'), + getConfig, + head: makeMethodFn('HEAD'), + instance, + options: makeMethodFn('OPTIONS'), + patch: makeMethodFn('PATCH'), + post: makeMethodFn('POST'), + put: makeMethodFn('PUT'), + request, + setConfig, + sse: { + connect: makeSseFn('CONNECT'), + delete: makeSseFn('DELETE'), + get: makeSseFn('GET'), + head: makeSseFn('HEAD'), + options: makeSseFn('OPTIONS'), + patch: makeSseFn('PATCH'), + post: makeSseFn('POST'), + put: makeSseFn('PUT'), + trace: makeSseFn('TRACE'), + }, + trace: makeMethodFn('TRACE'), + } as Client; +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/index.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/index.ts new file mode 100644 index 0000000000000..7bd7b98807a15 --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/index.ts @@ -0,0 +1,23 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from '../core/auth.gen'; +export type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from '../core/bodySerializer.gen'; +export { buildClientParams } from '../core/params.gen'; +export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen'; +export { createClient } from './client.gen'; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + TDataShape, +} from './types.gen'; +export { createConfig } from './utils.gen'; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/types.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/types.gen.ts new file mode 100644 index 0000000000000..3a6f9244287a3 --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/types.gen.ts @@ -0,0 +1,160 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { + AxiosError, + AxiosInstance, + AxiosRequestHeaders, + AxiosResponse, + AxiosStatic, + CreateAxiosDefaults, +} from 'axios'; + +import type { Auth } from '../core/auth.gen'; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from '../core/serverSentEvents.gen'; +import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen'; + +export interface Config + extends Omit, CoreConfig { + /** + * Axios implementation. You can use this option to provide either an + * `AxiosStatic` or an `AxiosInstance`. + * + * @default axios + */ + axios?: AxiosStatic | AxiosInstance; + /** + * Base URL for all requests made by this client. + */ + baseURL?: T['baseURL']; + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | AxiosRequestHeaders + | Record< + string, + string | number | boolean | (string | number | boolean)[] | null | undefined | unknown + >; + /** + * Throw an error instead of returning it in the response? + * + * @default false + */ + throwOnError?: T['throwOnError']; +} + +export interface RequestOptions< + TData = unknown, + ThrowOnError extends boolean = boolean, + Url extends string = string, +> + extends + Config<{ + throwOnError: ThrowOnError; + }>, + Pick< + ServerSentEventsOptions, + | 'onSseError' + | 'onSseEvent' + | 'sseDefaultRetryDelay' + | 'sseMaxRetryAttempts' + | 'sseMaxRetryDelay' + > { + /** + * Any body that you want to add to your request. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} + */ + body?: unknown; + path?: Record; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ClientOptions { + baseURL?: string; + throwOnError?: boolean; +} + +export type RequestResult< + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = boolean, +> = ThrowOnError extends true + ? Promise ? TData[keyof TData] : TData>> + : Promise< + | (AxiosResponse ? TData[keyof TData] : TData> & { + error: undefined; + }) + | (AxiosError ? TError[keyof TError] : TError> & { + data: undefined; + error: TError extends Record ? TError[keyof TError] : TError; + }) + >; + +type MethodFn = ( + options: Omit, 'method'>, +) => RequestResult; + +type SseFn = ( + options: Omit, 'method'>, +) => Promise>; + +type RequestFn = ( + options: Omit, 'method'> & + Pick>, 'method'>, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: TData & Options, +) => string; + +export type Client = CoreClient & { + instance: AxiosInstance; +}; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, +> = OmitKeys, 'body' | 'path' | 'query' | 'url'> & + ([TData] extends [never] ? unknown : Omit); diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/utils.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/utils.gen.ts new file mode 100644 index 0000000000000..1b4600f76873e --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/client/utils.gen.ts @@ -0,0 +1,208 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from '../core/auth.gen'; +import type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from '../core/pathSerializer.gen'; +import { getUrl } from '../core/utils.gen'; +import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'; + +export const createQuerySerializer = ({ + parameters = {}, + ...args +}: QuerySerializerOptions = {}) => { + const querySerializer = (queryParams: T) => { + const search: string[] = []; + if (queryParams && typeof queryParams === 'object') { + for (const name in queryParams) { + const value = queryParams[name]; + + if (value === undefined || value === null) { + continue; + } + + const options = parameters[name] || args; + + if (Array.isArray(value)) { + const serializedArray = serializeArrayParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: 'form', + value, + ...options.array, + }); + if (serializedArray) search.push(serializedArray); + } else if (typeof value === 'object') { + const serializedObject = serializeObjectParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: 'deepObject', + value: value as Record, + ...options.object, + }); + if (serializedObject) search.push(serializedObject); + } else { + const serializedPrimitive = serializePrimitiveParam({ + allowReserved: options.allowReserved, + name, + value: value as string, + }); + if (serializedPrimitive) search.push(serializedPrimitive); + } + } + } + return search.join('&'); + }; + return querySerializer; +}; + +const checkForExistence = ( + options: Pick & { + headers: Record; + }, + name?: string, +): boolean => { + if (!name) { + return false; + } + if (name in options.headers || options.query?.[name]) { + return true; + } + if ( + 'Cookie' in options.headers && + options.headers['Cookie'] && + typeof options.headers['Cookie'] === 'string' + ) { + return options.headers['Cookie'].includes(`${name}=`); + } + return false; +}; + +export const setAuthParams = async ({ + security, + ...options +}: Pick, 'security'> & + Pick & { + headers: Record; + }) => { + for (const auth of security) { + if (checkForExistence(options, auth.name)) { + continue; + } + const token = await getAuthToken(auth, options.auth); + + if (!token) { + continue; + } + + const name = auth.name ?? 'Authorization'; + + switch (auth.in) { + case 'query': + if (!options.query) { + options.query = {}; + } + options.query[name] = token; + break; + case 'cookie': { + const value = `${name}=${token}`; + if ('Cookie' in options.headers && options.headers['Cookie']) { + options.headers['Cookie'] = `${options.headers['Cookie']}; ${value}`; + } else { + options.headers['Cookie'] = value; + } + break; + } + case 'header': + default: + options.headers[name] = token; + break; + } + } +}; + +export const buildUrl: Client['buildUrl'] = (options) => { + const instanceBaseUrl = options.axios?.defaults?.baseURL; + + const baseUrl = + !!options.baseURL && typeof options.baseURL === 'string' ? options.baseURL : instanceBaseUrl; + + return getUrl({ + baseUrl: baseUrl as string, + path: options.path, + // let `paramsSerializer()` handle query params if it exists + query: !options.paramsSerializer ? options.query : undefined, + querySerializer: + typeof options.querySerializer === 'function' + ? options.querySerializer + : createQuerySerializer(options.querySerializer), + url: options.url, + }); +}; + +export const mergeConfigs = (a: Config, b: Config): Config => { + const config = { ...a, ...b }; + config.headers = mergeHeaders(a.headers, b.headers); + return config; +}; + +/** + * Special Axios headers keywords allowing to set headers by request method. + */ +export const axiosHeadersKeywords = [ + 'common', + 'delete', + 'get', + 'head', + 'patch', + 'post', + 'put', +] as const; + +export const mergeHeaders = ( + ...headers: Array['headers'] | undefined> +): Record => { + const mergedHeaders: Record = {}; + for (const header of headers) { + if (!header || typeof header !== 'object') { + continue; + } + + const iterator = Object.entries(header); + + for (const [key, value] of iterator) { + if ( + axiosHeadersKeywords.includes(key as (typeof axiosHeadersKeywords)[number]) && + typeof value === 'object' + ) { + mergedHeaders[key] = { + ...(mergedHeaders[key] as Record), + ...value, + }; + } else if (value === null) { + delete mergedHeaders[key]; + } else if (Array.isArray(value)) { + for (const v of value) { + // @ts-expect-error + mergedHeaders[key] = [...(mergedHeaders[key] ?? []), v as string]; + } + } else if (value !== undefined) { + // assume object headers are meant to be JSON stringified, i.e. their + // content value in OpenAPI specification is 'application/json' + mergedHeaders[key] = typeof value === 'object' ? JSON.stringify(value) : (value as string); + } + } + } + return mergedHeaders; +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...override, +}); diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiError.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiError.ts deleted file mode 100644 index fc85c6d1888ba..0000000000000 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiError.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { ApiRequestOptions } from "./ApiRequestOptions"; -import type { ApiResult } from "./ApiResult"; - -export class ApiError extends Error { - public readonly url: string; - public readonly status: number; - public readonly statusText: string; - public readonly body: unknown; - public readonly request: ApiRequestOptions; - - constructor(request: ApiRequestOptions, response: ApiResult, message: string) { - super(message); - - this.name = "ApiError"; - this.url = response.url; - this.status = response.status; - this.statusText = response.statusText; - this.body = response.body; - this.request = request; - } -} diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiRequestOptions.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiRequestOptions.ts deleted file mode 100644 index a74f880c89a2f..0000000000000 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiRequestOptions.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type ApiRequestOptions = { - readonly body?: any; - readonly cookies?: Record; - readonly errors?: Record; - readonly formData?: Record | any[] | Blob | File; - readonly headers?: Record; - readonly mediaType?: string; - readonly method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT"; - readonly path?: Record; - readonly query?: Record; - readonly responseHeader?: string; - readonly responseTransformer?: (data: unknown) => Promise; - readonly url: string; -}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiResult.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiResult.ts deleted file mode 100644 index 05040ba816733..0000000000000 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/ApiResult.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type ApiResult = { - readonly body: TData; - readonly ok: boolean; - readonly status: number; - readonly statusText: string; - readonly url: string; -}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/CancelablePromise.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/CancelablePromise.ts deleted file mode 100644 index 0640e989760e4..0000000000000 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/CancelablePromise.ts +++ /dev/null @@ -1,126 +0,0 @@ -export class CancelError extends Error { - constructor(message: string) { - super(message); - this.name = "CancelError"; - } - - public get isCancelled(): boolean { - return true; - } -} - -export interface OnCancel { - readonly isResolved: boolean; - readonly isRejected: boolean; - readonly isCancelled: boolean; - - (cancelHandler: () => void): void; -} - -export class CancelablePromise implements Promise { - private _isResolved: boolean; - private _isRejected: boolean; - private _isCancelled: boolean; - readonly cancelHandlers: (() => void)[]; - readonly promise: Promise; - private _resolve?: (value: T | PromiseLike) => void; - private _reject?: (reason?: unknown) => void; - - constructor( - executor: ( - resolve: (value: T | PromiseLike) => void, - reject: (reason?: unknown) => void, - onCancel: OnCancel, - ) => void, - ) { - this._isResolved = false; - this._isRejected = false; - this._isCancelled = false; - this.cancelHandlers = []; - this.promise = new Promise((resolve, reject) => { - this._resolve = resolve; - this._reject = reject; - - const onResolve = (value: T | PromiseLike): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { - return; - } - this._isResolved = true; - if (this._resolve) this._resolve(value); - }; - - const onReject = (reason?: unknown): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { - return; - } - this._isRejected = true; - if (this._reject) this._reject(reason); - }; - - const onCancel = (cancelHandler: () => void): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { - return; - } - this.cancelHandlers.push(cancelHandler); - }; - - Object.defineProperty(onCancel, "isResolved", { - get: (): boolean => this._isResolved, - }); - - Object.defineProperty(onCancel, "isRejected", { - get: (): boolean => this._isRejected, - }); - - Object.defineProperty(onCancel, "isCancelled", { - get: (): boolean => this._isCancelled, - }); - - return executor(onResolve, onReject, onCancel as OnCancel); - }); - } - - get [Symbol.toStringTag]() { - return "Cancellable Promise"; - } - - public then( - onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, - onRejected?: ((reason: unknown) => TResult2 | PromiseLike) | null, - ): Promise { - return this.promise.then(onFulfilled, onRejected); - } - - public catch( - onRejected?: ((reason: unknown) => TResult | PromiseLike) | null, - ): Promise { - return this.promise.catch(onRejected); - } - - public finally(onFinally?: (() => void) | null): Promise { - return this.promise.finally(onFinally); - } - - public cancel(): void { - if (this._isResolved || this._isRejected || this._isCancelled) { - return; - } - this._isCancelled = true; - if (this.cancelHandlers.length) { - try { - for (const cancelHandler of this.cancelHandlers) { - cancelHandler(); - } - } catch (error) { - console.warn("Cancellation threw an error", error); - return; - } - } - this.cancelHandlers.length = 0; - if (this._reject) this._reject(new CancelError("Request aborted")); - } - - public get isCancelled(): boolean { - return this._isCancelled; - } -} diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/OpenAPI.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/OpenAPI.ts deleted file mode 100644 index dddf78f069e06..0000000000000 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/OpenAPI.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { AxiosRequestConfig, AxiosResponse } from "axios"; - -import type { ApiRequestOptions } from "./ApiRequestOptions"; - -type Headers = Record; -type Middleware = (value: T) => T | Promise; -type Resolver = (options: ApiRequestOptions) => Promise; - -export class Interceptors { - _fns: Middleware[]; - - constructor() { - this._fns = []; - } - - eject(fn: Middleware): void { - const index = this._fns.indexOf(fn); - if (index !== -1) { - this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)]; - } - } - - use(fn: Middleware): void { - this._fns = [...this._fns, fn]; - } -} - -export type OpenAPIConfig = { - BASE: string; - CREDENTIALS: "include" | "omit" | "same-origin"; - ENCODE_PATH?: ((path: string) => string) | undefined; - HEADERS?: Headers | Resolver | undefined; - PASSWORD?: string | Resolver | undefined; - TOKEN?: string | Resolver | undefined; - USERNAME?: string | Resolver | undefined; - VERSION: string; - WITH_CREDENTIALS: boolean; - interceptors: { - request: Interceptors; - response: Interceptors; - }; -}; - -export const OpenAPI: OpenAPIConfig = { - BASE: "", - CREDENTIALS: "include", - ENCODE_PATH: undefined, - HEADERS: undefined, - PASSWORD: undefined, - TOKEN: undefined, - USERNAME: undefined, - VERSION: "0.1.0", - WITH_CREDENTIALS: false, - interceptors: { - request: new Interceptors(), - response: new Interceptors(), - }, -}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/auth.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/auth.gen.ts new file mode 100644 index 0000000000000..3ebf9947883f3 --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/auth.gen.ts @@ -0,0 +1,41 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type AuthToken = string | undefined; + +export interface Auth { + /** + * Which part of the request do we use to send the auth? + * + * @default 'header' + */ + in?: 'header' | 'query' | 'cookie'; + /** + * Header or query parameter name. + * + * @default 'Authorization' + */ + name?: string; + scheme?: 'basic' | 'bearer'; + type: 'apiKey' | 'http'; +} + +export const getAuthToken = async ( + auth: Auth, + callback: ((auth: Auth) => Promise | AuthToken) | AuthToken, +): Promise => { + const token = typeof callback === 'function' ? await callback(auth) : callback; + + if (!token) { + return; + } + + if (auth.scheme === 'bearer') { + return `Bearer ${token}`; + } + + if (auth.scheme === 'basic') { + return `Basic ${btoa(token)}`; + } + + return token; +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/bodySerializer.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/bodySerializer.gen.ts new file mode 100644 index 0000000000000..8ad92c9ffd6ac --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/bodySerializer.gen.ts @@ -0,0 +1,84 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerializer.gen'; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: any) => any; + +type QuerySerializerOptionsObject = { + allowReserved?: boolean; + array?: Partial>; + object?: Partial>; +}; + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record; +}; + +const serializeFormDataPair = (data: FormData, key: string, value: unknown): void => { + if (typeof value === 'string' || value instanceof Blob) { + data.append(key, value); + } else if (value instanceof Date) { + data.append(key, value.toISOString()); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => { + if (typeof value === 'string') { + data.append(key, value); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +export const formDataBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): FormData => { + const data = new FormData(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeFormDataPair(data, key, v)); + } else { + serializeFormDataPair(data, key, value); + } + }); + + return data; + }, +}; + +export const jsonBodySerializer = { + bodySerializer: (body: T): string => + JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: | Array>>(body: T): string => { + const data = new URLSearchParams(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)); + } else { + serializeUrlSearchParamsPair(data, key, value); + } + }); + + return data.toString(); + }, +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/params.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/params.gen.ts new file mode 100644 index 0000000000000..6099cab1b428e --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/params.gen.ts @@ -0,0 +1,169 @@ +// This file is auto-generated by @hey-api/openapi-ts + +type Slot = 'body' | 'headers' | 'path' | 'query'; + +export type Field = + | { + in: Exclude; + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If omitted, we use the same value as `key`. + */ + map?: string; + } + | { + in: Extract; + /** + * Key isn't required for bodies. + */ + key?: string; + map?: string; + } + | { + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If `in` is omitted, `map` aliases `key` to the transport layer. + */ + map: Slot; + }; + +export interface Fields { + allowExtra?: Partial>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $body_: 'body', + $headers_: 'headers', + $path_: 'path', + $query_: 'query', +}; +const extraPrefixes = Object.entries(extraPrefixesMap); + +type KeyMap = Map< + string, + | { + in: Slot; + map?: string; + } + | { + in?: never; + map: Slot; + } +>; + +const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { + if (!map) { + map = new Map(); + } + + for (const config of fields) { + if ('in' in config) { + if (config.key) { + map.set(config.key, { + in: config.in, + map: config.map, + }); + } + } else if ('key' in config) { + map.set(config.key, { + map: config.map, + }); + } else if (config.args) { + buildKeyMap(config.args, map); + } + } + + return map; +}; + +interface Params { + body: unknown; + headers: Record; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === 'object' && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = (args: ReadonlyArray, fields: FieldsConfig) => { + const params: Params = { + body: {}, + headers: {}, + path: {}, + query: {}, + }; + + const map = buildKeyMap(fields); + + let config: FieldsConfig[number] | undefined; + + for (const [index, arg] of args.entries()) { + if (fields[index]) { + config = fields[index]; + } + + if (!config) { + continue; + } + + if ('in' in config) { + if (config.key) { + const field = map.get(config.key)!; + const name = field.map || config.key; + if (field.in) { + (params[field.in] as Record)[name] = arg; + } + } else { + params.body = arg; + } + } else { + for (const [key, value] of Object.entries(arg ?? {})) { + const field = map.get(key); + + if (field) { + if (field.in) { + const name = field.map || key; + (params[field.in] as Record)[name] = value; + } else { + params[field.map] = value; + } + } else { + const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix)); + + if (extra) { + const [prefix, slot] = extra; + (params[slot] as Record)[key.slice(prefix.length)] = value; + } else if ('allowExtra' in config && config.allowExtra) { + for (const [slot, allowed] of Object.entries(config.allowExtra)) { + if (allowed) { + (params[slot as Slot] as Record)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/pathSerializer.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/pathSerializer.gen.ts new file mode 100644 index 0000000000000..994b2848c63f0 --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/pathSerializer.gen.ts @@ -0,0 +1,171 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions extends SerializePrimitiveOptions, SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @default true + */ + explode: boolean; + style: T; +} + +export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; +export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; +type MatrixStyle = 'label' | 'matrix' | 'simple'; +export type ObjectStyle = 'form' | 'deepObject'; +type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; + +interface SerializePrimitiveParam extends SerializePrimitiveOptions { + value: string; +} + +export const separatorArrayExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case 'label': + return '.'; + case 'matrix': + return ';'; + case 'simple': + return ','; + default: + return '&'; + } +}; + +export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case 'form': + return ','; + case 'pipeDelimited': + return '|'; + case 'spaceDelimited': + return '%20'; + default: + return ','; + } +}; + +export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { + switch (style) { + case 'label': + return '.'; + case 'matrix': + return ';'; + case 'simple': + return ','; + default: + return '&'; + } +}; + +export const serializeArrayParam = ({ + allowReserved, + explode, + name, + style, + value, +}: SerializeOptions & { + value: unknown[]; +}) => { + if (!explode) { + const joinedValues = ( + allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) + ).join(separatorArrayNoExplode(style)); + switch (style) { + case 'label': + return `.${joinedValues}`; + case 'matrix': + return `;${name}=${joinedValues}`; + case 'simple': + return joinedValues; + default: + return `${name}=${joinedValues}`; + } + } + + const separator = separatorArrayExplode(style); + const joinedValues = value + .map((v) => { + if (style === 'label' || style === 'simple') { + return allowReserved ? v : encodeURIComponent(v as string); + } + + return serializePrimitiveParam({ + allowReserved, + name, + value: v as string, + }); + }) + .join(separator); + return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues; +}; + +export const serializePrimitiveParam = ({ + allowReserved, + name, + value, +}: SerializePrimitiveParam) => { + if (value === undefined || value === null) { + return ''; + } + + if (typeof value === 'object') { + throw new Error( + 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.', + ); + } + + return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; +}; + +export const serializeObjectParam = ({ + allowReserved, + explode, + name, + style, + value, + valueOnly, +}: SerializeOptions & { + value: Record | Date; + valueOnly?: boolean; +}) => { + if (value instanceof Date) { + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; + } + + if (style !== 'deepObject' && !explode) { + let values: string[] = []; + Object.entries(value).forEach(([key, v]) => { + values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)]; + }); + const joinedValues = values.join(','); + switch (style) { + case 'form': + return `${name}=${joinedValues}`; + case 'label': + return `.${joinedValues}`; + case 'matrix': + return `;${name}=${joinedValues}`; + default: + return joinedValues; + } + } + + const separator = separatorObjectExplode(style); + const joinedValues = Object.entries(value) + .map(([key, v]) => + serializePrimitiveParam({ + allowReserved, + name: style === 'deepObject' ? `${name}[${key}]` : key, + value: v as string, + }), + ) + .join(separator); + return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues; +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/queryKeySerializer.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/queryKeySerializer.gen.ts new file mode 100644 index 0000000000000..5000df606f37c --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/queryKeySerializer.gen.ts @@ -0,0 +1,117 @@ +// This file is auto-generated by @hey-api/openapi-ts + +/** + * JSON-friendly union that mirrors what Pinia Colada can hash. + */ +export type JsonValue = + | null + | string + | number + | boolean + | JsonValue[] + | { [key: string]: JsonValue }; + +/** + * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes. + */ +export const queryKeyJsonReplacer = (_key: string, value: unknown) => { + if (value === undefined || typeof value === 'function' || typeof value === 'symbol') { + return undefined; + } + if (typeof value === 'bigint') { + return value.toString(); + } + if (value instanceof Date) { + return value.toISOString(); + } + return value; +}; + +/** + * Safely stringifies a value and parses it back into a JsonValue. + */ +export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => { + try { + const json = JSON.stringify(input, queryKeyJsonReplacer); + if (json === undefined) { + return undefined; + } + return JSON.parse(json) as JsonValue; + } catch { + return undefined; + } +}; + +/** + * Detects plain objects (including objects with a null prototype). + */ +const isPlainObject = (value: unknown): value is Record => { + if (value === null || typeof value !== 'object') { + return false; + } + const prototype = Object.getPrototypeOf(value as object); + return prototype === Object.prototype || prototype === null; +}; + +/** + * Turns URLSearchParams into a sorted JSON object for deterministic keys. + */ +const serializeSearchParams = (params: URLSearchParams): JsonValue => { + const entries = Array.from(params.entries()).sort(([a], [b]) => a.localeCompare(b)); + const result: Record = {}; + + for (const [key, value] of entries) { + const existing = result[key]; + if (existing === undefined) { + result[key] = value; + continue; + } + + if (Array.isArray(existing)) { + (existing as string[]).push(value); + } else { + result[key] = [existing, value]; + } + } + + return result; +}; + +/** + * Normalizes any accepted value into a JSON-friendly shape for query keys. + */ +export const serializeQueryKeyValue = (value: unknown): JsonValue | undefined => { + if (value === null) { + return null; + } + + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return value; + } + + if (value === undefined || typeof value === 'function' || typeof value === 'symbol') { + return undefined; + } + + if (typeof value === 'bigint') { + return value.toString(); + } + + if (value instanceof Date) { + return value.toISOString(); + } + + if (Array.isArray(value)) { + return stringifyToJsonValue(value); + } + + if (typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams) { + return serializeSearchParams(value); + } + + if (isPlainObject(value)) { + return stringifyToJsonValue(value); + } + + return undefined; +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/request.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/request.ts deleted file mode 100644 index 319b8c47df5ad..0000000000000 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/request.ts +++ /dev/null @@ -1,374 +0,0 @@ -import axios from "axios"; -import type { AxiosError, AxiosRequestConfig, AxiosResponse, AxiosInstance } from "axios"; - -import { ApiError } from "./ApiError"; -import type { ApiRequestOptions } from "./ApiRequestOptions"; -import type { ApiResult } from "./ApiResult"; -import { CancelablePromise } from "./CancelablePromise"; -import type { OnCancel } from "./CancelablePromise"; -import type { OpenAPIConfig } from "./OpenAPI"; - -export const isString = (value: unknown): value is string => { - return typeof value === "string"; -}; - -export const isStringWithValue = (value: unknown): value is string => { - return isString(value) && value !== ""; -}; - -export const isBlob = (value: any): value is Blob => { - return value instanceof Blob; -}; - -export const isFormData = (value: unknown): value is FormData => { - return value instanceof FormData; -}; - -export const isSuccess = (status: number): boolean => { - return status >= 200 && status < 300; -}; - -export const base64 = (str: string): string => { - try { - return btoa(str); - } catch (err) { - // @ts-ignore - return Buffer.from(str).toString("base64"); - } -}; - -export const getQueryString = (params: Record): string => { - const qs: string[] = []; - - const append = (key: string, value: unknown) => { - qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); - }; - - const encodePair = (key: string, value: unknown) => { - if (value === undefined || value === null) { - return; - } - - if (value instanceof Date) { - append(key, value.toISOString()); - } else if (Array.isArray(value)) { - value.forEach((v) => encodePair(key, v)); - } else if (typeof value === "object") { - Object.entries(value).forEach(([k, v]) => encodePair(`${key}[${k}]`, v)); - } else { - append(key, value); - } - }; - - Object.entries(params).forEach(([key, value]) => encodePair(key, value)); - - return qs.length ? `?${qs.join("&")}` : ""; -}; - -const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { - const encoder = config.ENCODE_PATH || encodeURI; - - const path = options.url - .replace("{api-version}", config.VERSION) - .replace(/{(.*?)}/g, (substring: string, group: string) => { - if (options.path?.hasOwnProperty(group)) { - return encoder(String(options.path[group])); - } - return substring; - }); - - const url = config.BASE + path; - return options.query ? url + getQueryString(options.query) : url; -}; - -export const getFormData = (options: ApiRequestOptions): FormData | undefined => { - if (options.formData) { - const formData = new FormData(); - - const process = (key: string, value: unknown) => { - if (isString(value) || isBlob(value)) { - formData.append(key, value); - } else { - formData.append(key, JSON.stringify(value)); - } - }; - - Object.entries(options.formData) - .filter(([, value]) => value !== undefined && value !== null) - .forEach(([key, value]) => { - if (Array.isArray(value)) { - value.forEach((v) => process(key, v)); - } else { - process(key, value); - } - }); - - return formData; - } - return undefined; -}; - -type Resolver = (options: ApiRequestOptions) => Promise; - -export const resolve = async ( - options: ApiRequestOptions, - resolver?: T | Resolver, -): Promise => { - if (typeof resolver === "function") { - return (resolver as Resolver)(options); - } - return resolver; -}; - -export const getHeaders = async ( - config: OpenAPIConfig, - options: ApiRequestOptions, -): Promise> => { - const [token, username, password, additionalHeaders] = await Promise.all([ - // @ts-ignore - resolve(options, config.TOKEN), - // @ts-ignore - resolve(options, config.USERNAME), - // @ts-ignore - resolve(options, config.PASSWORD), - // @ts-ignore - resolve(options, config.HEADERS), - ]); - - const headers = Object.entries({ - Accept: "application/json", - ...additionalHeaders, - ...options.headers, - }) - .filter(([, value]) => value !== undefined && value !== null) - .reduce( - (headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), - {} as Record, - ); - - if (isStringWithValue(token)) { - headers["Authorization"] = `Bearer ${token}`; - } - - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers["Authorization"] = `Basic ${credentials}`; - } - - if (options.body !== undefined) { - if (options.mediaType) { - headers["Content-Type"] = options.mediaType; - } else if (isBlob(options.body)) { - headers["Content-Type"] = options.body.type || "application/octet-stream"; - } else if (isString(options.body)) { - headers["Content-Type"] = "text/plain"; - } else if (!isFormData(options.body)) { - headers["Content-Type"] = "application/json"; - } - } else if (options.formData !== undefined) { - if (options.mediaType) { - headers["Content-Type"] = options.mediaType; - } - } - - return headers; -}; - -export const getRequestBody = (options: ApiRequestOptions): unknown => { - if (options.body) { - return options.body; - } - return undefined; -}; - -export const sendRequest = async ( - config: OpenAPIConfig, - options: ApiRequestOptions, - url: string, - body: unknown, - formData: FormData | undefined, - headers: Record, - onCancel: OnCancel, - axiosClient: AxiosInstance, -): Promise> => { - const controller = new AbortController(); - - let requestConfig: AxiosRequestConfig = { - data: body ?? formData, - headers, - method: options.method, - signal: controller.signal, - url, - withCredentials: config.WITH_CREDENTIALS, - }; - - onCancel(() => controller.abort()); - - for (const fn of config.interceptors.request._fns) { - requestConfig = await fn(requestConfig); - } - - try { - return await axiosClient.request(requestConfig); - } catch (error) { - const axiosError = error as AxiosError; - if (axiosError.response) { - return axiosError.response; - } - throw error; - } -}; - -export const getResponseHeader = ( - response: AxiosResponse, - responseHeader?: string, -): string | undefined => { - if (responseHeader) { - const content = response.headers[responseHeader]; - if (isString(content)) { - return content; - } - } - return undefined; -}; - -export const getResponseBody = (response: AxiosResponse): unknown => { - if (response.status !== 204) { - return response.data; - } - return undefined; -}; - -export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { - const errors: Record = { - 400: "Bad Request", - 401: "Unauthorized", - 402: "Payment Required", - 403: "Forbidden", - 404: "Not Found", - 405: "Method Not Allowed", - 406: "Not Acceptable", - 407: "Proxy Authentication Required", - 408: "Request Timeout", - 409: "Conflict", - 410: "Gone", - 411: "Length Required", - 412: "Precondition Failed", - 413: "Payload Too Large", - 414: "URI Too Long", - 415: "Unsupported Media Type", - 416: "Range Not Satisfiable", - 417: "Expectation Failed", - 418: "Im a teapot", - 421: "Misdirected Request", - 422: "Unprocessable Content", - 423: "Locked", - 424: "Failed Dependency", - 425: "Too Early", - 426: "Upgrade Required", - 428: "Precondition Required", - 429: "Too Many Requests", - 431: "Request Header Fields Too Large", - 451: "Unavailable For Legal Reasons", - 500: "Internal Server Error", - 501: "Not Implemented", - 502: "Bad Gateway", - 503: "Service Unavailable", - 504: "Gateway Timeout", - 505: "HTTP Version Not Supported", - 506: "Variant Also Negotiates", - 507: "Insufficient Storage", - 508: "Loop Detected", - 510: "Not Extended", - 511: "Network Authentication Required", - ...options.errors, - }; - - const error = errors[result.status]; - if (error) { - throw new ApiError(options, result, error); - } - - if (!result.ok) { - const errorStatus = result.status ?? "unknown"; - const errorStatusText = result.statusText ?? "unknown"; - const errorBody = (() => { - try { - return JSON.stringify(result.body, null, 2); - } catch (e) { - return undefined; - } - })(); - - throw new ApiError( - options, - result, - `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}`, - ); - } -}; - -/** - * Request method - * @param config The OpenAPI configuration object - * @param options The request options from the service - * @param axiosClient The axios client instance to use - * @returns CancelablePromise - * @throws ApiError - */ -export const request = ( - config: OpenAPIConfig, - options: ApiRequestOptions, - axiosClient: AxiosInstance = axios, -): CancelablePromise => { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(config, options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(config, options); - - if (!onCancel.isCancelled) { - let response = await sendRequest( - config, - options, - url, - body, - formData, - headers, - onCancel, - axiosClient, - ); - - for (const fn of config.interceptors.response._fns) { - response = await fn(response); - } - - const responseBody = getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); - - let transformedBody = responseBody; - if (options.responseTransformer && isSuccess(response.status)) { - transformedBody = await options.responseTransformer(responseBody); - } - - const result: ApiResult = { - url, - ok: isSuccess(response.status), - status: response.status, - statusText: response.statusText, - body: responseHeader ?? transformedBody, - }; - - catchErrorCodes(options, result); - - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); -}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/serverSentEvents.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/serverSentEvents.gen.ts new file mode 100644 index 0000000000000..6aa6cf02a4f40 --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/serverSentEvents.gen.ts @@ -0,0 +1,243 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from './types.gen'; + +export type ServerSentEventsOptions = Omit & + Pick & { + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch; + /** + * Implementing clients can call request interceptors inside this hook. + */ + onRequest?: (url: string, init: RequestInit) => Promise; + /** + * Callback invoked when a network or parsing error occurs during streaming. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param error The error that occurred. + */ + onSseError?: (error: unknown) => void; + /** + * Callback invoked when an event is streamed from the server. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param event Event streamed from the server. + * @returns Nothing (void). + */ + onSseEvent?: (event: StreamEvent) => void; + serializedBody?: RequestInit['body']; + /** + * Default retry delay in milliseconds. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 3000 + */ + sseDefaultRetryDelay?: number; + /** + * Maximum number of retry attempts before giving up. + */ + sseMaxRetryAttempts?: number; + /** + * Maximum retry delay in milliseconds. + * + * Applies only when exponential backoff is used. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 30000 + */ + sseMaxRetryDelay?: number; + /** + * Optional sleep function for retry backoff. + * + * Defaults to using `setTimeout`. + */ + sseSleepFn?: (ms: number) => Promise; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export const createSseClient = ({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult => { + let lastEventId: string | undefined; + + const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms))); + + const createStream = async function* () { + let retryDelay: number = sseDefaultRetryDelay ?? 3000; + let attempt = 0; + const signal = options.signal ?? new AbortController().signal; + + while (true) { + if (signal.aborted) break; + + attempt++; + + const headers = + options.headers instanceof Headers + ? options.headers + : new Headers(options.headers as Record | undefined); + + if (lastEventId !== undefined) { + headers.set('Last-Event-ID', lastEventId); + } + + try { + const requestInit: RequestInit = { + redirect: 'follow', + ...options, + body: options.serializedBody, + headers, + signal, + }; + let request = new Request(url, requestInit); + if (onRequest) { + request = await onRequest(url, requestInit); + } + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = options.fetch ?? globalThis.fetch; + const response = await _fetch(request); + + if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`); + + if (!response.body) throw new Error('No body in SSE response'); + + const reader = response.body.pipeThrough(new TextDecoderStream()).getReader(); + + let buffer = ''; + + const abortHandler = () => { + try { + reader.cancel(); + } catch { + // noop + } + }; + + signal.addEventListener('abort', abortHandler); + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + buffer += value; + // Normalize line endings: CRLF -> LF, then CR -> LF + buffer = buffer.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); + + const chunks = buffer.split('\n\n'); + buffer = chunks.pop() ?? ''; + + for (const chunk of chunks) { + const lines = chunk.split('\n'); + const dataLines: Array = []; + let eventName: string | undefined; + + for (const line of lines) { + if (line.startsWith('data:')) { + dataLines.push(line.replace(/^data:\s*/, '')); + } else if (line.startsWith('event:')) { + eventName = line.replace(/^event:\s*/, ''); + } else if (line.startsWith('id:')) { + lastEventId = line.replace(/^id:\s*/, ''); + } else if (line.startsWith('retry:')) { + const parsed = Number.parseInt(line.replace(/^retry:\s*/, ''), 10); + if (!Number.isNaN(parsed)) { + retryDelay = parsed; + } + } + } + + let data: unknown; + let parsedJson = false; + + if (dataLines.length) { + const rawData = dataLines.join('\n'); + try { + data = JSON.parse(rawData); + parsedJson = true; + } catch { + data = rawData; + } + } + + if (parsedJson) { + if (responseValidator) { + await responseValidator(data); + } + + if (responseTransformer) { + data = await responseTransformer(data); + } + } + + onSseEvent?.({ + data, + event: eventName, + id: lastEventId, + retry: retryDelay, + }); + + if (dataLines.length) { + yield data as any; + } + } + } + } finally { + signal.removeEventListener('abort', abortHandler); + reader.releaseLock(); + } + + break; // exit loop on normal completion + } catch (error) { + // connection failed or aborted; retry after delay + onSseError?.(error); + + if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) { + break; // stop after firing error + } + + // exponential backoff: double retry each attempt, cap at 30s + const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000); + await sleep(backoff); + } + } + }; + + const stream = createStream(); + + return { stream }; +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/types.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/types.gen.ts new file mode 100644 index 0000000000000..97463257e43ec --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/types.gen.ts @@ -0,0 +1,104 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from './auth.gen'; +import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen'; + +export type HttpMethod = + | 'connect' + | 'delete' + | 'get' + | 'head' + | 'options' + | 'patch' + | 'post' + | 'put' + | 'trace'; + +export type Client< + RequestFn = never, + Config = unknown, + MethodFn = never, + BuildUrlFn = never, + SseFn = never, +> = { + /** + * Returns the final request URL. + */ + buildUrl: BuildUrlFn; + getConfig: () => Config; + request: RequestFn; + setConfig: (config: Config) => Config; +} & { + [K in HttpMethod]: MethodFn; +} & ([SseFn] extends [never] ? { sse?: never } : { sse: { [K in HttpMethod]: SseFn } }); + +export interface Config { + /** + * Auth token or a function returning auth token. The resolved value will be + * added to the request payload as defined by its `security` array. + */ + auth?: ((auth: Auth) => Promise | AuthToken) | AuthToken; + /** + * A function for serializing request body parameter. By default, + * {@link JSON.stringify()} will be used. + */ + bodySerializer?: BodySerializer | null; + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | RequestInit['headers'] + | Record< + string, + string | number | boolean | (string | number | boolean)[] | null | undefined | unknown + >; + /** + * The request method. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} + */ + method?: Uppercase; + /** + * A function for serializing request query parameters. By default, arrays + * will be exploded in form style, objects will be exploded in deepObject + * style, and reserved characters are percent-encoded. + * + * This method will have no effect if the native `paramsSerializer()` Axios + * API function is used. + * + * {@link https://swagger.io/docs/specification/serialization/#query View examples} + */ + querySerializer?: QuerySerializer | QuerySerializerOptions; + /** + * A function validating request data. This is useful if you want to ensure + * the request conforms to the desired shape, so it can be safely sent to + * the server. + */ + requestValidator?: (data: unknown) => Promise; + /** + * A function transforming response data before it's returned. This is useful + * for post-processing data, e.g. converting ISO strings into Date objects. + */ + responseTransformer?: (data: unknown) => Promise; + /** + * A function validating response data. This is useful if you want to ensure + * the response conforms to the desired shape, so it can be safely passed to + * the transformers and returned to the user. + */ + responseValidator?: (data: unknown) => Promise; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true ? never : K]: T[K]; +}; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/utils.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/utils.gen.ts new file mode 100644 index 0000000000000..e7ddbe3541176 --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/core/utils.gen.ts @@ -0,0 +1,140 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from './bodySerializer.gen'; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from './pathSerializer.gen'; + +export interface PathSerializer { + path: Record; + url: string; +} + +export const PATH_PARAM_RE = /\{[^{}]+\}/g; + +export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { + let url = _url; + const matches = _url.match(PATH_PARAM_RE); + if (matches) { + for (const match of matches) { + let explode = false; + let name = match.substring(1, match.length - 1); + let style: ArraySeparatorStyle = 'simple'; + + if (name.endsWith('*')) { + explode = true; + name = name.substring(0, name.length - 1); + } + + if (name.startsWith('.')) { + name = name.substring(1); + style = 'label'; + } else if (name.startsWith(';')) { + name = name.substring(1); + style = 'matrix'; + } + + const value = path[name]; + + if (value === undefined || value === null) { + continue; + } + + if (Array.isArray(value)) { + url = url.replace(match, serializeArrayParam({ explode, name, style, value })); + continue; + } + + if (typeof value === 'object') { + url = url.replace( + match, + serializeObjectParam({ + explode, + name, + style, + value: value as Record, + valueOnly: true, + }), + ); + continue; + } + + if (style === 'matrix') { + url = url.replace( + match, + `;${serializePrimitiveParam({ + name, + value: value as string, + })}`, + ); + continue; + } + + const replaceValue = encodeURIComponent( + style === 'label' ? `.${value as string}` : (value as string), + ); + url = url.replace(match, replaceValue); + } + } + return url; +}; + +export const getUrl = ({ + baseUrl, + path, + query, + querySerializer, + url: _url, +}: { + baseUrl?: string; + path?: Record; + query?: Record; + querySerializer: QuerySerializer; + url: string; +}) => { + const pathUrl = _url.startsWith('/') ? _url : `/${_url}`; + let url = (baseUrl ?? '') + pathUrl; + if (path) { + url = defaultPathSerializer({ path, url }); + } + let search = query ? querySerializer(query) : ''; + if (search.startsWith('?')) { + search = search.substring(1); + } + if (search) { + url += `?${search}`; + } + return url; +}; + +export function getValidRequestBody(options: { + body?: unknown; + bodySerializer?: BodySerializer | null; + serializedBody?: unknown; +}) { + const hasBody = options.body !== undefined; + const isSerializedBody = hasBody && options.bodySerializer; + + if (isSerializedBody) { + if ('serializedBody' in options) { + const hasSerializedBody = + options.serializedBody !== undefined && options.serializedBody !== ''; + + return hasSerializedBody ? options.serializedBody : null; + } + + // not all clients implement a serializedBody property (i.e. client-axios) + return options.body !== '' ? options.body : null; + } + + // plain/text body + if (hasBody) { + return options.body; + } + + // no body was provided + return undefined; +} diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/index.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/index.ts index 1cb041de5c9d7..4d874426a858c 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/index.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export * from "./schemas.gen"; -export * from "./services.gen"; -export * from "./types.gen"; + +export { createToken, createTokenAllAdmins, createTokenCli, loginAllAdmins, type Options } from './sdk.gen'; +export type { ClientOptions, CreateTokenAllAdminsData, CreateTokenAllAdminsError, CreateTokenAllAdminsErrors, CreateTokenAllAdminsResponse, CreateTokenAllAdminsResponses, CreateTokenCliData, CreateTokenCliError, CreateTokenCliErrors, CreateTokenCliResponse, CreateTokenCliResponses, CreateTokenData, CreateTokenError, CreateTokenErrors, CreateTokenResponse, CreateTokenResponses, HttpExceptionResponse, HttpValidationError, LoginAllAdminsData, LoginAllAdminsError, LoginAllAdminsErrors, LoginBody, LoginResponse, ValidationError } from './types.gen'; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/schemas.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/schemas.gen.ts index a95410436ad2f..25b02375ff846 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/schemas.gen.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/schemas.gen.ts @@ -1,104 +1,115 @@ // This file is auto-generated by @hey-api/openapi-ts export const HTTPExceptionResponseSchema = { - properties: { - detail: { - anyOf: [ - { - type: "string", - }, - { - additionalProperties: true, - type: "object", - }, - ], - title: "Detail", + properties: { + detail: { + anyOf: [ + { + type: 'string' + }, + { + additionalProperties: true, + type: 'object' + } + ], + title: 'Detail' + } }, - }, - type: "object", - required: ["detail"], - title: "HTTPExceptionResponse", - description: "HTTPException Model used for error response.", + type: 'object', + required: [ + 'detail' + ], + title: 'HTTPExceptionResponse', + description: 'HTTPException Model used for error response.' } as const; export const HTTPValidationErrorSchema = { - properties: { - detail: { - items: { - $ref: "#/components/schemas/ValidationError", - }, - type: "array", - title: "Detail", + properties: { + detail: { + items: { + $ref: '#/components/schemas/ValidationError' + }, + type: 'array', + title: 'Detail' + } }, - }, - type: "object", - title: "HTTPValidationError", + type: 'object', + title: 'HTTPValidationError' } as const; export const LoginBodySchema = { - properties: { - username: { - type: "string", - title: "Username", - }, - password: { - type: "string", - title: "Password", + properties: { + username: { + type: 'string', + title: 'Username' + }, + password: { + type: 'string', + title: 'Password' + } }, - }, - additionalProperties: false, - type: "object", - required: ["username", "password"], - title: "LoginBody", - description: "Login serializer for post bodies.", + additionalProperties: false, + type: 'object', + required: [ + 'username', + 'password' + ], + title: 'LoginBody', + description: 'Login serializer for post bodies.' } as const; export const LoginResponseSchema = { - properties: { - access_token: { - type: "string", - title: "Access Token", + properties: { + access_token: { + type: 'string', + title: 'Access Token' + } }, - }, - type: "object", - required: ["access_token"], - title: "LoginResponse", - description: "Login serializer for responses.", + type: 'object', + required: [ + 'access_token' + ], + title: 'LoginResponse', + description: 'Login serializer for responses.' } as const; export const ValidationErrorSchema = { - properties: { - loc: { - items: { - anyOf: [ - { - type: "string", - }, - { - type: "integer", - }, - ], - }, - type: "array", - title: "Location", - }, - msg: { - type: "string", - title: "Message", - }, - type: { - type: "string", - title: "Error Type", - }, - input: { - title: "Input", - }, - ctx: { - type: "object", - title: "Context", + properties: { + loc: { + items: { + anyOf: [ + { + type: 'string' + }, + { + type: 'integer' + } + ] + }, + type: 'array', + title: 'Location' + }, + msg: { + type: 'string', + title: 'Message' + }, + type: { + type: 'string', + title: 'Error Type' + }, + input: { + title: 'Input' + }, + ctx: { + type: 'object', + title: 'Context' + } }, - }, - type: "object", - required: ["loc", "msg", "type"], - title: "ValidationError", + type: 'object', + required: [ + 'loc', + 'msg', + 'type' + ], + title: 'ValidationError' } as const; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/sdk.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/sdk.gen.ts new file mode 100644 index 0000000000000..d34e29be6ae19 --- /dev/null +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/sdk.gen.ts @@ -0,0 +1,67 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Client, Options as Options2, TDataShape } from './client'; +import { client } from './client.gen'; +import type { CreateTokenAllAdminsData, CreateTokenAllAdminsErrors, CreateTokenAllAdminsResponses, CreateTokenCliData, CreateTokenCliErrors, CreateTokenCliResponses, CreateTokenData, CreateTokenErrors, CreateTokenResponses, LoginAllAdminsData, LoginAllAdminsErrors } from './types.gen'; + +export type Options = Options2 & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; + +/** + * Create Token All Admins + * + * Create a token with no credentials only if ``simple_auth_manager_all_admins`` is True. + */ +export const createTokenAllAdmins = (options?: Options) => (options?.client ?? client).get({ + responseType: 'json', + url: '/auth/token', + ...options +}); + +/** + * Create Token + * + * Authenticate the user. + */ +export const createToken = (options: Options) => (options.client ?? client).post({ + responseType: 'json', + url: '/auth/token', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + +/** + * Login All Admins + * + * Login the user with no credentials. + */ +export const loginAllAdmins = (options?: Options) => (options?.client ?? client).get({ url: '/auth/token/login', ...options }); + +/** + * Create Token Cli + * + * Authenticate the user for the CLI. + */ +export const createTokenCli = (options: Options) => (options.client ?? client).post({ + responseType: 'json', + url: '/auth/token/cli', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/services.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/services.gen.ts index 24bf06e54870f..fbae39c7afb60 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/services.gen.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/services.gen.ts @@ -1,71 +1,3 @@ -// This file is auto-generated by @hey-api/openapi-ts -import { createClient, createConfig, type Options } from "@hey-api/client-axios"; - -import type { - CreateTokenData, - CreateTokenError, - CreateTokenResponse, - CreateTokenAllAdminsError, - CreateTokenAllAdminsResponse, - CreateTokenCliData, - CreateTokenCliError, - CreateTokenCliResponse, -} from "./types.gen"; - -export const client = createClient(createConfig()); - -/** - * Create Token - * Authenticate the user. - */ -export const createToken = ( - options: Options, -) => { - return (options?.client ?? client).post({ - ...options, - url: "/auth/token", - }); -}; - -/** - * Create Token All Admins - * Create a token with no credentials only if ``simple_auth_manager_all_admins`` is True. - */ -export const createTokenAllAdmins = ( - options?: Options, -) => { - return (options?.client ?? client).get< - CreateTokenAllAdminsResponse, - CreateTokenAllAdminsError, - ThrowOnError - >({ - ...options, - url: "/auth/token", - }); -}; - -/** - * Login All Admins - * Login the user with no credentials. - */ -export const loginAllAdmins = ( - options?: Options, -) => { - return (options?.client ?? client).get({ - ...options, - url: "/auth/token/login", - }); -}; - -/** - * Create Token Cli - * Authenticate the user for the CLI. - */ -export const createTokenCli = ( - options: Options, -) => { - return (options?.client ?? client).post({ - ...options, - url: "/auth/token/cli", - }); -}; +// This file is auto-generated for backward compatibility +export * from './client.gen.js'; +export * from './sdk.gen.js'; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/types.gen.ts index 81e0f48ffbcc6..2497945807ab1 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/openapi-gen/requests/types.gen.ts @@ -1,67 +1,204 @@ // This file is auto-generated by @hey-api/openapi-ts +export type ClientOptions = { + baseURL: `${string}://${string}` | (string & {}); +}; + /** + * HTTPExceptionResponse + * * HTTPException Model used for error response. */ -export type HTTPExceptionResponse = { - detail: - | string - | { +export type HttpExceptionResponse = { + /** + * Detail + */ + detail: string | { [key: string]: unknown; - }; + }; }; -export type HTTPValidationError = { - detail?: Array; +/** + * HTTPValidationError + */ +export type HttpValidationError = { + /** + * Detail + */ + detail?: Array; }; /** + * LoginBody + * * Login serializer for post bodies. */ export type LoginBody = { - username: string; - password: string; + /** + * Username + */ + username: string; + /** + * Password + */ + password: string; }; /** + * LoginResponse + * * Login serializer for responses. */ export type LoginResponse = { - access_token: string; + /** + * Access Token + */ + access_token: string; }; +/** + * ValidationError + */ export type ValidationError = { - loc: Array; - msg: string; - type: string; - input?: unknown; - ctx?: { - [key: string]: unknown; - }; + /** + * Location + */ + loc: Array; + /** + * Message + */ + msg: string; + /** + * Error Type + */ + type: string; + /** + * Input + */ + input?: unknown; + /** + * Context + */ + ctx?: { + [key: string]: unknown; + }; +}; + +export type CreateTokenAllAdminsData = { + body?: never; + path?: never; + query?: never; + url: '/auth/token'; +}; + +export type CreateTokenAllAdminsErrors = { + /** + * Forbidden + */ + 403: HttpExceptionResponse; +}; + +export type CreateTokenAllAdminsError = CreateTokenAllAdminsErrors[keyof CreateTokenAllAdminsErrors]; + +export type CreateTokenAllAdminsResponses = { + /** + * Successful Response + */ + 201: LoginResponse; }; +export type CreateTokenAllAdminsResponse = CreateTokenAllAdminsResponses[keyof CreateTokenAllAdminsResponses]; + export type CreateTokenData = { - body: LoginBody; - headers?: { + body: LoginBody; + headers?: { + /** + * Content-Type + * + * Content-Type of the request body + */ + 'Content-Type'?: 'application/json' | 'application/x-www-form-urlencoded'; + }; + path?: never; + query?: never; + url: '/auth/token'; +}; + +export type CreateTokenErrors = { + /** + * Bad Request + */ + 400: HttpExceptionResponse; + /** + * Unauthorized + */ + 401: HttpExceptionResponse; + /** + * Unsupported Media Type + */ + 415: HttpExceptionResponse; + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateTokenError = CreateTokenErrors[keyof CreateTokenErrors]; + +export type CreateTokenResponses = { /** - * Content-Type of the request body + * Successful Response */ - "Content-Type"?: "application/json" | "application/x-www-form-urlencoded"; - }; + 201: LoginResponse; }; -export type CreateTokenResponse = LoginResponse; +export type CreateTokenResponse = CreateTokenResponses[keyof CreateTokenResponses]; -export type CreateTokenError = HTTPExceptionResponse | HTTPValidationError; +export type LoginAllAdminsData = { + body?: never; + path?: never; + query?: never; + url: '/auth/token/login'; +}; -export type CreateTokenAllAdminsResponse = LoginResponse; +export type LoginAllAdminsErrors = { + /** + * Forbidden + */ + 403: HttpExceptionResponse; +}; -export type CreateTokenAllAdminsError = HTTPExceptionResponse; +export type LoginAllAdminsError = LoginAllAdminsErrors[keyof LoginAllAdminsErrors]; export type CreateTokenCliData = { - body: LoginBody; + body: LoginBody; + path?: never; + query?: never; + url: '/auth/token/cli'; }; -export type CreateTokenCliResponse = LoginResponse; +export type CreateTokenCliErrors = { + /** + * Bad Request + */ + 400: HttpExceptionResponse; + /** + * Unauthorized + */ + 401: HttpExceptionResponse; + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateTokenCliError = CreateTokenCliErrors[keyof CreateTokenCliErrors]; + +export type CreateTokenCliResponses = { + /** + * Successful Response + */ + 201: LoginResponse; +}; -export type CreateTokenCliError = HTTPExceptionResponse | HTTPValidationError; +export type CreateTokenCliResponse = CreateTokenCliResponses[keyof CreateTokenCliResponses]; diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts index 3220e25aab3e1..dc3bdc9ba6ee9 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts @@ -17,19 +17,18 @@ * under the License. */ import { QueryClient } from "@tanstack/react-query"; - -import { OpenAPI } from "openapi/requests/core/OpenAPI"; import { client } from "openapi/requests/services.gen"; // Dynamically set the base URL for XHR requests based on the meta tag. -OpenAPI.BASE = document.querySelector("head>base")?.getAttribute("href") ?? ""; -if (OpenAPI.BASE.endsWith("/")) { - OpenAPI.BASE = OpenAPI.BASE.slice(0, -1); +let base = document.querySelector("head>base")?.getAttribute("href") ?? ""; + +if (base.endsWith("/")) { + base = base.slice(0, -1); } // Configure the generated API client so requests include the subpath prefix // when Airflow runs behind a reverse proxy (e.g. /team-a/auth/token instead of /auth/token). -client.setConfig({ baseURL: OpenAPI.BASE, throwOnError: true }); +client.setConfig({ baseURL: base, throwOnError: true }); export const queryClient = new QueryClient({ defaultOptions: {